Skip to content

Commit f29dea5

Browse files
committed
Lens appears on face
1 parent 36aceb1 commit f29dea5

File tree

6 files changed

+226
-20
lines changed

6 files changed

+226
-20
lines changed

src/main/java/corundum/rubinated_nether/client/RubinatedNetherClient.java

+39-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,53 @@
11
package corundum.rubinated_nether.client;
22

3+
import corundum.rubinated_nether.client.particles.RubyAuraParticle;
4+
import corundum.rubinated_nether.client.render.entity.RubyLensModel;
5+
import corundum.rubinated_nether.client.render.entity.RubyLensRenderLayer;
6+
import corundum.rubinated_nether.content.RNParticleTypes;
7+
import corundum.rubinated_nether.mixin.accessors.EntityRenderDispatcherAccessor;
8+
import net.minecraft.client.model.HeadedModel;
9+
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
10+
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
11+
import net.minecraft.client.resources.PlayerSkin.Model;
312
import net.neoforged.api.distmarker.Dist;
413
import net.neoforged.api.distmarker.OnlyIn;
514
import net.neoforged.bus.api.IEventBus;
15+
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
616
import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent;
717

8-
import corundum.rubinated_nether.client.particles.RubyAuraParticle;
9-
import corundum.rubinated_nether.content.RNParticleTypes;
10-
1118
@OnlyIn(Dist.CLIENT)
1219
public class RubinatedNetherClient {
1320
public static void client(IEventBus bussin) {
1421
bussin.addListener(RubinatedNetherClient::registerParticleProviders);
22+
bussin.addListener(RubinatedNetherClient::registerEntityLayers);
23+
bussin.addListener(RubinatedNetherClient::registeModelLayers);
24+
}
25+
26+
public static void registeModelLayers(EntityRenderersEvent.RegisterLayerDefinitions event) {
27+
event.registerLayerDefinition(
28+
RubyLensModel.LAYER_LOCATION,
29+
RubyLensModel::createBodyLayer
30+
);
31+
}
32+
33+
@SuppressWarnings({ "unchecked", "rawtypes" })
34+
public static void registerEntityLayers(EntityRenderersEvent.AddLayers event) {
35+
var dispatcher = event.getContext().getEntityRenderDispatcher();
36+
var renderers = ((EntityRenderDispatcherAccessor)dispatcher).getRenderers();
37+
var models = event.getEntityModels();
38+
39+
renderers.forEach((type, renderer) -> {
40+
if(renderer instanceof LivingEntityRenderer<?,?> livingRenderer && livingRenderer.getModel() instanceof HeadedModel) {
41+
livingRenderer.addLayer(new RubyLensRenderLayer(livingRenderer, models, livingRenderer.getModel()));
42+
}
43+
});
44+
45+
((EntityRenderDispatcherAccessor)dispatcher).setRenderers(renderers);
46+
47+
PlayerRenderer defaultSkin = event.getSkin(Model.WIDE);
48+
PlayerRenderer slimSkin = event.getSkin(Model.SLIM);
49+
defaultSkin.addLayer(new RubyLensRenderLayer<>(defaultSkin, models, defaultSkin.getModel()));
50+
slimSkin.addLayer(new RubyLensRenderLayer<>(slimSkin, models, slimSkin.getModel()));
1551
}
1652

1753
public static void registerParticleProviders(RegisterParticleProvidersEvent event) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Made with Blockbench 4.10.3
2+
// Exported for Minecraft version 1.17 or later with Mojang mappings
3+
// Paste this class into your mod and generate all required imports
4+
package corundum.rubinated_nether.client.render.entity;
5+
6+
import com.mojang.blaze3d.vertex.PoseStack;
7+
import com.mojang.blaze3d.vertex.VertexConsumer;
8+
9+
import corundum.rubinated_nether.RubinatedNether;
10+
import net.minecraft.client.model.EntityModel;
11+
import net.minecraft.client.model.geom.ModelLayerLocation;
12+
import net.minecraft.client.model.geom.ModelPart;
13+
import net.minecraft.client.model.geom.PartPose;
14+
import net.minecraft.client.model.geom.builders.CubeDeformation;
15+
import net.minecraft.client.model.geom.builders.CubeListBuilder;
16+
import net.minecraft.client.model.geom.builders.LayerDefinition;
17+
import net.minecraft.client.model.geom.builders.MeshDefinition;
18+
import net.minecraft.client.model.geom.builders.PartDefinition;
19+
import net.minecraft.world.entity.Entity;
20+
21+
public class RubyLensModel<T extends Entity> extends EntityModel<T> {
22+
// This layer location should be baked with EntityRendererProvider.Context in the entity renderer and passed into this model's constructor
23+
public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation(RubinatedNether.id("wearable/ruby_lens"), "main");
24+
private final ModelPart head;
25+
26+
public RubyLensModel(ModelPart root) {
27+
this.head = root.getChild("head");
28+
}
29+
30+
public static LayerDefinition createBodyLayer() {
31+
MeshDefinition meshdefinition = new MeshDefinition();
32+
PartDefinition partdefinition = meshdefinition.getRoot();
33+
34+
partdefinition.addOrReplaceChild("head", CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new CubeDeformation(0.0F))
35+
.texOffs(0, 3).addBox(-4.0F, -6.0F, -6.0F, 3.0F, 3.0F, 2.0F, new CubeDeformation(0.0F))
36+
.texOffs(0, 3).addBox(1.0F, -6.0F, -6.0F, 3.0F, 3.0F, 2.0F, new CubeDeformation(0.0F))
37+
.texOffs(24, 4).addBox(-4.0F, -6.0F, -6.0F, 3.0F, 3.0F, 1.0F, new CubeDeformation(0.2F))
38+
.texOffs(24, 4).addBox(1.0F, -6.0F, -6.0F, 3.0F, 3.0F, 1.0F, new CubeDeformation(0.2F)), PartPose.offset(0.0F, 24.0F, 0.0F));
39+
40+
return LayerDefinition.create(meshdefinition, 32, 16);
41+
}
42+
43+
public void copyHeadData(ModelPart head) {
44+
this.head.copyFrom(head);
45+
}
46+
47+
@Override
48+
public void setupAnim(
49+
Entity entity,
50+
float limbSwing,
51+
float limbSwingAmount,
52+
float ageInTicks,
53+
float netHeadYaw,
54+
float headPitch
55+
) {}
56+
57+
@Override
58+
public void renderToBuffer(
59+
PoseStack poseStack,
60+
VertexConsumer buffer,
61+
int packedLight,
62+
int packedOverlay,
63+
int color
64+
) {
65+
head.render(
66+
poseStack,
67+
buffer,
68+
packedLight,
69+
packedOverlay,
70+
color
71+
);
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package corundum.rubinated_nether.client.render.entity;
2+
3+
import com.mojang.blaze3d.vertex.PoseStack;
4+
5+
import corundum.rubinated_nether.RubinatedNether;
6+
import corundum.rubinated_nether.content.RNItems;
7+
import net.minecraft.client.model.EntityModel;
8+
import net.minecraft.client.model.HeadedModel;
9+
import net.minecraft.client.model.geom.EntityModelSet;
10+
import net.minecraft.client.renderer.MultiBufferSource;
11+
import net.minecraft.client.renderer.entity.RenderLayerParent;
12+
import net.minecraft.client.renderer.entity.layers.RenderLayer;
13+
import net.minecraft.client.renderer.texture.OverlayTexture;
14+
import net.minecraft.resources.ResourceLocation;
15+
import net.minecraft.world.entity.EquipmentSlot;
16+
import net.minecraft.world.entity.LivingEntity;
17+
18+
public class RubyLensRenderLayer<T extends LivingEntity, M extends EntityModel<T> & HeadedModel> extends RenderLayer<T, M> {
19+
20+
public static final ResourceLocation RUBY_LENS_TEXTURE = RubinatedNether.id("textures/models/wearable/ruby_lens.png");
21+
22+
private final M baseModel;
23+
private final RubyLensModel<T> lensModel;
24+
25+
public RubyLensRenderLayer(RenderLayerParent<T, M> renderer, EntityModelSet models, M baseModel) {
26+
super(renderer);
27+
this.baseModel = baseModel;
28+
lensModel = new RubyLensModel<>(models.bakeLayer(RubyLensModel.LAYER_LOCATION));
29+
}
30+
31+
@Override
32+
public void render(PoseStack poseStack, MultiBufferSource buffer, int packedLight, LivingEntity livingEntity, float limbSwing, float limbSwingAmount, float partialTick, float ageInTicks, float netHeadYaw, float headPitch) {
33+
if(livingEntity.getItemBySlot(EquipmentSlot.HEAD).is(RNItems.RUBY_LENS.get())) {
34+
lensModel.copyHeadData(baseModel.getHead());
35+
lensModel.renderToBuffer(
36+
poseStack,
37+
buffer.getBuffer(lensModel.renderType(RUBY_LENS_TEXTURE)),
38+
packedLight,
39+
OverlayTexture.NO_OVERLAY,
40+
0xFFFFFFFF
41+
);
42+
}
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package corundum.rubinated_nether.client.render.entity;
2+
3+
import com.mojang.blaze3d.vertex.PoseStack;
4+
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
5+
import net.minecraft.client.model.EntityModel;
6+
import net.minecraft.client.model.HeadedModel;
7+
import net.minecraft.client.renderer.MultiBufferSource;
8+
import net.minecraft.client.renderer.texture.OverlayTexture;
9+
import net.minecraft.world.entity.LivingEntity;
10+
11+
import java.util.Map;
12+
13+
/**
14+
* Used for trinkets and curios
15+
*/
16+
public abstract class RubyLensRenderer {
17+
18+
private final Map<HeadedModel, RubyLensModel<?>> models = new Reference2ReferenceOpenHashMap<>();
19+
20+
protected void renderInternal(EntityModel<? extends LivingEntity> entityModel, PoseStack poseStack, MultiBufferSource multiBufferSource, int light) {
21+
if(entityModel instanceof HeadedModel headed) {
22+
RubyLensModel<?> model = models.computeIfAbsent(headed, $ -> new RubyLensModel<>(RubyLensModel.createBodyLayer().bakeRoot()));
23+
model.copyHeadData(headed.getHead());
24+
model.renderToBuffer(
25+
poseStack,
26+
multiBufferSource.getBuffer(model.renderType(RubyLensRenderLayer.RUBY_LENS_TEXTURE)),
27+
light,
28+
OverlayTexture.NO_OVERLAY,
29+
0xFFFFFFFF
30+
);
31+
}
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package corundum.rubinated_nether.mixin.accessors;
2+
3+
import java.util.Map;
4+
5+
import org.spongepowered.asm.mixin.Mixin;
6+
import org.spongepowered.asm.mixin.gen.Accessor;
7+
8+
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
9+
import net.minecraft.client.renderer.entity.EntityRenderer;
10+
import net.minecraft.world.entity.EntityType;
11+
12+
@Mixin(EntityRenderDispatcher.class)
13+
public interface EntityRenderDispatcherAccessor {
14+
@Accessor("renderers")
15+
public Map<EntityType<?>, EntityRenderer<?>> getRenderers();
16+
17+
@Accessor("renderers")
18+
public void setRenderers(Map<EntityType<?>, EntityRenderer<?>> renderers);
19+
}
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
{
2-
"required": true,
3-
"package": "corundum.rubinated_nether.mixin",
4-
"compatibilityLevel": "JAVA_17",
5-
"minVersion": "0.8",
6-
"mixins": [
7-
"LevelMixin",
8-
"accessors.AbstractFurnaceBlockEntityAccessor",
9-
"accessors.DoublePlantBlockAccessor",
10-
"accessors.LevelAccessor"
11-
],
12-
"injectors": {
13-
"defaultRequire": 1
14-
},
15-
"client": [
16-
"accessors.GuiAccessor"
17-
]
18-
}
2+
"required": true,
3+
"package": "corundum.rubinated_nether.mixin",
4+
"compatibilityLevel": "JAVA_17",
5+
"minVersion": "0.8",
6+
"mixins": [
7+
"LevelMixin",
8+
"accessors.AbstractFurnaceBlockEntityAccessor",
9+
"accessors.EntityRenderDispatcherAccessor",
10+
"accessors.DoublePlantBlockAccessor",
11+
"accessors.LevelAccessor"
12+
],
13+
"injectors": {
14+
"defaultRequire": 1
15+
},
16+
"client": [
17+
"accessors.GuiAccessor"
18+
]
19+
}

0 commit comments

Comments
 (0)