diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/EntityDisguiseRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/EntityDisguiseRenderer.java new file mode 100644 index 00000000..e130258c --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/render/EntityDisguiseRenderer.java @@ -0,0 +1,129 @@ +package com.minelittlepony.unicopia.client.render; + +import org.jetbrains.annotations.Nullable; + +import com.minelittlepony.unicopia.compat.pehkui.PehkUtil; +import com.minelittlepony.unicopia.entity.Living; +import com.minelittlepony.unicopia.entity.behaviour.Disguise; +import com.minelittlepony.unicopia.entity.behaviour.EntityAppearance; +import com.minelittlepony.unicopia.entity.behaviour.FallingBlockBehaviour; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; +import net.minecraft.client.render.entity.LivingEntityRenderer; +import net.minecraft.client.render.entity.model.BipedEntityModel; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; +import net.minecraft.state.property.Properties; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RotationAxis; +import net.minecraft.util.math.Vec3d; + +class EntityDisguiseRenderer { + + private final WorldRenderDelegate delegate; + + public EntityDisguiseRenderer(WorldRenderDelegate delegate) { + this.delegate = delegate; + } + + public boolean render(Living pony, Disguise disguise, + double x, double y, double z, + float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) { + int fireTicks = pony.asEntity().doesRenderOnFire() ? 1 : 0; + disguise.update(pony, false); + + EntityAppearance ve = disguise.getDisguise(); + Entity e = ve.getAppearance(); + + if (e == null) { + return false; + } + + PehkUtil.copyScale(pony.asEntity(), e); + + if (delegate.client.getEntityRenderDispatcher().shouldRenderHitboxes()) { + e.setBoundingBox(pony.asEntity().getBoundingBox()); + } + + render(ve, e, x, y, z, fireTicks, tickDelta, matrices, vertexConsumers, light); + ve.getAttachments().forEach(ee -> { + PehkUtil.copyScale(pony.asEntity(), ee); + Vec3d difference = ee.getPos().subtract(e.getPos()); + render(ve, ee, x + difference.x, y + difference.y, z + difference.z, fireTicks, tickDelta, matrices, vertexConsumers, light); + PehkUtil.clearScale(ee); + }); + + delegate.afterEntityRender(pony, matrices, light); + PehkUtil.clearScale(e); + return true; + } + + private void render(EntityAppearance ve, Entity e, + double x, double y, double z, + int fireTicks, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) { + + if (ve.isAxisAligned() && (x != 0 || y != 0 || z != 0)) { + Vec3d cam = MinecraftClient.getInstance().gameRenderer.getCamera().getPos(); + + x = MathHelper.lerp(tickDelta, e.lastRenderX, e.getX()) - cam.x; + y = MathHelper.lerp(tickDelta, e.lastRenderY, e.getY()) - cam.y; + z = MathHelper.lerp(tickDelta, e.lastRenderZ, e.getZ()) - cam.z; + } + + BlockEntity blockEntity = ve.getBlockEntity(); + + if (blockEntity != null) { + BlockEntityRenderer r = MinecraftClient.getInstance().getBlockEntityRenderDispatcher().get(blockEntity); + if (r != null) { + ((FallingBlockBehaviour.Positioned)blockEntity).setPos(e.getBlockPos()); + blockEntity.setWorld(e.getWorld()); + matrices.push(); + + BlockState state = blockEntity.getCachedState(); + Direction direction = state.contains(Properties.HORIZONTAL_FACING) ? state.get(Properties.HORIZONTAL_FACING) : Direction.UP; + + matrices.translate(x, y, z); + + matrices.multiply(direction.getRotationQuaternion()); + matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(90)); + + matrices.translate(-0.5, 0, -0.5); + + r.render(blockEntity, 1, matrices, vertexConsumers, light, OverlayTexture.DEFAULT_UV); + + matrices.pop(); + blockEntity.setWorld(null); + return; + } + } + + BipedEntityModel model = getBipedModel(e); + + if (model != null) { + model.sneaking = e.isSneaking(); + } + + e.setFireTicks(fireTicks); + delegate.client.getEntityRenderDispatcher().render(e, x, y, z, e.getYaw(), tickDelta, matrices, vertexConsumers, light); + e.setFireTicks(0); + + if (model != null) { + model.sneaking = false; + } + } + + @Nullable + private BipedEntityModel getBipedModel(Entity entity) { + if (delegate.client.getEntityRenderDispatcher().getRenderer(entity) instanceof LivingEntityRenderer livingRenderer + && livingRenderer.getModel() instanceof BipedEntityModel biped) { + return biped; + } + return null; + } + +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementRenderManager.java b/src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementManager.java similarity index 94% rename from src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementRenderManager.java rename to src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementManager.java index ce5713ce..c1a9d8c7 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementRenderManager.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementManager.java @@ -18,9 +18,7 @@ import net.minecraft.entity.EntityType; import net.minecraft.entity.passive.PassiveEntity; import net.minecraft.entity.player.PlayerEntity; -class EntityReplacementRenderManager implements Disguise { - public static final EntityReplacementRenderManager INSTANCE = new EntityReplacementRenderManager(); - +class EntityReplacementManager implements Disguise { @Nullable private EntityType currentType; private final EntityAppearance disguise = new EntityAppearance(); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/SmittenEyesRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/SmittenEyesRenderer.java index 4b5c40d5..2459266a 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/SmittenEyesRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/SmittenEyesRenderer.java @@ -23,8 +23,6 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RotationAxis; public class SmittenEyesRenderer { - public static final SmittenEyesRenderer INSTANCE = new SmittenEyesRenderer(); - private static final Identifier TEXTURE = Unicopia.id("textures/entity/smitten_eyes.png"); private final MinecraftClient client = MinecraftClient.getInstance(); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java b/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java index b0a28a6e..b5e043f2 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java @@ -1,44 +1,41 @@ package com.minelittlepony.unicopia.client.render; -import org.jetbrains.annotations.Nullable; +import java.util.Optional; import com.minelittlepony.client.util.render.RenderLayerUtil; +import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.Unicopia; -import com.minelittlepony.unicopia.compat.pehkui.PehkUtil; import com.minelittlepony.unicopia.entity.Creature; import com.minelittlepony.unicopia.entity.Equine; import com.minelittlepony.unicopia.entity.ItemImpl; import com.minelittlepony.unicopia.entity.Living; -import com.minelittlepony.unicopia.entity.behaviour.EntityAppearance; -import com.minelittlepony.unicopia.entity.behaviour.FallingBlockBehaviour; import com.minelittlepony.unicopia.entity.duck.LavaAffine; import com.minelittlepony.unicopia.entity.player.Pony; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.*; import net.minecraft.client.render.VertexConsumerProvider.Immediate; -import net.minecraft.client.render.block.entity.BlockEntityRenderer; -import net.minecraft.client.render.entity.EntityRenderDispatcher; -import net.minecraft.client.render.entity.LivingEntityRenderer; -import net.minecraft.client.render.entity.model.BipedEntityModel; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.*; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.vehicle.BoatEntity; import net.minecraft.screen.PlayerScreenHandler; -import net.minecraft.state.property.Properties; import net.minecraft.util.Identifier; import net.minecraft.util.math.*; public class WorldRenderDelegate { public static final WorldRenderDelegate INSTANCE = new WorldRenderDelegate(); + private final EntityReplacementManager disguiseLookup = new EntityReplacementManager(); + private final EntityDisguiseRenderer disguiseRenderer = new EntityDisguiseRenderer(this); + private final SmittenEyesRenderer smittenEyesRenderer = new SmittenEyesRenderer(); + private boolean recurseMinion; private boolean recurseFrosting; - public boolean beforeEntityRender(EntityRenderDispatcher dispatcher, Entity entity, + final MinecraftClient client = MinecraftClient.getInstance(); + + public boolean beforeEntityRender(Entity entity, double x, double y, double z, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light) { @@ -47,7 +44,7 @@ public class WorldRenderDelegate { if (MinecraftClient.getInstance().getResourceManager().getResource(frostingTexture).isPresent()) { recurseFrosting = true; - dispatcher.render(entity, x, y, z, yaw, tickDelta, matrices, layer -> { + client.getEntityRenderDispatcher().render(entity, x, y, z, yaw, tickDelta, matrices, layer -> { if (RenderLayerUtil.getTexture(layer).orElse(null) == null) { return vertices.getBuffer(layer); } @@ -62,17 +59,36 @@ public class WorldRenderDelegate { return false; } - return Equine.of(entity).filter(eq -> onEntityRender(dispatcher, eq, x, y, z, yaw, tickDelta, matrices, vertices, light)).isPresent(); + return Equine.of(entity).filter(eq -> onEntityRender(eq, x, y, z, yaw, tickDelta, matrices, vertices, light)).isPresent(); } - public boolean onEntityRender(EntityRenderDispatcher dispatcher, Equine pony, + public void afterEntityRender(Equine pony, MatrixStack matrices, int light) { + if (recurseFrosting) { + return; + } + + if (pony instanceof Creature creature && smittenEyesRenderer.isSmitten(creature)) { + Immediate immediate = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers(); + smittenEyesRenderer.render(creature, matrices, immediate, light, 0); + } + + if (pony instanceof ItemImpl || pony instanceof Living) { + matrices.pop(); + + if (pony instanceof Living && pony.getPhysics().isGravityNegative()) { + flipAngles(pony.asEntity()); + } + } + } + + private boolean onEntityRender(Equine pony, double x, double y, double z, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light) { if (!recurseMinion && pony instanceof Creature creature && creature.isMinion()) { try { recurseMinion = true; - dispatcher.render(creature.asEntity(), x, y, z, yaw, tickDelta, matrices, layer -> { + client.getEntityRenderDispatcher().render(creature.asEntity(), x, y, z, yaw, tickDelta, matrices, layer -> { return RenderLayerUtil.getTexture(layer) .filter(texture -> texture != PlayerScreenHandler.BLOCK_ATLAS_TEXTURE) .map(texture -> { @@ -100,14 +116,14 @@ public class WorldRenderDelegate { return false; } - if (pony instanceof Living) { - return onLivingRender(dispatcher, (Living)pony, x, y, z, yaw, tickDelta, matrices, vertices, light); + if (pony instanceof Living living) { + return onLivingRender(living, x, y, z, yaw, tickDelta, matrices, vertices, light); } return false; } - private boolean onLivingRender(EntityRenderDispatcher dispatcher, Living pony, + private boolean onLivingRender(Living pony, double x, double y, double z, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) { @@ -145,7 +161,7 @@ public class WorldRenderDelegate { matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(diveAngle)); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(yaw)); - } else if (pony instanceof Creature creature && SmittenEyesRenderer.INSTANCE.isSmitten(creature)) { + } else if (pony instanceof Creature creature && smittenEyesRenderer.isSmitten(creature)) { ModelPartHooks.startCollecting(); } @@ -155,117 +171,7 @@ public class WorldRenderDelegate { flipAngles(owner); } - int fireTicks = owner.doesRenderOnFire() ? 1 : 0; - - return EntityReplacementRenderManager.INSTANCE.getAppearanceFor(pony).map(effect -> { - effect.update(pony, false); - - EntityAppearance ve = effect.getDisguise(); - Entity e = ve.getAppearance(); - - if (e != null) { - PehkUtil.copyScale(pony.asEntity(), e); - - if (dispatcher.shouldRenderHitboxes()) { - e.setBoundingBox(pony.asEntity().getBoundingBox()); - } - - renderDisguise(dispatcher, ve, e, x, y, z, fireTicks, tickDelta, matrices, vertexConsumers, light); - ve.getAttachments().forEach(ee -> { - PehkUtil.copyScale(pony.asEntity(), ee); - Vec3d difference = ee.getPos().subtract(e.getPos()); - renderDisguise(dispatcher, ve, ee, x + difference.x, y + difference.y, z + difference.z, fireTicks, tickDelta, matrices, vertexConsumers, light); - PehkUtil.clearScale(ee); - }); - - afterEntityRender(pony, matrices, light); - PehkUtil.clearScale(e); - return true; - } - return false; - }).orElse(false); - } - - public void afterEntityRender(Equine pony, MatrixStack matrices, int light) { - if (recurseFrosting) { - return; - } - - if (pony instanceof Creature creature && SmittenEyesRenderer.INSTANCE.isSmitten(creature)) { - Immediate immediate = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers(); - SmittenEyesRenderer.INSTANCE.render(creature, matrices, immediate, light, 0); - } - - if (pony instanceof ItemImpl || pony instanceof Living) { - matrices.pop(); - - if (pony instanceof Living && pony.getPhysics().isGravityNegative()) { - flipAngles(pony.asEntity()); - } - } - } - - public void renderDisguise(EntityRenderDispatcher dispatcher, EntityAppearance ve, Entity e, - double x, double y, double z, - int fireTicks, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) { - - if (ve.isAxisAligned() && (x != 0 || y != 0 || z != 0)) { - Vec3d cam = MinecraftClient.getInstance().gameRenderer.getCamera().getPos(); - - x = MathHelper.lerp(tickDelta, e.lastRenderX, e.getX()) - cam.x; - y = MathHelper.lerp(tickDelta, e.lastRenderY, e.getY()) - cam.y; - z = MathHelper.lerp(tickDelta, e.lastRenderZ, e.getZ()) - cam.z; - } - - BlockEntity blockEntity = ve.getBlockEntity(); - - if (blockEntity != null) { - BlockEntityRenderer r = MinecraftClient.getInstance().getBlockEntityRenderDispatcher().get(blockEntity); - if (r != null) { - ((FallingBlockBehaviour.Positioned)blockEntity).setPos(e.getBlockPos()); - blockEntity.setWorld(e.getWorld()); - matrices.push(); - - BlockState state = blockEntity.getCachedState(); - Direction direction = state.contains(Properties.HORIZONTAL_FACING) ? state.get(Properties.HORIZONTAL_FACING) : Direction.UP; - - matrices.translate(x, y, z); - - matrices.multiply(direction.getRotationQuaternion()); - matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(90)); - - matrices.translate(-0.5, 0, -0.5); - - r.render(blockEntity, 1, matrices, vertexConsumers, light, OverlayTexture.DEFAULT_UV); - - matrices.pop(); - blockEntity.setWorld(null); - return; - } - } - - BipedEntityModel model = getBipedModel(dispatcher, e); - - if (model != null) { - model.sneaking = e.isSneaking(); - } - - e.setFireTicks(fireTicks); - dispatcher.render(e, x, y, z, e.getYaw(), tickDelta, matrices, vertexConsumers, light); - e.setFireTicks(0); - - if (model != null) { - model.sneaking = false; - } - } - - @Nullable - private BipedEntityModel getBipedModel(EntityRenderDispatcher dispatcher, Entity entity) { - if (dispatcher.getRenderer(entity) instanceof LivingEntityRenderer livingRenderer - && livingRenderer.getModel() instanceof BipedEntityModel biped) { - return biped; - } - return null; + return disguiseLookup.getAppearanceFor(pony).map(effect -> disguiseRenderer.render(pony, effect, x, y, z, tickDelta, matrices, vertexConsumers, light)).orElse(false); } private void flipAngles(Entity entity) { diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinEntityRenderDispatcher.java b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinEntityRenderDispatcher.java index 16289191..b81bb782 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinEntityRenderDispatcher.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinEntityRenderDispatcher.java @@ -20,7 +20,7 @@ abstract class MixinEntityRenderDispatcher { @Inject(method = RENDER, at = @At("HEAD"), cancellable = true) private void beforeRender(E entity, double x, double y, double z, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo info) { - if (WorldRenderDelegate.INSTANCE.beforeEntityRender((EntityRenderDispatcher)(Object)this, entity, x, y, z, yaw, tickDelta, matrices, vertexConsumers, light)) { + if (WorldRenderDelegate.INSTANCE.beforeEntityRender(entity, x, y, z, yaw, tickDelta, matrices, vertexConsumers, light)) { info.cancel(); } }