From 4af11dfd303b05bcb245c29e1076c63992e6562b Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 27 Sep 2020 15:11:50 +0200 Subject: [PATCH] When disguised as doors or beds, make sure to render the entire block --- .../ability/ChangelingDisguiseAbility.java | 4 +- .../ability/magic/spell/DisguiseSpell.java | 6 +- .../client/render/WorldRenderDelegate.java | 86 ++++++++++++------- .../entity/behaviour/BeeBehaviour.java | 5 +- .../{VirtualEntity.java => Disguise.java} | 57 ++++++++++-- .../entity/behaviour/EntityBehaviour.java | 35 +++++--- .../behaviour/FallingBlockBehaviour.java | 58 +++++++++++++ .../entity/behaviour/MinecartBehaviour.java | 5 +- .../unicopia/mixin/MixinLivingEntity.java | 4 +- 9 files changed, 198 insertions(+), 62 deletions(-) rename src/main/java/com/minelittlepony/unicopia/entity/behaviour/{VirtualEntity.java => Disguise.java} (82%) create mode 100644 src/main/java/com/minelittlepony/unicopia/entity/behaviour/FallingBlockBehaviour.java diff --git a/src/main/java/com/minelittlepony/unicopia/ability/ChangelingDisguiseAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/ChangelingDisguiseAbility.java index 65e1c8cc..9ea50379 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/ChangelingDisguiseAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/ChangelingDisguiseAbility.java @@ -5,7 +5,7 @@ import javax.annotation.Nullable; import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell; -import com.minelittlepony.unicopia.entity.behaviour.VirtualEntity; +import com.minelittlepony.unicopia.entity.behaviour.Disguise; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.util.VecHelper; @@ -55,7 +55,7 @@ public class ChangelingDisguiseAbility extends ChangelingFeedAbility { looked = Pony.of((PlayerEntity)looked) .getSpellOrEmpty(DisguiseSpell.class) .map(DisguiseSpell::getDisguise) - .map(VirtualEntity::getAppearance) + .map(Disguise::getAppearance) .orElse(looked); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DisguiseSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DisguiseSpell.java index e10a6c3f..4ebd9c74 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DisguiseSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DisguiseSpell.java @@ -12,7 +12,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Spell; import com.minelittlepony.unicopia.ability.magic.Suppressable; import com.minelittlepony.unicopia.entity.behaviour.EntityBehaviour; -import com.minelittlepony.unicopia.entity.behaviour.VirtualEntity; +import com.minelittlepony.unicopia.entity.behaviour.Disguise; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.particle.UParticles; @@ -26,7 +26,7 @@ import net.minecraft.nbt.CompoundTag; public class DisguiseSpell extends AbstractSpell implements AttachableSpell, Suppressable, FlightPredicate, HeightPredicate { - private final VirtualEntity disguise = new VirtualEntity(); + private final Disguise disguise = new Disguise(); private int suppressionCounter; @@ -66,7 +66,7 @@ public class DisguiseSpell extends AbstractSpell implements AttachableSpell, Sup return suppressionCounter > 0; } - public VirtualEntity getDisguise() { + public Disguise getDisguise() { return disguise; } 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 82d784f4..9c42dfb5 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/WorldRenderDelegate.java @@ -3,12 +3,15 @@ package com.minelittlepony.unicopia.client.render; import javax.annotation.Nullable; import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell; -import com.minelittlepony.unicopia.entity.behaviour.VirtualEntity; +import com.minelittlepony.unicopia.entity.behaviour.Disguise; import com.minelittlepony.unicopia.entity.player.Pony; +import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.client.model.Model; +import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.render.entity.EntityRenderer; import net.minecraft.client.render.entity.LivingEntityRenderer; @@ -49,9 +52,24 @@ public class WorldRenderDelegate { matrices.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(roll)); } - return pony.getSpellOrEmpty(DisguiseSpell.class, true) - .map(effect -> renderDisguise(dispatcher, pony, effect, x, y, z, tickDelta, matrices, vertexConsumers, light)) - .orElse(false); + return pony.getSpellOrEmpty(DisguiseSpell.class, true).map(effect -> { + effect.update(pony, false); + + Disguise ve = effect.getDisguise(); + Entity e = ve.getAppearance(); + + if (e != null) { + renderDisguise(dispatcher, ve, e, x, y, z, tickDelta, matrices, vertexConsumers, light); + ve.getAttachments().forEach(ee -> { + Vec3d difference = ee.getPos().subtract(e.getPos()); + renderDisguise(dispatcher, ve, ee, x + difference.x, y + difference.y, z + difference.z, tickDelta, matrices, vertexConsumers, light); + }); + + afterEntityRender(pony, matrices); + return true; + } + return false; + }).orElse(false); } public void afterEntityRender(Pony pony, MatrixStack matrices) { @@ -63,40 +81,44 @@ public class WorldRenderDelegate { } } - public boolean renderDisguise(EntityRenderDispatcher dispatcher, Pony pony, DisguiseSpell effect, + public void renderDisguise(EntityRenderDispatcher dispatcher, Disguise ve, Entity e, double x, double y, double z, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) { - effect.update(pony, false); - VirtualEntity ve = effect.getDisguise(); - Entity e = ve.getAppearance(); + if (ve.isAxisAligned() && (x != 0 || y != 0 || z != 0)) { + Vec3d cam = MinecraftClient.getInstance().gameRenderer.getCamera().getPos(); - if (e != null) { - 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; - } - - BipedEntityModel model = getBipedModel(dispatcher, e); - - if (model != null) { - model.sneaking = e.isSneaking(); - } - - dispatcher.render(e, x, y, z, e.yaw, tickDelta, matrices, vertexConsumers, light); - - if (model != null) { - model.sneaking = false; - } - - afterEntityRender(pony, matrices); - return true; + 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; } - return false; + BlockEntity blockEntity = ve.getBlockEntity(); + + if (blockEntity != null) { + blockEntity.setPos(e.getBlockPos()); + matrices.push(); + + matrices.translate(x, y, z); + matrices.translate(-0.5, 0, -0.5); + + BlockEntityRenderDispatcher.INSTANCE.get(blockEntity).render(blockEntity, 1, matrices, vertexConsumers, light, OverlayTexture.DEFAULT_UV); + + matrices.pop(); + return; + } + + BipedEntityModel model = getBipedModel(dispatcher, e); + + if (model != null) { + model.sneaking = e.isSneaking(); + } + + dispatcher.render(e, x, y, z, e.yaw, tickDelta, matrices, vertexConsumers, light); + + if (model != null) { + model.sneaking = false; + } } @Nullable diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/BeeBehaviour.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/BeeBehaviour.java index 24790512..2c3c013b 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/BeeBehaviour.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/BeeBehaviour.java @@ -9,13 +9,14 @@ import net.minecraft.entity.passive.BeeEntity; public class BeeBehaviour extends EntityBehaviour { @Override - public void onCreate(BeeEntity entity) { - super.onCreate(entity); + public BeeEntity onCreate(BeeEntity entity, Disguise context) { + super.onCreate(entity, context); if (entity.world.isClient) { MinecraftClient.getInstance().getSoundManager().playNextTick( entity.hasAngerTime() ? new AggressiveBeeSoundInstance(entity) : new PassiveBeeSoundInstance(entity) ); } + return entity; } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/VirtualEntity.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java similarity index 82% rename from src/main/java/com/minelittlepony/unicopia/entity/behaviour/VirtualEntity.java rename to src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java index 9eb256ca..99dd3476 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/VirtualEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java @@ -1,5 +1,7 @@ package com.minelittlepony.unicopia.entity.behaviour; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import javax.annotation.Nonnull; @@ -14,6 +16,7 @@ import com.minelittlepony.unicopia.projectile.ProjectileUtil; import com.minelittlepony.unicopia.util.NbtSerialisable; import com.mojang.authlib.GameProfile; +import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.SkullBlockEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; @@ -30,7 +33,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.ShulkerBulletEntity; import net.minecraft.nbt.CompoundTag; -public class VirtualEntity implements NbtSerialisable { +public class Disguise implements NbtSerialisable { @Nonnull private String entityId = ""; @@ -38,14 +41,39 @@ public class VirtualEntity implements NbtSerialisable { @Nullable private Entity entity; + @Nullable + private BlockEntity blockEntity; + + private List attachments = new ArrayList<>(); + @Nullable private CompoundTag entityNbt; + @Nullable + private CompoundTag blockEntityNbt; + @Nullable public Entity getAppearance() { return entity; } + @Nullable + public BlockEntity getBlockEntity() { + return blockEntity; + } + + public List getAttachments() { + return attachments; + } + + public void addBlockEntity(BlockEntity blockEntity) { + this.blockEntity = blockEntity; + } + + public void attachExtraEntity(Entity entity) { + attachments.add(entity); + } + public void setAppearance(@Nullable Entity entity) { remove(); @@ -58,10 +86,15 @@ public class VirtualEntity implements NbtSerialisable { } public void remove() { + attachments.clear(); if (entity != null) { entity.remove(); entity = null; } + if (blockEntity != null) { + blockEntity.markRemoved(); + blockEntity = null; + } } private synchronized void createPlayer(CompoundTag nbt, GameProfile profile, Caster source) { @@ -80,6 +113,8 @@ public class VirtualEntity implements NbtSerialisable { if (entity == null && entityNbt != null) { CompoundTag nbt = entityNbt; entityNbt = null; + blockEntityNbt = null; + attachments.clear(); if ("player".equals(entityId)) { createPlayer(nbt, new GameProfile( @@ -94,13 +129,11 @@ public class VirtualEntity implements NbtSerialisable { if (source.isClient()) { entity = EntityType.fromTag(nbt).map(type -> type.create(source.getWorld())).orElse(null); if (entity != null) { - EntityBehaviour.forEntity(entity).onCreate(entity); + entity = EntityBehaviour.forEntity(entity).onCreate(entity, this); } } else { entity = EntityType.loadEntityWithPassengers(nbt, source.getWorld(), e -> { - EntityBehaviour.forEntity(e).onCreate(e); - - return e; + return EntityBehaviour.forEntity(e).onCreate(e, this); }); } } @@ -189,6 +222,12 @@ public class VirtualEntity implements NbtSerialisable { } else if (entity != null) { compound.put("entity", encodeEntityToNBT(entity)); } + + if (blockEntityNbt != null) { + compound.put("blockEntity", blockEntityNbt); + } else if (blockEntity != null) { + compound.put("blockEntity", blockEntity.toInitialChunkDataTag()); + } } @Override @@ -197,9 +236,14 @@ public class VirtualEntity implements NbtSerialisable { if (!newId.contentEquals(entityId)) { entityNbt = null; + blockEntityNbt = null; remove(); } + if (compound.contains("blockEntity")) { + blockEntityNbt = compound.getCompound("blockEntityNbt"); + } + if (compound.contains("entity")) { entityId = newId; @@ -213,6 +257,9 @@ public class VirtualEntity implements NbtSerialisable { } catch (Exception ignored) { // Mojang pls } + + attachments.clear(); + entity = EntityBehaviour.forEntity(entity).onCreate(entity, this); } } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityBehaviour.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityBehaviour.java index da9f57fa..419f9724 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityBehaviour.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityBehaviour.java @@ -17,6 +17,7 @@ import net.minecraft.entity.passive.TameableEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.registry.Registry; public class EntityBehaviour { @@ -28,20 +29,25 @@ public class EntityBehaviour { } - public void onCreate(T entity) { + public T onCreate(T entity, Disguise context) { entity.extinguish(); + return entity; } public void copyBaseAttributes(LivingEntity from, Entity to) { + copyBaseAttributes(from, to, Vec3d.ZERO); + } + + public void copyBaseAttributes(LivingEntity from, Entity to, Vec3d positionOffset) { // Set first because position calculations rely on it to.age = from.age; to.removed = from.removed; to.setOnGround(from.isOnGround()); - if (VirtualEntity.isAxisAligned(to)) { - double x = Math.floor(from.getX()) + 0.5; - double y = Math.floor(from.getY()); - double z = Math.floor(from.getZ()) + 0.5; + if (Disguise.isAxisAligned(to)) { + double x = positionOffset.x + Math.floor(from.getX()) + 0.5; + double y = positionOffset.y + Math.floor(from.getY()); + double z = positionOffset.z + Math.floor(from.getZ()) + 0.5; to.prevX = x; to.prevY = y; @@ -59,25 +65,25 @@ public class EntityBehaviour { } else { to.copyPositionAndRotation(from); - to.prevX = from.prevX; - to.prevY = from.prevY; - to.prevZ = from.prevZ; + to.prevX = positionOffset.x + from.prevX; + to.prevY = positionOffset.y + from.prevY; + to.prevZ = positionOffset.z + from.prevZ; to.chunkX = from.chunkX; to.chunkY = from.chunkY; to.chunkZ = from.chunkZ; - to.lastRenderX = from.lastRenderX; - to.lastRenderY = from.lastRenderY; - to.lastRenderZ = from.lastRenderZ; + to.lastRenderX = positionOffset.x + from.lastRenderX; + to.lastRenderY = positionOffset.y + from.lastRenderY; + to.lastRenderZ = positionOffset.z + from.lastRenderZ; } if (to instanceof PlayerEntity) { PlayerEntity l = (PlayerEntity)to; - l.capeX = l.getX(); - l.capeY = l.getY(); - l.capeZ = l.getZ(); + l.capeX = positionOffset.x + l.getX(); + l.capeY = positionOffset.y + l.getY(); + l.capeZ = positionOffset.z + l.getZ(); } to.setVelocity(from.getVelocity()); @@ -174,6 +180,7 @@ public class EntityBehaviour { } static { + register(FallingBlockBehaviour::new, EntityType.FALLING_BLOCK); register(VillagerBehaviour::new, EntityType.VILLAGER, EntityType.WANDERING_TRADER); register(SheepBehaviour::new, EntityType.SHEEP); register(BeeBehaviour::new, EntityType.BEE); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/FallingBlockBehaviour.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/FallingBlockBehaviour.java new file mode 100644 index 00000000..31f3d399 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/FallingBlockBehaviour.java @@ -0,0 +1,58 @@ +package com.minelittlepony.unicopia.entity.behaviour; + +import java.util.List; + +import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.Spell; +import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.DoorBlock; +import net.minecraft.block.enums.DoubleBlockHalf; +import net.minecraft.entity.Entity; +import net.minecraft.entity.FallingBlockEntity; +import net.minecraft.tag.BlockTags; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; + +public class FallingBlockBehaviour extends EntityBehaviour { + + private static final Vec3d UP = Vec3d.of(Direction.UP.getVector()); + + @Override + public FallingBlockEntity onCreate(FallingBlockEntity entity, Disguise context) { + super.onCreate(entity, context); + + BlockState state = entity.getBlockState(); + Block block = state.getBlock(); + if (block == Blocks.SAND) { + block = Blocks.BLACKSTONE; + } + + if (state.isIn(BlockTags.DOORS) && block instanceof DoorBlock) { + BlockState lowerState = state.with(DoorBlock.HALF, DoubleBlockHalf.LOWER); + BlockState upperState = state.with(DoorBlock.HALF, DoubleBlockHalf.UPPER); + + context.attachExtraEntity(new FallingBlockEntity(entity.world, entity.getX(), entity.getY(), entity.getZ(), upperState)); + + return new FallingBlockEntity(entity.world, entity.getX(), entity.getY() + 1, entity.getZ(), lowerState); + } + + if (block instanceof BlockEntityProvider) { + context.addBlockEntity(((BlockEntityProvider)block).createBlockEntity(entity.world)); + } + + return entity; + } + + @Override + public void update(Caster source, FallingBlockEntity entity, Spell spell) { + List attachments = ((DisguiseSpell)spell).getDisguise().getAttachments(); + if (attachments.size() > 0) { + copyBaseAttributes(source.getOwner(), attachments.get(0), UP); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/MinecartBehaviour.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/MinecartBehaviour.java index c6067ce2..b0e71383 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/MinecartBehaviour.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/MinecartBehaviour.java @@ -11,11 +11,12 @@ import net.minecraft.entity.vehicle.AbstractMinecartEntity; public class MinecartBehaviour extends EntityBehaviour { @Override - public void onCreate(AbstractMinecartEntity entity) { - super.onCreate(entity); + public AbstractMinecartEntity onCreate(AbstractMinecartEntity entity, Disguise context) { + super.onCreate(entity, context); if (entity.world.isClient) { MinecraftClient.getInstance().getSoundManager().play(new MovingMinecartSoundInstance(entity)); } + return entity; } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java index d4cb7c77..c64dbfe4 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java @@ -14,7 +14,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell; import com.minelittlepony.unicopia.entity.Creature; import com.minelittlepony.unicopia.entity.PonyContainer; -import com.minelittlepony.unicopia.entity.behaviour.VirtualEntity; +import com.minelittlepony.unicopia.entity.behaviour.Disguise; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.Equine; @@ -51,7 +51,7 @@ abstract class MixinLivingEntity extends Entity implements PonyContainer { climbingPos = Optional.of(getBlockPos()); info.setReturnValue(true);