diff --git a/src/main/java/com/simibubi/create/compat/curios/Curios.java b/src/main/java/com/simibubi/create/compat/curios/Curios.java index 5d55aef84..566677125 100644 --- a/src/main/java/com/simibubi/create/compat/curios/Curios.java +++ b/src/main/java/com/simibubi/create/compat/curios/Curios.java @@ -1,31 +1,43 @@ package com.simibubi.create.compat.curios; +import java.util.concurrent.atomic.AtomicBoolean; + import com.simibubi.create.AllItems; import com.simibubi.create.content.contraptions.goggles.GogglesItem; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.InterModComms; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import top.theillusivec4.curios.api.CuriosCapability; import top.theillusivec4.curios.api.SlotTypeMessage; import top.theillusivec4.curios.api.SlotTypePreset; - -import java.util.concurrent.atomic.AtomicBoolean; +import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler; public class Curios { public static void init() { FMLJavaModLoadingContext.get().getModEventBus().addListener(Curios::onInterModEnqueue); + FMLJavaModLoadingContext.get().getModEventBus().addListener(Curios::onClientSetup); GogglesItem.addIsWearingPredicate(player -> { AtomicBoolean hasGoggles = new AtomicBoolean(false); player.getCapability(CuriosCapability.INVENTORY).ifPresent(handler -> { - hasGoggles.set(handler.getCurios().get("head").getStacks().getStackInSlot(0).getItem() == AllItems.GOGGLES.get()); + ICurioStacksHandler stacksHandler = handler.getCurios().get("head"); + if(stacksHandler != null) hasGoggles.set(stacksHandler.getStacks().getStackInSlot(0).getItem() == AllItems.GOGGLES.get()); }); return hasGoggles.get(); }); + + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FMLJavaModLoadingContext.get().getModEventBus().addListener(CuriosRenderers::onLayerRegister)); } private static void onInterModEnqueue(final InterModEnqueueEvent event) { InterModComms.sendTo("curios", SlotTypeMessage.REGISTER_TYPE, () -> SlotTypePreset.HEAD.getMessageBuilder().build()); } + + private static void onClientSetup(final FMLClientSetupEvent event) { + CuriosRenderers.register(); + } } diff --git a/src/main/java/com/simibubi/create/compat/curios/CuriosRenderers.java b/src/main/java/com/simibubi/create/compat/curios/CuriosRenderers.java new file mode 100644 index 000000000..740d251b0 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/curios/CuriosRenderers.java @@ -0,0 +1,21 @@ +package com.simibubi.create.compat.curios; + +import com.simibubi.create.AllItems; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.EntityRenderersEvent; +import top.theillusivec4.curios.api.client.CuriosRendererRegistry; + +@OnlyIn(Dist.CLIENT) +public class CuriosRenderers { + public static void register() { + CuriosRendererRegistry.register(AllItems.GOGGLES.get(), () -> new GogglesCurioRenderer(Minecraft.getInstance().getEntityModels().bakeLayer(GogglesCurioRenderer.LAYER))); + } + + public static void onLayerRegister(final EntityRenderersEvent.RegisterLayerDefinitions event) { + event.registerLayerDefinition(GogglesCurioRenderer.LAYER, () -> LayerDefinition.create(GogglesCurioRenderer.mesh(), 1, 1)); + } +} diff --git a/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java b/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java new file mode 100644 index 000000000..940822439 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java @@ -0,0 +1,67 @@ +package com.simibubi.create.compat.curios; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Vector3f; +import com.simibubi.create.Create; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import top.theillusivec4.curios.api.SlotContext; +import top.theillusivec4.curios.api.client.ICurioRenderer; + +@OnlyIn(Dist.CLIENT) +public class GogglesCurioRenderer implements ICurioRenderer { + public static final ModelLayerLocation LAYER = new ModelLayerLocation(new ResourceLocation(Create.ID, "goggles"), "goggles"); + + private final HumanoidModel model; + + public GogglesCurioRenderer(ModelPart part) { + this.model = new HumanoidModel<>(part); + } + + @Override + public > void render(ItemStack stack, SlotContext slotContext, PoseStack matrixStack, RenderLayerParent renderLayerParent, MultiBufferSource renderTypeBuffer, int light, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { + // Prepare values for transformation + model.setupAnim(slotContext.entity(), limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); + model.prepareMobModel(slotContext.entity(), limbSwing, limbSwingAmount, partialTicks); + ICurioRenderer.followHeadRotations(slotContext.entity(), model.head); + + // Translate and rotate with our head + matrixStack.pushPose(); + matrixStack.translate(model.head.x / 16.0, model.head.y / 16.0, model.head.z / 16.0); + matrixStack.mulPose(Vector3f.YP.rotation(model.head.yRot)); + matrixStack.mulPose(Vector3f.XP.rotation(model.head.xRot)); + + // Translate and scale to our head + matrixStack.translate(0, -0.25, 0); + matrixStack.mulPose(Vector3f.ZP.rotationDegrees(180.0f)); + matrixStack.scale(0.625f, 0.625f, 0.625f); + + // Render + Minecraft.getInstance().getItemRenderer().renderStatic(stack, ItemTransforms.TransformType.HEAD, light, OverlayTexture.NO_OVERLAY, matrixStack, renderTypeBuffer, 0); + matrixStack.popPose(); + } + + public static MeshDefinition mesh() { + CubeListBuilder builder = new CubeListBuilder(); + MeshDefinition mesh = HumanoidModel.createMesh(CubeDeformation.NONE, 0); + mesh.getRoot().addOrReplaceChild("head", builder, PartPose.ZERO); + return mesh; + } +}