From c02c72cc60c76b082296bd5facdc08b18c1633a3 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 12 Feb 2019 15:25:48 +0200 Subject: [PATCH] A changeling's bounding box and eye height will now match the entity they disguise themselves as --- .../unicopia/mixin/MixinEntity.java | 28 ++++++-- .../unicopia/player/IGravity.java | 2 +- .../player/IPlayerHeightPredicate.java | 12 ++++ .../player/PlayerGravityDelegate.java | 59 +++++++++++++--- .../unicopia/power/PowerDisguise.java | 18 ++++- .../unicopia/spell/SpellDisguise.java | 68 ++++++++++++++++--- 6 files changed, 159 insertions(+), 28 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/player/IPlayerHeightPredicate.java diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntity.java index 9fd4b16b..68f22406 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntity.java @@ -1,6 +1,7 @@ package com.minelittlepony.unicopia.mixin; -import com.google.common.base.Optional; +import java.lang.reflect.Field; + import com.minelittlepony.unicopia.forgebullshit.FUF; import net.minecraft.entity.Entity; @@ -8,7 +9,6 @@ import net.minecraft.entity.MoverType; import net.minecraft.entity.monster.EntityShulker; import net.minecraft.network.datasync.DataParameter; import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; @FUF(reason = "Waiting for mixins?") public interface MixinEntity { @@ -24,8 +24,28 @@ public interface MixinEntity { abstract class Shulker extends EntityShulker { private Shulker() { super(null);} - public static DataParameter> getAttachmentPosFlag() { - return ATTACHED_BLOCK_POS; + private static boolean __init; + private static Field __peekAmount = null; + + public static void setPeek(EntityShulker shulker, float peekAmount) { + initFields(); + + try { + if (__peekAmount != null) { + __peekAmount.set(shulker, peekAmount); + } + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + + } + + private static void initFields() { + if (!__init && __peekAmount == null) { + Field[] fields = EntityShulker.class.getDeclaredFields(); + __peekAmount = fields[fields.length - 3]; + __peekAmount.setAccessible(true); + } } } diff --git a/src/main/java/com/minelittlepony/unicopia/player/IGravity.java b/src/main/java/com/minelittlepony/unicopia/player/IGravity.java index 2305102c..c8cb6ebd 100644 --- a/src/main/java/com/minelittlepony/unicopia/player/IGravity.java +++ b/src/main/java/com/minelittlepony/unicopia/player/IGravity.java @@ -1,6 +1,6 @@ package com.minelittlepony.unicopia.player; -public interface IGravity extends IFlyingPredicate { +public interface IGravity { boolean isFlying(); float getFlightExperience(); diff --git a/src/main/java/com/minelittlepony/unicopia/player/IPlayerHeightPredicate.java b/src/main/java/com/minelittlepony/unicopia/player/IPlayerHeightPredicate.java new file mode 100644 index 00000000..d0abe22b --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/player/IPlayerHeightPredicate.java @@ -0,0 +1,12 @@ +package com.minelittlepony.unicopia.player; + +/** + * Predicate for abilities to control what the player's physical height is. + * + * This overrides the default. + */ +public interface IPlayerHeightPredicate { + float getTargetEyeHeight(IPlayer player); + + float getTargetBodyHeight(IPlayer player); +} diff --git a/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java b/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java index 0c86bbe4..d90c69f3 100644 --- a/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java +++ b/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java @@ -21,7 +21,7 @@ import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; -class PlayerGravityDelegate implements IUpdatable, IGravity, InbtSerialisable { +class PlayerGravityDelegate implements IUpdatable, IGravity, InbtSerialisable, IFlyingPredicate, IPlayerHeightPredicate { private final IPlayer player; @@ -36,6 +36,7 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtS this.player = player; } + @Override public boolean checkCanFly(IPlayer player) { if (player.getOwner().capabilities.isCreativeMode) { return true; @@ -51,6 +52,51 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtS return player.getPlayerSpecies().canFly(); } + protected boolean isRainboom(IPlayer player) { + return Math.sqrt(getHorizontalMotion(player.getOwner())) > 0.4F; + } + + @Override + public float getTargetEyeHeight(IPlayer player) { + if (player.hasEffect()) { + IMagicEffect effect = player.getEffect(); + if (!effect.getDead() && effect instanceof IPlayerHeightPredicate) { + float val = ((IPlayerHeightPredicate)effect).getTargetEyeHeight(player); + if (val > 0) { + return val; + } + } + } + + if (isFlying && isRainboom(player)) { + return 0.5F; + } + + return player.getOwner().getDefaultEyeHeight(); + } + + @Override + public float getTargetBodyHeight(IPlayer player) { + if (player.hasEffect()) { + IMagicEffect effect = player.getEffect(); + if (!effect.getDead() && effect instanceof IPlayerHeightPredicate) { + float val = ((IPlayerHeightPredicate)effect).getTargetBodyHeight(player); + if (val > 0) { + return val; + } + } + } + + // Player height is reset at this point, so we can use it as our baseline. + + if (isFlying && isRainboom(player)) { + return player.getOwner().height / 2; + } + + return player.getOwner().height; + } + + @Override public void onUpdate(EntityPlayer entity) { @@ -62,15 +108,8 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtS isFlying = entity.capabilities.isFlying && !entity.capabilities.isCreativeMode; - boolean rainboom = Math.sqrt(getHorizontalMotion(entity)) > 0.4F; - - if (isFlying && rainboom) { - MixinEntity.setSize(entity, entity.width, player.getInterpolator().interpolate("standingHeight", 0.5F, 10)); - entity.eyeHeight = player.getInterpolator().interpolate("eyeHeight", entity.height / 2, 10); - } else { - MixinEntity.setSize(entity, entity.width, player.getInterpolator().interpolate("standingHeight", entity.height, 10)); - entity.eyeHeight = player.getInterpolator().interpolate("eyeHeight", entity.getDefaultEyeHeight(), 10); - } + MixinEntity.setSize(entity, entity.width, player.getInterpolator().interpolate("standingHeight", getTargetBodyHeight(player), 10)); + entity.eyeHeight = player.getInterpolator().interpolate("eyeHeight", getTargetEyeHeight(player), 10); if (!entity.capabilities.isCreativeMode && !entity.isElytraFlying()) { if (isFlying && !entity.isRiding()) { diff --git a/src/main/java/com/minelittlepony/unicopia/power/PowerDisguise.java b/src/main/java/com/minelittlepony/unicopia/power/PowerDisguise.java index 736c7bba..f22a3ab4 100644 --- a/src/main/java/com/minelittlepony/unicopia/power/PowerDisguise.java +++ b/src/main/java/com/minelittlepony/unicopia/power/PowerDisguise.java @@ -13,10 +13,13 @@ import com.minelittlepony.unicopia.spell.IMagicEffect; import com.minelittlepony.unicopia.spell.SpellDisguise; import com.minelittlepony.util.vector.VecHelper; +import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityFallingBlock; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.RayTraceResult; public class PowerDisguise extends PowerFeed { @@ -39,7 +42,18 @@ public class PowerDisguise extends PowerFeed { @Override public void apply(IPlayer iplayer, Hit data) { EntityPlayer player = iplayer.getOwner(); - Entity looked = VecHelper.getLookedAtEntity(player, 17); + RayTraceResult trace = VecHelper.getObjectMouseOver(player, 10, 1); + Entity looked = null; + + if (trace.typeOfHit == RayTraceResult.Type.BLOCK) { + IBlockState state = player.getEntityWorld().getBlockState(trace.getBlockPos()); + + if (!state.getBlock().isAir(state, player.getEntityWorld(), trace.getBlockPos())) { + looked = new EntityFallingBlock(player.getEntityWorld(), 0, 0, 0, state); + } + } else { + looked = trace.entityHit; + } if (looked instanceof EntityPlayer) { IPlayer ilooked = PlayerSpeciesList.instance().getPlayer((EntityPlayer)looked); @@ -52,7 +66,7 @@ public class PowerDisguise extends PowerFeed { } } - player.world.playSound(null, player.getPosition(), SoundEvents.E_PARROT_IM_POLAR_BEAR, SoundCategory.PLAYERS, 1.4F, 0.4F); + player.getEntityWorld().playSound(null, player.getPosition(), SoundEvents.E_PARROT_IM_POLAR_BEAR, SoundCategory.PLAYERS, 1.4F, 0.4F); IMagicEffect effect = iplayer.getEffect(); if (effect instanceof SpellDisguise && !effect.getDead()) { diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellDisguise.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellDisguise.java index f93060e5..d8a42286 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellDisguise.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellDisguise.java @@ -11,7 +11,9 @@ import com.minelittlepony.unicopia.mixin.MixinEntity; import com.minelittlepony.unicopia.player.IFlyingPredicate; import com.minelittlepony.unicopia.player.IOwned; import com.minelittlepony.unicopia.player.IPlayer; +import com.minelittlepony.unicopia.player.IPlayerHeightPredicate; import com.minelittlepony.unicopia.player.PlayerSpeciesList; +import com.minelittlepony.unicopia.render.DisguiseRenderer; import com.mojang.authlib.GameProfile; import net.minecraft.entity.Entity; @@ -24,13 +26,14 @@ import net.minecraft.entity.item.EntityFallingBlock; import net.minecraft.entity.item.EntityMinecart; import net.minecraft.entity.monster.EntityShulker; import net.minecraft.entity.passive.EntityAmbientCreature; +import net.minecraft.entity.passive.EntityTameable; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntitySkull; -public class SpellDisguise extends AbstractSpell implements IFlyingPredicate { +public class SpellDisguise extends AbstractSpell implements IFlyingPredicate, IPlayerHeightPredicate { @Nonnull private String entityId = ""; @@ -223,15 +226,13 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate { if (l instanceof EntityShulker) { l.rotationYaw = 0; - l.rotationPitch = 0; - l.rotationYawHead = 0; - l.prevRotationYawHead = 0; + l.renderYawOffset = 0; l.prevRenderYawOffset = 0; } } - if (entity instanceof EntityShulker || entity instanceof EntityFallingBlock) { + if (DisguiseRenderer.instance().isAttachedEntity(entity)) { entity.posX = Math.floor(owner.posX) + 0.5; entity.posY = Math.floor(owner.posY + 0.2); @@ -244,9 +245,31 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate { entity.prevPosX = entity.posX; entity.prevPosY = entity.posY; entity.prevPosZ = entity.posZ; + } - if (entity instanceof EntityShulker) { - ((EntityShulker)entity).setAttachmentPos(null); + if (entity instanceof EntityShulker) { + EntityShulker shulker = ((EntityShulker)entity); + + shulker.setAttachmentPos(null); + + if (source.getWorld().isRemote && source instanceof IPlayer) { + IPlayer player = (IPlayer)source; + + + float peekAmount = 0.3F; + + if (!owner.isSneaking()) { + float speed = (float)Math.sqrt(Math.pow(owner.motionX, 2) + Math.pow(owner.motionZ, 2)); + + peekAmount = speed * 30; + if (peekAmount > 1) { + peekAmount = 1; + } + } + + peekAmount = player.getInterpolator().interpolate("peek", peekAmount, 5); + + MixinEntity.Shulker.setPeek(shulker, peekAmount); } } @@ -287,11 +310,13 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate { owner.setInvisible(true); + if (entity instanceof EntityTameable) { + ((EntityTameable)entity).setSitting(owner.isSneaking()); + } + if (owner instanceof EntityPlayer) { EntityPlayer player = (EntityPlayer)owner; - player.eyeHeight = entity.getEyeHeight(); - if (entity instanceof IOwned) { IOwned.cast(entity).setOwner(player); } @@ -306,7 +331,7 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate { if (UClient.instance().getViewMode() == 0) { entity.setInvisible(true); - entity.posY = -10; + entity.posY = -Integer.MIN_VALUE; } } else { entity.setAlwaysRenderNameTag(true); @@ -337,7 +362,6 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate { @Override public void render(ICaster source) { - } @Override @@ -399,4 +423,26 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate { return false; } + + @Override + public float getTargetEyeHeight(IPlayer player) { + if (entity != null) { + if (entity instanceof EntityFallingBlock) { + return 0.5F; + } + return entity.getEyeHeight(); + } + return -1; + } + + @Override + public float getTargetBodyHeight(IPlayer player) { + if (entity != null) { + if (entity instanceof EntityFallingBlock) { + return 0.9F; + } + return entity.height - 0.1F; + } + return -1; + } }