A changeling's bounding box and eye height will now match the entity they disguise themselves as

This commit is contained in:
Sollace 2019-02-12 15:25:48 +02:00
parent 3f0805b1d8
commit c02c72cc60
6 changed files with 159 additions and 28 deletions

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.mixin; package com.minelittlepony.unicopia.mixin;
import com.google.common.base.Optional; import java.lang.reflect.Field;
import com.minelittlepony.unicopia.forgebullshit.FUF; import com.minelittlepony.unicopia.forgebullshit.FUF;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
@ -8,7 +9,6 @@ import net.minecraft.entity.MoverType;
import net.minecraft.entity.monster.EntityShulker; import net.minecraft.entity.monster.EntityShulker;
import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataParameter;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
@FUF(reason = "Waiting for mixins?") @FUF(reason = "Waiting for mixins?")
public interface MixinEntity { public interface MixinEntity {
@ -24,8 +24,28 @@ public interface MixinEntity {
abstract class Shulker extends EntityShulker { abstract class Shulker extends EntityShulker {
private Shulker() { super(null);} private Shulker() { super(null);}
public static DataParameter<Optional<BlockPos>> getAttachmentPosFlag() { private static boolean __init;
return ATTACHED_BLOCK_POS; 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);
}
} }
} }

View file

@ -1,6 +1,6 @@
package com.minelittlepony.unicopia.player; package com.minelittlepony.unicopia.player;
public interface IGravity extends IFlyingPredicate { public interface IGravity {
boolean isFlying(); boolean isFlying();
float getFlightExperience(); float getFlightExperience();

View file

@ -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);
}

View file

@ -21,7 +21,7 @@ import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
class PlayerGravityDelegate implements IUpdatable<EntityPlayer>, IGravity, InbtSerialisable { class PlayerGravityDelegate implements IUpdatable<EntityPlayer>, IGravity, InbtSerialisable, IFlyingPredicate, IPlayerHeightPredicate {
private final IPlayer player; private final IPlayer player;
@ -36,6 +36,7 @@ class PlayerGravityDelegate implements IUpdatable<EntityPlayer>, IGravity, InbtS
this.player = player; this.player = player;
} }
@Override
public boolean checkCanFly(IPlayer player) { public boolean checkCanFly(IPlayer player) {
if (player.getOwner().capabilities.isCreativeMode) { if (player.getOwner().capabilities.isCreativeMode) {
return true; return true;
@ -51,6 +52,51 @@ class PlayerGravityDelegate implements IUpdatable<EntityPlayer>, IGravity, InbtS
return player.getPlayerSpecies().canFly(); 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 @Override
public void onUpdate(EntityPlayer entity) { public void onUpdate(EntityPlayer entity) {
@ -62,15 +108,8 @@ class PlayerGravityDelegate implements IUpdatable<EntityPlayer>, IGravity, InbtS
isFlying = entity.capabilities.isFlying && !entity.capabilities.isCreativeMode; isFlying = entity.capabilities.isFlying && !entity.capabilities.isCreativeMode;
boolean rainboom = Math.sqrt(getHorizontalMotion(entity)) > 0.4F; MixinEntity.setSize(entity, entity.width, player.getInterpolator().interpolate("standingHeight", getTargetBodyHeight(player), 10));
entity.eyeHeight = player.getInterpolator().interpolate("eyeHeight", getTargetEyeHeight(player), 10);
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);
}
if (!entity.capabilities.isCreativeMode && !entity.isElytraFlying()) { if (!entity.capabilities.isCreativeMode && !entity.isElytraFlying()) {
if (isFlying && !entity.isRiding()) { if (isFlying && !entity.isRiding()) {

View file

@ -13,10 +13,13 @@ import com.minelittlepony.unicopia.spell.IMagicEffect;
import com.minelittlepony.unicopia.spell.SpellDisguise; import com.minelittlepony.unicopia.spell.SpellDisguise;
import com.minelittlepony.util.vector.VecHelper; import com.minelittlepony.util.vector.VecHelper;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityFallingBlock;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents; import net.minecraft.init.SoundEvents;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.RayTraceResult;
public class PowerDisguise extends PowerFeed { public class PowerDisguise extends PowerFeed {
@ -39,7 +42,18 @@ public class PowerDisguise extends PowerFeed {
@Override @Override
public void apply(IPlayer iplayer, Hit data) { public void apply(IPlayer iplayer, Hit data) {
EntityPlayer player = iplayer.getOwner(); 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) { if (looked instanceof EntityPlayer) {
IPlayer ilooked = PlayerSpeciesList.instance().getPlayer((EntityPlayer)looked); 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(); IMagicEffect effect = iplayer.getEffect();
if (effect instanceof SpellDisguise && !effect.getDead()) { if (effect instanceof SpellDisguise && !effect.getDead()) {

View file

@ -11,7 +11,9 @@ import com.minelittlepony.unicopia.mixin.MixinEntity;
import com.minelittlepony.unicopia.player.IFlyingPredicate; import com.minelittlepony.unicopia.player.IFlyingPredicate;
import com.minelittlepony.unicopia.player.IOwned; import com.minelittlepony.unicopia.player.IOwned;
import com.minelittlepony.unicopia.player.IPlayer; import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.player.IPlayerHeightPredicate;
import com.minelittlepony.unicopia.player.PlayerSpeciesList; import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import com.minelittlepony.unicopia.render.DisguiseRenderer;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import net.minecraft.entity.Entity; 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.item.EntityMinecart;
import net.minecraft.entity.monster.EntityShulker; import net.minecraft.entity.monster.EntityShulker;
import net.minecraft.entity.passive.EntityAmbientCreature; import net.minecraft.entity.passive.EntityAmbientCreature;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntitySkull; import net.minecraft.tileentity.TileEntitySkull;
public class SpellDisguise extends AbstractSpell implements IFlyingPredicate { public class SpellDisguise extends AbstractSpell implements IFlyingPredicate, IPlayerHeightPredicate {
@Nonnull @Nonnull
private String entityId = ""; private String entityId = "";
@ -223,15 +226,13 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate {
if (l instanceof EntityShulker) { if (l instanceof EntityShulker) {
l.rotationYaw = 0; l.rotationYaw = 0;
l.rotationPitch = 0;
l.rotationYawHead = 0;
l.prevRotationYawHead = 0;
l.renderYawOffset = 0; l.renderYawOffset = 0;
l.prevRenderYawOffset = 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.posX = Math.floor(owner.posX) + 0.5;
entity.posY = Math.floor(owner.posY + 0.2); entity.posY = Math.floor(owner.posY + 0.2);
@ -244,9 +245,31 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate {
entity.prevPosX = entity.posX; entity.prevPosX = entity.posX;
entity.prevPosY = entity.posY; entity.prevPosY = entity.posY;
entity.prevPosZ = entity.posZ; entity.prevPosZ = entity.posZ;
}
if (entity instanceof EntityShulker) { if (entity instanceof EntityShulker) {
((EntityShulker)entity).setAttachmentPos(null); 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); owner.setInvisible(true);
if (entity instanceof EntityTameable) {
((EntityTameable)entity).setSitting(owner.isSneaking());
}
if (owner instanceof EntityPlayer) { if (owner instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer)owner; EntityPlayer player = (EntityPlayer)owner;
player.eyeHeight = entity.getEyeHeight();
if (entity instanceof IOwned) { if (entity instanceof IOwned) {
IOwned.cast(entity).setOwner(player); IOwned.cast(entity).setOwner(player);
} }
@ -306,7 +331,7 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate {
if (UClient.instance().getViewMode() == 0) { if (UClient.instance().getViewMode() == 0) {
entity.setInvisible(true); entity.setInvisible(true);
entity.posY = -10; entity.posY = -Integer.MIN_VALUE;
} }
} else { } else {
entity.setAlwaysRenderNameTag(true); entity.setAlwaysRenderNameTag(true);
@ -337,7 +362,6 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate {
@Override @Override
public void render(ICaster<?> source) { public void render(ICaster<?> source) {
} }
@Override @Override
@ -399,4 +423,26 @@ public class SpellDisguise extends AbstractSpell implements IFlyingPredicate {
return false; 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;
}
} }