diff --git a/src/main/java/com/minelittlepony/unicopia/ability/HeightPredicate.java b/src/main/java/com/minelittlepony/unicopia/ability/DimensionsPredicate.java similarity index 59% rename from src/main/java/com/minelittlepony/unicopia/ability/HeightPredicate.java rename to src/main/java/com/minelittlepony/unicopia/ability/DimensionsPredicate.java index 12aa6c9e..a507ae17 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/HeightPredicate.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/DimensionsPredicate.java @@ -1,14 +1,18 @@ package com.minelittlepony.unicopia.ability; +import java.util.Optional; + import com.minelittlepony.unicopia.entity.player.Pony; +import net.minecraft.entity.EntityDimensions; + /** * Predicate for abilities to control what the player's physical height is. * * This overrides the default. */ -public interface HeightPredicate { +public interface DimensionsPredicate { float getTargetEyeHeight(Pony player); - float getTargetBodyHeight(Pony player); + Optional getTargetDimensions(Pony player); } 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 4ebd9c74..22f86ba3 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 @@ -1,12 +1,14 @@ package com.minelittlepony.unicopia.ability.magic.spell; +import java.util.Optional; + import javax.annotation.Nullable; import com.minelittlepony.unicopia.Affinity; import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.Owned; import com.minelittlepony.unicopia.ability.FlightPredicate; -import com.minelittlepony.unicopia.ability.HeightPredicate; +import com.minelittlepony.unicopia.ability.DimensionsPredicate; import com.minelittlepony.unicopia.ability.magic.AttachableSpell; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Spell; @@ -17,6 +19,7 @@ import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.particle.UParticles; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.data.TrackedData; import net.minecraft.entity.mob.MobEntity; @@ -24,7 +27,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.ProjectileEntity; import net.minecraft.nbt.CompoundTag; -public class DisguiseSpell extends AbstractSpell implements AttachableSpell, Suppressable, FlightPredicate, HeightPredicate { +public class DisguiseSpell extends AbstractSpell implements AttachableSpell, Suppressable, FlightPredicate, DimensionsPredicate { private final Disguise disguise = new Disguise(); @@ -55,6 +58,12 @@ public class DisguiseSpell extends AbstractSpell implements AttachableSpell, Sup return suppressionCounter <= otherSource.getCurrentLevel(); } + @Override + public void onDestroyed(Caster caster) { + super.onDestroyed(caster); + caster.getEntity().calculateDimensions(); + } + @Override public void onSuppressed(Caster otherSource) { suppressionCounter = 100; @@ -218,8 +227,8 @@ public class DisguiseSpell extends AbstractSpell implements AttachableSpell, Sup } @Override - public float getTargetBodyHeight(Pony player) { - return isSuppressed() ? -1 : disguise.getHeight(); + public Optional getTargetDimensions(Pony player) { + return isSuppressed() ? Optional.empty() : disguise.getDimensions(); } static abstract class PlayerAccess extends PlayerEntity { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/ItemWielder.java b/src/main/java/com/minelittlepony/unicopia/entity/ItemWielder.java new file mode 100644 index 00000000..b2210ffa --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/ItemWielder.java @@ -0,0 +1,8 @@ +package com.minelittlepony.unicopia.entity; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; + +public interface ItemWielder { + void updateItemUsage(Hand hand, ItemStack stack, int time); +} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java index a6591b94..9c9ac695 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java @@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.entity.behaviour; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.UUID; import javax.annotation.Nonnull; @@ -19,6 +20,7 @@ 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.EntityDimensions; import net.minecraft.entity.EntityType; import net.minecraft.entity.FallingBlockEntity; import net.minecraft.entity.Flutterer; @@ -46,6 +48,8 @@ public class Disguise implements NbtSerialisable { private List attachments = new ArrayList<>(); + private Optional dimensions = Optional.empty(); + @Nullable private CompoundTag entityNbt; @@ -200,6 +204,10 @@ public class Disguise implements NbtSerialisable { return -1; } + public Optional getDimensions() { + return dimensions = EntityBehaviour.forEntity(entity).getDimensions(entity, dimensions); + } + public boolean skipsUpdate() { return entity instanceof FallingBlockEntity || entity instanceof AbstractDecorationEntity 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 dd31acf9..971a2341 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityBehaviour.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityBehaviour.java @@ -1,14 +1,17 @@ package com.minelittlepony.unicopia.entity.behaviour; +import java.util.Optional; import java.util.function.Supplier; import javax.annotation.Nullable; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Spell; +import com.minelittlepony.unicopia.entity.ItemWielder; import com.minelittlepony.unicopia.util.Registries; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.EntityType; import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.FallingBlockEntity; @@ -36,6 +39,21 @@ public class EntityBehaviour { return entity; } + public Optional getDimensions(T entity, Optional current) { + if (entity == null) { + return Optional.empty(); + } + + float h = entity.getHeight() - 0.1F; + float w = entity.getWidth(); + + if (current.isPresent() && h == current.get().height && w == current.get().width) { + return current; + } + + return Optional.of(EntityDimensions.changing(entity.getHeight() - 0.1F, entity.getWidth())); + } + public void copyBaseAttributes(LivingEntity from, Entity to) { copyBaseAttributes(from, to, Vec3d.ZERO); } @@ -102,6 +120,9 @@ public class EntityBehaviour { to.prevYaw = from.prevYaw; to.horizontalSpeed = from.horizontalSpeed; to.prevHorizontalSpeed = from.prevHorizontalSpeed; + to.horizontalCollision = from.horizontalCollision; + to.verticalCollision = from.verticalCollision; + to.setOnGround(from.isOnGround()); to.distanceTraveled = from.distanceTraveled; @@ -139,6 +160,10 @@ public class EntityBehaviour { ((AbstractSkeletonEntity)to).setAttacking(from.getItemUseTimeLeft() > 0); } + if (to instanceof ItemWielder) { + ((ItemWielder)to).updateItemUsage(from.getActiveHand(), from.getActiveItem(), from.getItemUseTimeLeft()); + } + if (from.age < 100 || from instanceof PlayerEntity && ((PlayerEntity)from).isCreative()) { to.extinguish(); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/FallingBlockBehaviour.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/FallingBlockBehaviour.java index ee8fb6be..c00c3272 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/FallingBlockBehaviour.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/FallingBlockBehaviour.java @@ -1,6 +1,7 @@ package com.minelittlepony.unicopia.entity.behaviour; import java.util.List; +import java.util.Optional; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Spell; @@ -18,6 +19,7 @@ import net.minecraft.block.entity.ChestBlockEntity; import net.minecraft.block.entity.EnderChestBlockEntity; import net.minecraft.block.enums.DoubleBlockHalf; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.FallingBlockEntity; import net.minecraft.state.property.Properties; import net.minecraft.tag.BlockTags; @@ -29,6 +31,14 @@ public class FallingBlockBehaviour extends EntityBehaviour { private static final Vec3d UP = Vec3d.of(Direction.UP.getVector()); + private static final Optional FULL_BLOCK = Optional.of(EntityDimensions.changing(1, 0.9F)); + + + @Override + public Optional getDimensions(FallingBlockEntity entity, Optional current) { + return FULL_BLOCK; + } + @Override public FallingBlockEntity onCreate(FallingBlockEntity entity, Disguise context, boolean replaceOld) { super.onCreate(entity, context, replaceOld); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerDimensions.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerDimensions.java index e75400bb..2b289e09 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerDimensions.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerDimensions.java @@ -1,18 +1,22 @@ package com.minelittlepony.unicopia.entity.player; -import com.minelittlepony.unicopia.ability.HeightPredicate; +import java.util.Optional; + +import javax.annotation.Nullable; + +import com.minelittlepony.unicopia.ability.DimensionsPredicate; import com.minelittlepony.unicopia.ability.magic.Spell; import net.minecraft.entity.EntityDimensions; -import net.minecraft.entity.EntityPose; public final class PlayerDimensions { private float defaultEyeHeight; - private float defaultBodyHeight; - private float lastTargetEyeHeight; - private float lastTargetBodyHeight; + @Nullable + private EntityDimensions defaultDimensions; + @Nullable + private EntityDimensions flyingDimensions; private final PlayerPhysics physics; @@ -23,52 +27,42 @@ public final class PlayerDimensions { this.physics = gravity; } - public float getActiveEyeHeight(float original) { + public float calculateActiveEyeHeight(EntityDimensions dimensions, float original) { defaultEyeHeight = original; - return calculateTargetEyeHeightWithGravity(calculateTargetBodyHeight()); - } - public EntityDimensions getDimensions(EntityPose pos, EntityDimensions dimensions) { - defaultBodyHeight = dimensions.height; - return EntityDimensions.changing(dimensions.width, calculateTargetBodyHeight()); - } - - boolean update() { - float targetBodyHeight = calculateTargetBodyHeight(); - float targetEyeHeight = calculateTargetEyeHeightWithGravity(targetBodyHeight); - - if (targetEyeHeight != lastTargetEyeHeight || targetBodyHeight != lastTargetBodyHeight) { - lastTargetBodyHeight = targetBodyHeight; - lastTargetEyeHeight = targetEyeHeight; - return true; - } - - return false; - } - - private float calculateTargetEyeHeightWithGravity(float targetBodyHeight) { float height = calculateTargetEyeHeight(); - if (physics.isGravityNegative() && pony.getOwner().isSneaking()) { - height += 0.2F; - } - if (physics.isGravityNegative()) { - height = targetBodyHeight - height; + if (pony.getOwner().isSneaking()) { + height += 0.2F; + } + + height = dimensions.height - height; } return height; } - private float calculateTargetEyeHeight() { - if (pony.hasSpell()) { - Spell effect = pony.getSpell(true); - if (!effect.isDead() && effect instanceof HeightPredicate) { - float val = ((HeightPredicate)effect).getTargetEyeHeight(pony); - if (val > 0) { - return val; - } + public EntityDimensions calculateDimensions(EntityDimensions dimensions) { + if (defaultDimensions == null || dimensions.height != defaultDimensions.height || dimensions.width != defaultDimensions.width) { + defaultDimensions = dimensions; + flyingDimensions = EntityDimensions.changing(dimensions.width, dimensions.height / 2); + } + + return getPredicate().flatMap(e -> e.getTargetDimensions(pony)).orElseGet(() -> { + if (physics.isFlyingSurvival && physics.isRainboom()) { + return flyingDimensions; } + + return defaultDimensions; + }); + } + + private float calculateTargetEyeHeight() { + float height = getPredicate().map(e -> e.getTargetEyeHeight(pony)).orElse(-1F); + + if (height > 0) { + return height; } if (physics.isFlyingSurvival && physics.isRainboom()) { @@ -78,22 +72,13 @@ public final class PlayerDimensions { return defaultEyeHeight; } - private float calculateTargetBodyHeight() { + Optional getPredicate() { if (pony.hasSpell()) { Spell effect = pony.getSpell(true); - if (!effect.isDead() && effect instanceof HeightPredicate) { - float val = ((HeightPredicate)effect).getTargetBodyHeight(pony); - if (val > 0) { - return val; - } + if (!effect.isDead() && effect instanceof DimensionsPredicate) { + return Optional.of(((DimensionsPredicate)effect)); } } - - if (physics.isFlyingSurvival && physics.isRainboom()) { - return defaultBodyHeight / 2; - } - - return defaultBodyHeight; + return Optional.empty(); } - } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java index c64dbfe4..0daf9530 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java @@ -17,14 +17,21 @@ import com.minelittlepony.unicopia.entity.PonyContainer; import com.minelittlepony.unicopia.entity.behaviour.Disguise; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.Equine; +import com.minelittlepony.unicopia.entity.ItemWielder; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @Mixin(LivingEntity.class) -abstract class MixinLivingEntity extends Entity implements PonyContainer> { +abstract class MixinLivingEntity extends Entity implements PonyContainer>, ItemWielder { + @Shadow + protected ItemStack activeItemStack; + @Shadow + protected int itemUseTimeLeft; @Shadow private Optional climbingPos; @@ -33,6 +40,9 @@ abstract class MixinLivingEntity extends Entity implements PonyContainer create() { return new Creature((LivingEntity)(Object)this); @@ -108,6 +118,17 @@ abstract class MixinLivingEntity extends Entity implements PonyContainer info) { - info.setReturnValue(get().getMotion().getDimensions().getActiveEyeHeight(info.getReturnValue())); + info.setReturnValue(get().getMotion().getDimensions().calculateActiveEyeHeight(dimensions, info.getReturnValue())); } @Inject(method = "getDimensions(Lnet/minecraft/entity/EntityPose;)Lnet/minecraft/entity/EntityDimensions;", at = @At("RETURN"), cancellable = true) public void onGetDimensions(EntityPose pose, CallbackInfoReturnable info) { - info.setReturnValue(get().getMotion().getDimensions().getDimensions(pose, info.getReturnValue())); + info.setReturnValue(get().getMotion().getDimensions().calculateDimensions(info.getReturnValue())); } }