diff --git a/src/main/java/com/wenxin2/marioverse/MarioverseClient.java b/src/main/java/com/wenxin2/marioverse/MarioverseClient.java index 069609b5..8984c201 100644 --- a/src/main/java/com/wenxin2/marioverse/MarioverseClient.java +++ b/src/main/java/com/wenxin2/marioverse/MarioverseClient.java @@ -6,6 +6,7 @@ import com.wenxin2.marioverse.client.particles.MediumRewardParticle; import com.wenxin2.marioverse.client.particles.NoMovementParticle; import com.wenxin2.marioverse.client.particles.RewardParticle; +import com.wenxin2.marioverse.client.renderers.accesories.ArmorRenderingExtension; import com.wenxin2.marioverse.client.renderers.accesories.OneUpRenderer; import com.wenxin2.marioverse.client.renderers.blocks.CoinBlockEntityRenderer; import com.wenxin2.marioverse.client.renderers.blocks.GoalPoleBlockEntityRenderer; @@ -28,7 +29,6 @@ import com.wenxin2.marioverse.init.MenuRegistry; import com.wenxin2.marioverse.init.ParticleRegistry; import io.wispforest.accessories.api.client.AccessoriesRendererRegistry; -import io.wispforest.accessories.api.client.ArmorRenderingExtension; import net.minecraft.client.particle.SuspendedTownParticle; import net.minecraft.client.renderer.BiomeColors; import net.minecraft.client.renderer.entity.player.PlayerRenderer; diff --git a/src/main/java/com/wenxin2/marioverse/client/renderers/accesories/ArmorRenderingExtension.java b/src/main/java/com/wenxin2/marioverse/client/renderers/accesories/ArmorRenderingExtension.java new file mode 100644 index 00000000..c2ed5517 --- /dev/null +++ b/src/main/java/com/wenxin2/marioverse/client/renderers/accesories/ArmorRenderingExtension.java @@ -0,0 +1,49 @@ +package com.wenxin2.marioverse.client.renderers.accesories; + +import com.mojang.blaze3d.vertex.PoseStack; +import io.wispforest.accessories.api.client.AccessoryRenderer; +import io.wispforest.accessories.api.slot.SlotReference; +import io.wispforest.accessories.mixin.client.LivingEntityRendererAccessor; +import java.util.Optional; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Equipable; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; + +public interface ArmorRenderingExtension> { + AccessoryRenderer RENDERER = new AccessoryRenderer() { + public void render(ItemStack stack, SlotReference reference, PoseStack matrices, EntityModel model, + MultiBufferSource multiBufferSource, int light, float limbSwing, float limbSwingAmount, + float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { + EntityRenderer entityRender = Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(reference.entity()); + if (entityRender instanceof LivingEntityRendererAccessor accessor) { + Item var16 = stack.getItem(); + if (var16 instanceof Equipable equipable) { + EquipmentSlot equipmentSlot = equipable.getEquipmentSlot(); + Optional var17 = accessor.getLayers().stream().filter((renderLayer) -> { + return renderLayer instanceof io.wispforest.accessories.api.client.ArmorRenderingExtension + || renderLayer instanceof ArmorRenderingExtension; + }).findFirst(); + if (model instanceof HumanoidModel humanoidModel) { + var17.ifPresent((layer) -> { + ((ArmorRenderingExtension) layer).renderEquipmentStack(stack, matrices, multiBufferSource, reference.entity(), + equipmentSlot, light, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, humanoidModel); + }); + } + } + } + } + }; + + default void renderEquipmentStack(ItemStack stack, PoseStack poseStack, MultiBufferSource multiBufferSource, T livingEntity, EquipmentSlot equipmentSlot, + int light, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, + float netHeadYaw, float headPitch, A baseModel) { + throw new IllegalStateException("Injected interface method is unimplemented!"); + } +} \ No newline at end of file diff --git a/src/main/java/com/wenxin2/marioverse/mixin/HumanoidArmorLayerMixin.java b/src/main/java/com/wenxin2/marioverse/mixin/HumanoidArmorLayerMixin.java new file mode 100644 index 00000000..20166a73 --- /dev/null +++ b/src/main/java/com/wenxin2/marioverse/mixin/HumanoidArmorLayerMixin.java @@ -0,0 +1,78 @@ +package com.wenxin2.marioverse.mixin; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.blaze3d.vertex.PoseStack; +import com.wenxin2.marioverse.client.renderers.accesories.ArmorRenderingExtension; +import io.wispforest.accessories.AccessoriesLoaderInternals; +import io.wispforest.accessories.compat.GeckoLibCompat; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer; +import net.minecraft.client.renderer.entity.layers.RenderLayer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import software.bernie.geckolib.animatable.client.GeoRenderProvider; +import software.bernie.geckolib.renderer.GeoArmorRenderer; +import software.bernie.geckolib.util.Color; + +@Mixin({HumanoidArmorLayer.class}) +public abstract class HumanoidArmorLayerMixin, + A extends HumanoidModel> extends RenderLayer implements ArmorRenderingExtension { + @Unique + private @Nullable ItemStack tempStack = null; + + public HumanoidArmorLayerMixin(RenderLayerParent renderer) { + super(renderer); + } + + @Shadow + protected abstract void renderArmorPiece(PoseStack var1, MultiBufferSource var2, T var3, EquipmentSlot var4, int var5, A var6, float var7, float var8, float var9, float var10, float var11, float var12); + + @Shadow + private A getArmorModel(EquipmentSlot slot) { + return null; + } + + @Shadow + protected abstract void setPartVisibility(A var1, EquipmentSlot var2); + + public void renderEquipmentStack(ItemStack stack, PoseStack poseStack, MultiBufferSource multiBufferSource, + T livingEntity, EquipmentSlot equipmentSlot, int light, float limbSwing, float limbSwingAmount, + float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, A baseModel) { + this.tempStack = stack; + + HumanoidModel geckolibModel = GeoRenderProvider.of(stack).getGeoArmorRenderer(livingEntity, stack, equipmentSlot, baseModel); + if (geckolibModel instanceof GeoArmorRenderer geoArmorRenderer) { + geoArmorRenderer.prepForRender(livingEntity, stack, equipmentSlot, baseModel, multiBufferSource, partialTicks, limbSwing, limbSwingAmount, netHeadYaw, headPitch); + geoArmorRenderer.renderToBuffer(poseStack, null, + light, OverlayTexture.NO_OVERLAY, Color.WHITE.argbInt()); + baseModel.copyPropertiesTo((A)geckolibModel); + } else this.renderArmorPiece(poseStack, multiBufferSource, livingEntity, equipmentSlot, light, this.getArmorModel(equipmentSlot), limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch); + this.tempStack = null; + } + + @WrapOperation( + method = {"renderArmorPiece(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/entity/EquipmentSlot;ILnet/minecraft/client/model/HumanoidModel;FFFFFF)V"}, + at = {@At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/LivingEntity;getItemBySlot(Lnet/minecraft/world/entity/EquipmentSlot;)Lnet/minecraft/world/item/ItemStack;" + )} + ) + private ItemStack getAlternativeStack(LivingEntity instance, EquipmentSlot equipmentSlot, Operation original) { + return this.tempStack != null ? this.tempStack : (ItemStack)original.call(instance, equipmentSlot); + } + + @Unique + private boolean attemptGeckoRender(ItemStack stack, PoseStack poseStack, MultiBufferSource multiBufferSource, T livingEntity, EquipmentSlot equipmentSlot, int light, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { + return !AccessoriesLoaderInternals.isModLoaded("geckolib") ? false : GeckoLibCompat.renderGeckoArmor(poseStack, multiBufferSource, livingEntity, stack, equipmentSlot, (HumanoidModel)this.getParentModel(), this.getArmorModel(equipmentSlot), partialTicks, light, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, this::setPartVisibility); + } +} diff --git a/src/main/resources/marioverse.mixins.json b/src/main/resources/marioverse.mixins.json index 68abf8ce..0520f18e 100644 --- a/src/main/resources/marioverse.mixins.json +++ b/src/main/resources/marioverse.mixins.json @@ -15,6 +15,7 @@ "TrapDoorBlockMixin" ], "client": [ + "HumanoidArmorLayerMixin", "LivingEntityClientMixin" ], "injectors": {