diff --git a/src/main/java/com/minelittlepony/api/model/ModelAttributes.java b/src/main/java/com/minelittlepony/api/model/ModelAttributes.java
index ded3dd9c..05710e89 100644
--- a/src/main/java/com/minelittlepony/api/model/ModelAttributes.java
+++ b/src/main/java/com/minelittlepony/api/model/ModelAttributes.java
@@ -1,6 +1,7 @@
package com.minelittlepony.api.model;
import com.minelittlepony.api.pony.IPony;
+import com.minelittlepony.api.pony.PonyPosture;
import com.minelittlepony.util.MathUtil;
import net.minecraft.entity.LivingEntity;
@@ -122,16 +123,16 @@ public class ModelAttributes {
public void updateLivingState(LivingEntity entity, IPony pony, Mode mode) {
visualHeight = entity.getHeight() + 0.125F;
- isSitting = pony.isSitting(entity);
- isCrouching = !isSitting && mode == Mode.THIRD_PERSON && pony.isCrouching(entity);
+ isSitting = PonyPosture.isSitting(entity);
+ isCrouching = !isSitting && mode == Mode.THIRD_PERSON && PonyPosture.isCrouching(pony, entity);
isSleeping = entity.isSleeping();
- isFlying = mode == Mode.THIRD_PERSON && pony.isFlying(entity);
+ isFlying = mode == Mode.THIRD_PERSON && PonyPosture.isFlying(entity);
isGliding = entity.isFallFlying();
- isSwimming = mode == Mode.THIRD_PERSON && pony.isSwimming(entity);
+ isSwimming = mode == Mode.THIRD_PERSON && PonyPosture.isSwimming(entity);
isSwimmingRotated = isSwimming && (entity instanceof PlayerEntity || entity instanceof Swimmer);
isRiptide = entity.isUsingRiptide();
isHorizontal = isSwimming;
- isRidingInteractive = pony.isRidingInteractive(entity);
+ isRidingInteractive = PonyPosture.isRidingAPony(entity);
interpolatorId = entity.getUuid();
isLeftHanded = entity.getMainArm() == Arm.LEFT;
}
diff --git a/src/main/java/com/minelittlepony/api/pony/IPony.java b/src/main/java/com/minelittlepony/api/pony/IPony.java
index e87940a4..2232c83a 100644
--- a/src/main/java/com/minelittlepony/api/pony/IPony.java
+++ b/src/main/java/com/minelittlepony/api/pony/IPony.java
@@ -1,11 +1,6 @@
package com.minelittlepony.api.pony;
-import net.minecraft.entity.Entity;
-import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier;
-import net.minecraft.util.math.Box;
-import net.minecraft.util.math.Vec3d;
-
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.MineLittlePony;
@@ -29,85 +24,28 @@ public interface IPony {
return getManager().getPony(texture);
}
- /**
- * Triggers state updates on the passed entity.
- */
- void updateForEntity(Entity entity);
-
/**
* Returns whether this is one of the default ponies assigned to a player without a custom skin.
*/
- boolean isDefault();
+ boolean defaulted();
/**
- * Unlike sneaking, crouching is a more specific animation parameter that controls whether the player is visible
- * nose to the ground, crouching the sand.
- *
- * You cannot crouch whilst flying or swimming.
+ * Returns whether this pony's metadata block has been initialized.
*/
- boolean isCrouching(LivingEntity entity);
-
- /**
- * Returns true if the provided entity is flying like a pegasus.
- * True if the entity is off the ground.
- * Creative flight counts only if the entity is not on the ground.
- *
- * Entities that are riding, climbing a ladder, or swimming are not flying.
- */
- boolean isFlying(LivingEntity entity);
-
- /**
- * Returns true if the provided entity is actively swimming.
- * That is, it should be fully submerged (isFullySubmerged returns true)
- * and is not standing on the (river) bed or riding a ladder or any other entity.
- */
- boolean isSwimming(LivingEntity entity);
-
- /**
- * Returns true if the provided entity is partially submerged. That is if any part of it is in contact with water.
- */
- boolean isPartiallySubmerged(LivingEntity entity);
+ boolean hasMetadata();
/**
* Gets the race associated with this pony.
*/
- Race getRace();
-
- /**
- * Returns true if an entity is sitting as when riding a vehicle or
- * a customized habitually actuated indoors rester (CHAIR)
- */
- boolean isSitting(LivingEntity entity);
-
- /**
- * Returns true if an entity is riding a pony or other sentient life-form.
- *
- * Boats do not count.
- */
- boolean isRidingInteractive(LivingEntity entity);
-
- /**
- * Returns the pony this entity is currently riding if any.
- */
- IPony getMountedPony(LivingEntity entity);
+ Race race();
/**
* Gets the texture used for rendering this pony.
*/
- Identifier getTexture();
+ Identifier texture();
/**
* Gets the metadata associated with this pony's model texture.
*/
- IPonyData getMetadata();
-
- /**
- * Gets the riding offset of this entity relative to its lowermost mount.
- */
- Vec3d getAbsoluteRidingOffset(LivingEntity entity);
-
- /**
- * Gets the actual bounding box of this entity as a pony.
- */
- Box getComputedBoundingBox(LivingEntity entity);
+ IPonyData metadata();
}
diff --git a/src/main/java/com/minelittlepony/api/pony/IPonyManager.java b/src/main/java/com/minelittlepony/api/pony/IPonyManager.java
index 8887e3e5..b3e18854 100644
--- a/src/main/java/com/minelittlepony/api/pony/IPonyManager.java
+++ b/src/main/java/com/minelittlepony/api/pony/IPonyManager.java
@@ -1,8 +1,12 @@
package com.minelittlepony.api.pony;
+import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Optional;
import java.util.UUID;
/**
@@ -14,6 +18,13 @@ public interface IPonyManager {
Identifier STEVE = new Identifier("minelittlepony", "textures/entity/steve_pony.png");
Identifier ALEX = new Identifier("minelittlepony", "textures/entity/alex_pony.png");
+ /**
+ * Gets a pony representation of the passed in entity.
+ *
+ * If the supplied entity is null or can't be determined to be a pony, returns the empty optional.
+ */
+ Optional getPony(@Nullable Entity entity);
+
/**
* Gets or creates a pony for the given player.
* Delegates to the background-ponies registry if no pony skins were available and client settings allows it.
diff --git a/src/main/java/com/minelittlepony/api/pony/PonyPosture.java b/src/main/java/com/minelittlepony/api/pony/PonyPosture.java
new file mode 100644
index 00000000..406a7a53
--- /dev/null
+++ b/src/main/java/com/minelittlepony/api/pony/PonyPosture.java
@@ -0,0 +1,85 @@
+package com.minelittlepony.api.pony;
+
+import com.minelittlepony.api.pony.meta.Race;
+
+import java.util.Optional;
+
+import net.minecraft.block.BlockState;
+import net.minecraft.block.Material;
+import net.minecraft.block.StairsBlock;
+import net.minecraft.entity.LivingEntity;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Vec3d;
+
+public final class PonyPosture {
+ public static Optional getMountPony(LivingEntity entity) {
+ return entity.getVehicle() instanceof LivingEntity mount
+ ? IPony.getManager().getPony(mount)
+ : Optional.empty();
+ }
+
+ public static boolean isCrouching(IPony pony, LivingEntity entity) {
+ boolean isSneak = entity.isInSneakingPose();
+ boolean isFlying = isFlying(entity);
+ boolean isSwimming = isSwimming(entity);
+
+ return !isPerformingRainboom(pony, entity) && !isSwimming && isSneak && !isFlying;
+ }
+
+ private static boolean isPerformingRainboom(IPony pony, LivingEntity entity) {
+ Vec3d motion = entity.getVelocity();
+ double zMotion = Math.sqrt(motion.x * motion.x + motion.z * motion.z);
+
+ return (isFlying(entity) && pony.race().hasWings()) || entity.isFallFlying() & zMotion > 0.4F;
+ }
+
+ public static boolean isFlying(LivingEntity entity) {
+ return !(isOnGround(entity)
+ || entity.hasVehicle()
+ || (entity.isClimbing() && !(entity instanceof PlayerEntity && ((PlayerEntity)entity).getAbilities().allowFlying))
+ || entity.isSubmergedInWater()
+ || entity.isSleeping());
+ }
+
+ /**
+ * Checks if the entity is on the ground, or close enough to be "effectively" grounded.
+ * this is to keep Pegasus wings from flapping in odd situations (Hypixel).
+ */
+ private static boolean isOnGround(LivingEntity entity) {
+ if (entity.isOnGround()) {
+ return true;
+ }
+
+ BlockState below = entity.getEntityWorld()
+ .getBlockState(entity.getBlockPos().down(1));
+
+ // Check for stairs so we can keep Pegasi from flailing their wings as they descend
+ double offsetAmount = below.getBlock() instanceof StairsBlock ? 1 : 0.05;
+
+ Vec3d pos = entity.getPos();
+ BlockPos blockpos = new BlockPos(
+ Math.floor(pos.x),
+ Math.floor(pos.y - offsetAmount),
+ Math.floor(pos.z));
+
+ return !entity.getEntityWorld().isAir(blockpos);
+ }
+
+ public static boolean isSwimming(LivingEntity entity) {
+ return entity.isSwimming() || entity.isInSwimmingPose();
+ }
+
+ public static boolean isPartiallySubmerged(LivingEntity entity) {
+ return entity.isSubmergedInWater()
+ || entity.getEntityWorld().getBlockState(entity.getBlockPos()).getMaterial() == Material.WATER;
+ }
+
+ public static boolean isSitting(LivingEntity entity) {
+ return entity.hasVehicle();
+ }
+
+ public static boolean isRidingAPony(LivingEntity entity) {
+ return isSitting(entity) && getMountPony(entity).map(IPony::race).orElse(Race.HUMAN) != Race.HUMAN;
+ }
+}
diff --git a/src/main/java/com/minelittlepony/api/pony/network/fabric/Channel.java b/src/main/java/com/minelittlepony/api/pony/network/fabric/Channel.java
index 6477bb07..c8bafe0f 100644
--- a/src/main/java/com/minelittlepony/api/pony/network/fabric/Channel.java
+++ b/src/main/java/com/minelittlepony/api/pony/network/fabric/Channel.java
@@ -39,7 +39,7 @@ public class Channel {
registered = true;
MineLittlePony.logger.info("Server has just consented");
- sender.sendPacket(CLIENT_PONY_DATA, new MsgPonyData(pony.getMetadata(), pony.isDefault()).toBuffer(PacketByteBufs.create()));
+ sender.sendPacket(CLIENT_PONY_DATA, new MsgPonyData(pony.metadata(), pony.defaulted()).toBuffer(PacketByteBufs.create()));
}
});
ServerPlayNetworking.registerGlobalReceiver(CLIENT_PONY_DATA, (server, player, ignore, buffer, ignore2) -> {
diff --git a/src/main/java/com/minelittlepony/api/pony/network/fabric/PonyDataCallback.java b/src/main/java/com/minelittlepony/api/pony/network/fabric/PonyDataCallback.java
index 72402f41..fb090025 100644
--- a/src/main/java/com/minelittlepony/api/pony/network/fabric/PonyDataCallback.java
+++ b/src/main/java/com/minelittlepony/api/pony/network/fabric/PonyDataCallback.java
@@ -15,7 +15,7 @@ import com.minelittlepony.client.MineLittlePony;
public interface PonyDataCallback {
Event EVENT = EventFactory.createArrayBacked(PonyDataCallback.class, listeners -> (sender, data, noSkin, env) -> {
- MineLittlePony.logger.info("Got pony data on the " + env + " from " + sender.getName().getString() + " with " + (noSkin ? "un" : "") + "set skin and he is a " + data.getRace() + "!");
+ MineLittlePony.logger.info("Got pony data on the " + env + " from " + sender.getUuidAsString() + " with " + (noSkin ? "un" : "") + "set skin and he is a " + data.getRace() + "!");
for (PonyDataCallback event : listeners) {
event.onPonyDataAvailable(sender, data, noSkin, env);
}
diff --git a/src/main/java/com/minelittlepony/client/HorseCam.java b/src/main/java/com/minelittlepony/client/HorseCam.java
index 32d693f9..4ae1e34a 100644
--- a/src/main/java/com/minelittlepony/client/HorseCam.java
+++ b/src/main/java/com/minelittlepony/client/HorseCam.java
@@ -47,7 +47,7 @@ public class HorseCam {
IPony pony = MineLittlePony.getInstance().getManager().getPony(player);
- if (!pony.getRace().isHuman()) {
+ if (!pony.race().isHuman()) {
Setting fillyCam = MineLittlePony.getInstance().getConfig().fillycam;
fillyCam.set(false);
diff --git a/src/main/java/com/minelittlepony/client/PonyBounds.java b/src/main/java/com/minelittlepony/client/PonyBounds.java
new file mode 100644
index 00000000..ea0fde43
--- /dev/null
+++ b/src/main/java/com/minelittlepony/client/PonyBounds.java
@@ -0,0 +1,50 @@
+package com.minelittlepony.client;
+
+import com.minelittlepony.api.pony.IPony;
+import com.minelittlepony.api.pony.PonyPosture;
+import com.minelittlepony.client.transform.PonyTransformation;
+
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.LivingEntity;
+import net.minecraft.util.math.Box;
+import net.minecraft.util.math.MathHelper;
+import net.minecraft.util.math.Vec3d;
+
+public class PonyBounds {
+ public static Vec3d getAbsoluteRidingOffset(LivingEntity entity) {
+ return PonyPosture.getMountPony(entity).map(ridingPony -> {
+ LivingEntity vehicle = (LivingEntity)entity.getVehicle();
+
+ Vec3d offset = PonyTransformation.forSize(ridingPony.metadata().getSize()).getRiderOffset();
+ float scale = ridingPony.metadata().getSize().getScaleFactor();
+
+ return getAbsoluteRidingOffset(vehicle).add(
+ 0,
+ offset.y - vehicle.getHeight() * 1 / scale,
+ 0
+ );
+ }).orElseGet(() -> getBaseRidingOffset(entity));
+ }
+
+ private static Vec3d getBaseRidingOffset(LivingEntity entity) {
+ float delta = MinecraftClient.getInstance().getTickDelta();
+
+ Entity vehicle = entity.getVehicle();
+ double vehicleOffset = vehicle == null ? 0 : vehicle.getHeight() - vehicle.getMountedHeightOffset();
+
+ return new Vec3d(
+ MathHelper.lerp(delta, entity.prevX, entity.getX()),
+ MathHelper.lerp(delta, entity.prevY, entity.getY()) + vehicleOffset,
+ MathHelper.lerp(delta, entity.prevZ, entity.getZ())
+ );
+ }
+
+ public static Box getBoundingBox(IPony pony, LivingEntity entity) {
+ final float scale = pony.metadata().getSize().getScaleFactor() + 0.1F;
+ final float width = entity.getWidth() * scale;
+ final float height = entity.getHeight() * scale;
+
+ return new Box(-width, height, -width, width, 0, width).offset(getAbsoluteRidingOffset(entity));
+ }
+}
diff --git a/src/main/java/com/minelittlepony/client/SkinsProxy.java b/src/main/java/com/minelittlepony/client/SkinsProxy.java
index 0f30ea1b..dcdfee4c 100644
--- a/src/main/java/com/minelittlepony/client/SkinsProxy.java
+++ b/src/main/java/com/minelittlepony/client/SkinsProxy.java
@@ -42,7 +42,7 @@ public class SkinsProxy {
}
public Identifier getSeaponySkin(EquineRenderManager> manager, AbstractClientPlayerEntity player) {
- return manager.getPony(player).getTexture();
+ return manager.getPony(player).texture();
}
}
diff --git a/src/main/java/com/minelittlepony/client/hdskins/DummyPony.java b/src/main/java/com/minelittlepony/client/hdskins/DummyPony.java
index e1863a89..592caae5 100644
--- a/src/main/java/com/minelittlepony/client/hdskins/DummyPony.java
+++ b/src/main/java/com/minelittlepony/client/hdskins/DummyPony.java
@@ -3,6 +3,7 @@ package com.minelittlepony.client.hdskins;
import net.minecraft.client.world.ClientWorld;
import com.minelittlepony.api.model.ModelAttributes;
+import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.IPonyManager;
import com.minelittlepony.client.IPreviewModel;
import com.minelittlepony.client.MineLittlePony;
@@ -19,7 +20,7 @@ class DummyPony extends DummyPlayer implements IPreviewModel, ModelAttributes.Sw
}
@Override
- public boolean shouldUpdateRegistration(Pony pony) {
+ public boolean shouldUpdateRegistration(IPony pony) {
return false;
}
@@ -35,7 +36,7 @@ class DummyPony extends DummyPlayer implements IPreviewModel, ModelAttributes.Sw
}
return MineLittlePony.getInstance().getManager()
.getPony(this)
- .getMetadata()
+ .metadata()
.getRace()
.getModelId(getTextures().usesThinSkin());
}
diff --git a/src/main/java/com/minelittlepony/client/hdskins/PonyPreview.java b/src/main/java/com/minelittlepony/client/hdskins/PonyPreview.java
index 9c8759f3..89951e04 100644
--- a/src/main/java/com/minelittlepony/client/hdskins/PonyPreview.java
+++ b/src/main/java/com/minelittlepony/client/hdskins/PonyPreview.java
@@ -48,7 +48,7 @@ class PonyPreview extends PlayerPreview {
MatrixStack matrices, @Nullable Consumer postAction) {
super.renderWorldAndPlayer(thePlayer, frame, horizon, mouseX, mouseY, ticks, partialTick, scale, matrices, postAction);
thePlayer.ifPresent(p -> {
- IPonyData data = MineLittlePony.getInstance().getManager().getPony(p).getMetadata();
+ IPonyData data = MineLittlePony.getInstance().getManager().getPony(p).metadata();
int[] index = new int[1];
data.getTriggerPixels().forEach((key, value) -> {
drawLegendBlock(matrices, index[0]++, frame.left, frame.top, mouseX, mouseY, key, value);
diff --git a/src/main/java/com/minelittlepony/client/mixin/MixinCamera.java b/src/main/java/com/minelittlepony/client/mixin/MixinCamera.java
index 8a9a97a6..19581a25 100644
--- a/src/main/java/com/minelittlepony/client/mixin/MixinCamera.java
+++ b/src/main/java/com/minelittlepony/client/mixin/MixinCamera.java
@@ -21,8 +21,8 @@ abstract class MixinCamera {
IPony pony = MineLittlePony.getInstance().getManager().getPony(MinecraftClient.getInstance().player);
- if (!pony.getRace().isHuman()) {
- value *= pony.getMetadata().getSize().getEyeDistanceFactor();
+ if (!pony.race().isHuman()) {
+ value *= pony.metadata().getSize().getEyeDistanceFactor();
}
info.setReturnValue(value);
diff --git a/src/main/java/com/minelittlepony/client/mixin/MixinClientPlayerEntity.java b/src/main/java/com/minelittlepony/client/mixin/MixinClientPlayerEntity.java
index d09341e1..4112382d 100644
--- a/src/main/java/com/minelittlepony/client/mixin/MixinClientPlayerEntity.java
+++ b/src/main/java/com/minelittlepony/client/mixin/MixinClientPlayerEntity.java
@@ -46,8 +46,8 @@ abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity implem
IPony pony = MineLittlePony.getInstance().getManager().getPony(this);
- if (!pony.getRace().isHuman()) {
- float factor = pony.getMetadata().getSize().getEyeHeightFactor();
+ if (!pony.race().isHuman()) {
+ float factor = pony.metadata().getSize().getEyeHeightFactor();
if (factor != 1) {
value *= factor;
diff --git a/src/main/java/com/minelittlepony/client/mixin/MixinDefaultPlayerSkin.java b/src/main/java/com/minelittlepony/client/mixin/MixinDefaultPlayerSkin.java
index 9a6826ed..d8f2db22 100644
--- a/src/main/java/com/minelittlepony/client/mixin/MixinDefaultPlayerSkin.java
+++ b/src/main/java/com/minelittlepony/client/mixin/MixinDefaultPlayerSkin.java
@@ -41,7 +41,7 @@ abstract class MixinDefaultPlayerSkin {
cir.setReturnValue(MineLittlePony.getInstance().getManager()
.getPony(IPonyManager.getDefaultSkin(uuid), uuid)
- .getRace()
+ .race()
.getModelId(IPonyManager.isSlimSkin(uuid)));
}
}
diff --git a/src/main/java/com/minelittlepony/client/mixin/MixinEntityRenderDispatcher.java b/src/main/java/com/minelittlepony/client/mixin/MixinEntityRenderDispatcher.java
index 74b4585f..dc9fa477 100644
--- a/src/main/java/com/minelittlepony/client/mixin/MixinEntityRenderDispatcher.java
+++ b/src/main/java/com/minelittlepony/client/mixin/MixinEntityRenderDispatcher.java
@@ -23,7 +23,7 @@ abstract class MixinEntityRenderDispatcher {
}
return MineLittlePony.getInstance().getManager()
.getPony(player)
- .getRace()
+ .race()
.getModelId(player.getModel().contains("slim"));
}
}
diff --git a/src/main/java/com/minelittlepony/client/pony/Pony.java b/src/main/java/com/minelittlepony/client/pony/Pony.java
index 860122c2..33745201 100644
--- a/src/main/java/com/minelittlepony/client/pony/Pony.java
+++ b/src/main/java/com/minelittlepony/client/pony/Pony.java
@@ -4,41 +4,19 @@ import com.google.common.base.MoreObjects;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.meta.Race;
-import com.minelittlepony.api.pony.meta.Size;
-import com.minelittlepony.api.pony.meta.Sizes;
import com.minelittlepony.api.pony.network.MsgPonyData;
-import com.minelittlepony.api.pony.network.fabric.Channel;
-import com.minelittlepony.api.pony.network.fabric.PonyDataCallback;
-import com.minelittlepony.client.render.IPonyRenderContext;
-import com.minelittlepony.client.render.PonyRenderDispatcher;
-import com.minelittlepony.client.transform.PonyTransformation;
import com.minelittlepony.settings.PonyConfig;
-import java.util.Objects;
-
-import net.fabricmc.api.EnvType;
-import net.minecraft.block.BlockState;
-import net.minecraft.block.Material;
-import net.minecraft.block.StairsBlock;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.entity.Entity;
-import net.minecraft.entity.LivingEntity;
-import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;
-import net.minecraft.util.math.Box;
-import net.minecraft.util.math.BlockPos;
-import net.minecraft.util.math.MathHelper;
-import net.minecraft.util.math.Vec3d;
import org.jetbrains.annotations.Unmodifiable;
@Unmodifiable
public class Pony implements IPony {
-
private final Identifier texture;
private final Memoize metadata;
- private boolean defaulted = false;
+ private boolean defaulted;
Pony(Identifier resource, Memoize data) {
texture = resource;
@@ -49,196 +27,46 @@ public class Pony implements IPony {
this(resource, PonyData.parse(resource));
}
- public IPony defaulted() {
+ public IPony markDefaulted() {
defaulted = true;
return this;
}
@Override
- public boolean isDefault() {
+ public boolean defaulted() {
return defaulted;
}
@Override
- public void updateForEntity(Entity entity) {
- if (!metadata.isPresent()) {
- return;
- }
-
- if (entity instanceof RegistrationHandler && ((RegistrationHandler)entity).shouldUpdateRegistration(this)) {
- entity.calculateDimensions();
-
- PlayerEntity clientPlayer = MinecraftClient.getInstance().player;
- if (clientPlayer != null) {
- if (Objects.equals(entity, clientPlayer) || Objects.equals(((PlayerEntity)entity).getGameProfile(), clientPlayer.getGameProfile())) {
- Channel.broadcastPonyData(new MsgPonyData(getMetadata(), defaulted));
- }
- }
- PonyDataCallback.EVENT.invoker().onPonyDataAvailable((PlayerEntity)entity, getMetadata(), defaulted, EnvType.CLIENT);
- }
+ public boolean hasMetadata() {
+ return metadata.isPresent();
}
@Override
- public boolean isCrouching(LivingEntity entity) {
-
- boolean isSneak = entity.isInSneakingPose();
- boolean isFlying = isFlying(entity);
- boolean isSwimming = isSwimming(entity);
-
- return !isPerformingRainboom(entity) && !isSwimming && isSneak && !isFlying;
- }
-
- private boolean isPerformingRainboom(LivingEntity entity) {
- Vec3d motion = entity.getVelocity();
- double zMotion = Math.sqrt(motion.x * motion.x + motion.z * motion.z);
-
- return (isFlying(entity) && getRace().hasWings()) || entity.isFallFlying() & zMotion > 0.4F;
+ public Race race() {
+ return PonyConfig.getEffectiveRace(metadata().getRace());
}
@Override
- public boolean isFlying(LivingEntity entity) {
- return !(isOnGround(entity)
- || entity.hasVehicle()
- || (entity.isClimbing() && !(entity instanceof PlayerEntity && ((PlayerEntity)entity).getAbilities().allowFlying))
- || entity.isSubmergedInWater()
- || entity.isSleeping());
- }
-
- /**
- * Checks if the entity is on the ground, or close enough to be "effectively" grounded.
- * this is to keep Pegasus wings from flapping in odd situations (Hypixel).
- */
- private boolean isOnGround(LivingEntity entity) {
- if (entity.isOnGround()) {
- return true;
- }
-
- BlockState below = entity.getEntityWorld()
- .getBlockState(entity.getBlockPos().down(1));
-
- // Check for stairs so we can keep Pegasi from flailing their wings as they descend
- double offsetAmount = below.getBlock() instanceof StairsBlock ? 1 : 0.05;
-
- Vec3d pos = entity.getPos();
- BlockPos blockpos = new BlockPos(
- Math.floor(pos.x),
- Math.floor(pos.y - offsetAmount),
- Math.floor(pos.z));
-
- return !entity.getEntityWorld().isAir(blockpos);
- }
-
- @Override
- public boolean isSwimming(LivingEntity entity) {
- return entity.isSwimming() || entity.isInSwimmingPose();
- }
-
- @Override
- public boolean isPartiallySubmerged(LivingEntity entity) {
- return entity.isSubmergedInWater()
- || entity.getEntityWorld().getBlockState(entity.getBlockPos()).getMaterial() == Material.WATER;
- }
-
- protected Vec3d getVisualEyePosition(LivingEntity entity) {
- Size size = entity.isBaby() ? Sizes.FOAL : getMetadata().getSize();
-
- return new Vec3d(
- entity.getX(),
- entity.getY() + (double) entity.getEyeHeight(entity.getPose()) * size.getScaleFactor(),
- entity.getZ()
- );
- }
-
- @Override
- public Race getRace() {
- return PonyConfig.getEffectiveRace(getMetadata().getRace());
- }
-
- @Override
- public Identifier getTexture() {
+ public Identifier texture() {
return texture;
}
@Override
- public IPonyData getMetadata() {
+ public IPonyData metadata() {
return metadata.get(PonyData.NULL);
}
- @Override
- public boolean isSitting(LivingEntity entity) {
- return entity.hasVehicle();
- }
-
- @Override
- public boolean isRidingInteractive(LivingEntity entity) {
-
- if (isSitting(entity) && entity.getVehicle() instanceof LivingEntity) {
- return PonyRenderDispatcher.getInstance().getPonyRenderer((LivingEntity) entity.getVehicle()) != null;
- }
-
- return false;
- }
-
- @Override
- public IPony getMountedPony(LivingEntity entity) {
- if (entity.hasVehicle() && entity.getVehicle() instanceof LivingEntity) {
- LivingEntity mount = (LivingEntity) entity.getVehicle();
-
- IPonyRenderContext render = PonyRenderDispatcher.getInstance().getPonyRenderer(mount);
-
- return render == null ? null : render.getEntityPony(mount);
- }
- return null;
- }
-
- @Override
- public Vec3d getAbsoluteRidingOffset(LivingEntity entity) {
- IPony ridingPony = getMountedPony(entity);
-
- if (ridingPony != null) {
- LivingEntity ridee = (LivingEntity)entity.getVehicle();
-
- Vec3d offset = PonyTransformation.forSize(ridingPony.getMetadata().getSize()).getRiderOffset();
- float scale = ridingPony.getMetadata().getSize().getScaleFactor();
-
- return ridingPony.getAbsoluteRidingOffset(ridee)
- .add(0, offset.y - ridee.getHeight() * 1/scale, 0);
- }
-
- float delta = MinecraftClient.getInstance().getTickDelta();
-
- Entity vehicle = entity.getVehicle();
- double vehicleOffset = vehicle == null ? 0 : vehicle.getHeight() - vehicle.getMountedHeightOffset();
-
- return new Vec3d(
- MathHelper.lerp(delta, entity.prevX, entity.getX()),
- MathHelper.lerp(delta, entity.prevY, entity.getY()) + vehicleOffset,
- MathHelper.lerp(delta, entity.prevZ, entity.getZ())
- );
- }
-
- @Override
- public Box getComputedBoundingBox(LivingEntity entity) {
- float scale = getMetadata().getSize().getScaleFactor() + 0.1F;
-
- Vec3d pos = getAbsoluteRidingOffset(entity);
-
- float width = entity.getWidth() * scale;
-
- return new Box(
- - width, (entity.getHeight() * scale), -width,
- width, 0, width).offset(pos);
- }
-
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("texture", texture)
.add("metadata", metadata)
+ .add("defaulted", defaulted)
.toString();
}
public interface RegistrationHandler {
- boolean shouldUpdateRegistration(Pony pony);
+ boolean shouldUpdateRegistration(IPony pony);
}
}
diff --git a/src/main/java/com/minelittlepony/client/pony/PonyManager.java b/src/main/java/com/minelittlepony/client/pony/PonyManager.java
index 97d17532..4ab38f3a 100644
--- a/src/main/java/com/minelittlepony/client/pony/PonyManager.java
+++ b/src/main/java/com/minelittlepony/client/pony/PonyManager.java
@@ -6,6 +6,8 @@ import com.google.common.cache.LoadingCache;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.IPonyManager;
import com.minelittlepony.client.MineLittlePony;
+import com.minelittlepony.client.render.IPonyRenderContext;
+import com.minelittlepony.client.render.PonyRenderDispatcher;
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer;
import com.minelittlepony.settings.PonyConfig;
import com.minelittlepony.settings.PonyLevel;
@@ -15,9 +17,12 @@ import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.util.DefaultSkinHelper;
import net.minecraft.resource.ResourceManager;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;
+import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@@ -41,12 +46,28 @@ public class PonyManager implements IPonyManager, SimpleSynchronousResourceReloa
this.config = config;
}
+ @Override
+ public Optional getPony(@Nullable Entity entity) {
+ if (entity instanceof PlayerEntity player) {
+ return Optional.of(getPony(player));
+ }
+
+ if (entity instanceof LivingEntity living) {
+ IPonyRenderContext dispatcher = PonyRenderDispatcher.getInstance().getPonyRenderer(living);
+ if (dispatcher != null) {
+ return Optional.of(dispatcher.getEntityPony(living));
+ }
+ }
+
+ return Optional.empty();
+ }
+
@Override
public IPony getPony(Identifier resource) {
try {
return poniesCache.get(resource);
} catch (ExecutionException e) {
- return new Pony(resource, Memoize.of(PonyData.NULL));
+ return new Pony(resource, PonyData.MEM_NULL);
}
}
@@ -83,7 +104,7 @@ public class PonyManager implements IPonyManager, SimpleSynchronousResourceReloa
public IPony getPony(Identifier resource, UUID uuid) {
IPony pony = getPony(resource);
- if (config.ponyLevel.get() == PonyLevel.PONIES && pony.getMetadata().getRace().isHuman()) {
+ if (config.ponyLevel.get() == PonyLevel.PONIES && pony.metadata().getRace().isHuman()) {
return getBackgroundPony(uuid);
}
@@ -93,7 +114,7 @@ public class PonyManager implements IPonyManager, SimpleSynchronousResourceReloa
@Override
public IPony getDefaultPony(UUID uuid) {
if (config.ponyLevel.get() != PonyLevel.PONIES) {
- return ((Pony)getPony(DefaultSkinHelper.getTexture(uuid))).defaulted();
+ return ((Pony)getPony(DefaultSkinHelper.getTexture(uuid))).markDefaulted();
}
return getBackgroundPony(uuid);
@@ -101,7 +122,7 @@ public class PonyManager implements IPonyManager, SimpleSynchronousResourceReloa
@Override
public IPony getBackgroundPony(UUID uuid) {
- return ((Pony)getPony(MineLittlePony.getInstance().getVariatedTextures().get(BACKGROUND_PONIES, uuid))).defaulted();
+ return ((Pony)getPony(MineLittlePony.getInstance().getVariatedTextures().get(BACKGROUND_PONIES, uuid))).markDefaulted();
}
@Override
diff --git a/src/main/java/com/minelittlepony/client/render/DebugBoundingBoxRenderer.java b/src/main/java/com/minelittlepony/client/render/DebugBoundingBoxRenderer.java
index b471692f..12699fe8 100644
--- a/src/main/java/com/minelittlepony/client/render/DebugBoundingBoxRenderer.java
+++ b/src/main/java/com/minelittlepony/client/render/DebugBoundingBoxRenderer.java
@@ -13,6 +13,7 @@ import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import com.minelittlepony.api.pony.IPony;
+import com.minelittlepony.client.PonyBounds;
public final class DebugBoundingBoxRenderer {
@@ -29,7 +30,7 @@ public final class DebugBoundingBoxRenderer {
stack.push();
stack.translate(-offset.x, -offset.y, -offset.z);
- Box boundingBox = pony.getComputedBoundingBox(entity);
+ Box boundingBox = PonyBounds.getBoundingBox(pony, entity);
Vec3d pos = entity.getPos();
diff --git a/src/main/java/com/minelittlepony/client/render/EquineRenderManager.java b/src/main/java/com/minelittlepony/client/render/EquineRenderManager.java
index 7135ea49..08a0bf93 100644
--- a/src/main/java/com/minelittlepony/client/render/EquineRenderManager.java
+++ b/src/main/java/com/minelittlepony/client/render/EquineRenderManager.java
@@ -2,9 +2,13 @@ package com.minelittlepony.client.render;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.pony.IPony;
+import com.minelittlepony.api.pony.network.MsgPonyData;
+import com.minelittlepony.api.pony.network.fabric.Channel;
+import com.minelittlepony.api.pony.network.fabric.PonyDataCallback;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.client.model.ModelWrapper;
+import com.minelittlepony.client.pony.Pony;
import com.minelittlepony.client.transform.PonyPosture;
import com.minelittlepony.mson.api.ModelKey;
import com.minelittlepony.util.MathUtil;
@@ -12,13 +16,18 @@ import com.mojang.blaze3d.platform.GlStateManager.DstFactor;
import com.mojang.blaze3d.platform.GlStateManager.SrcFactor;
import com.mojang.blaze3d.systems.RenderSystem;
+import java.util.Objects;
+
import org.jetbrains.annotations.NotNull;
+import net.fabricmc.api.EnvType;
+import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Frustum;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
+import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;
public class EquineRenderManager & IPonyModel> {
@@ -146,18 +155,32 @@ public class EquineRenderManager extends Frustum {
@@ -29,11 +29,7 @@ public class FrustrumCheck extends Frustum {
@Override
public boolean isVisible(Box bounds) {
- IPony pony = renderer.getPony(entity);
-
- Box boundingBox = pony.getComputedBoundingBox(entity);
-
- return vanilla.isVisible(boundingBox);
+ return vanilla.isVisible(PonyBounds.getBoundingBox(renderer.getPony(entity), entity));
}
@Override
diff --git a/src/main/java/com/minelittlepony/client/render/IPonyRenderContext.java b/src/main/java/com/minelittlepony/client/render/IPonyRenderContext.java
index 5900b9b0..39655baf 100644
--- a/src/main/java/com/minelittlepony/client/render/IPonyRenderContext.java
+++ b/src/main/java/com/minelittlepony/client/render/IPonyRenderContext.java
@@ -27,10 +27,10 @@ public interface IPonyRenderContext key.getKey(false).createModel());
- ponyHead.setMetadata(pony.getMetadata());
+ ponyHead.setMetadata(pony.metadata());
return true;
}
diff --git a/src/main/java/com/minelittlepony/client/render/entity/PlayerPonyRenderer.java b/src/main/java/com/minelittlepony/client/render/entity/PlayerPonyRenderer.java
index 5bd55b85..b1a75f99 100644
--- a/src/main/java/com/minelittlepony/client/render/entity/PlayerPonyRenderer.java
+++ b/src/main/java/com/minelittlepony/client/render/entity/PlayerPonyRenderer.java
@@ -99,7 +99,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
// (shadows are drawn after us)
if (!entity.hasVehicle() && !entity.isSleeping()) {
float yaw = MathHelper.lerpAngleDegrees(tickDelta, entity.prevBodyYaw, entity.bodyYaw);
- float l = entity.getWidth() / 2 * manager.getPony(entity).getMetadata().getSize().getScaleFactor();
+ float l = entity.getWidth() / 2 * manager.getPony(entity).metadata().getSize().getScaleFactor();
stack.multiply(RotationAxis.NEGATIVE_Y.rotationDegrees(yaw));
stack.translate(0, 0, -l);
@@ -178,7 +178,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
@Override
public Identifier getTexture(AbstractClientPlayerEntity player) {
- return manager.getPony(player).getTexture();
+ return manager.getPony(player).texture();
}
@Override
diff --git a/src/main/java/com/minelittlepony/client/render/entity/PlayerSeaponyRenderer.java b/src/main/java/com/minelittlepony/client/render/entity/PlayerSeaponyRenderer.java
index 3342b1ee..9f402ba8 100644
--- a/src/main/java/com/minelittlepony/client/render/entity/PlayerSeaponyRenderer.java
+++ b/src/main/java/com/minelittlepony/client/render/entity/PlayerSeaponyRenderer.java
@@ -1,6 +1,7 @@
package com.minelittlepony.client.render.entity;
import com.minelittlepony.api.pony.IPony;
+import com.minelittlepony.api.pony.PonyPosture;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.client.model.ClientPonyModel;
@@ -35,12 +36,12 @@ public class PlayerSeaponyRenderer extends PlayerPonyRenderer {
public IPony getEntityPony(AbstractClientPlayerEntity player) {
IPony pony = super.getEntityPony(player);
- boolean wet = pony.isPartiallySubmerged(player);
+ boolean wet = PonyPosture.isPartiallySubmerged(player);
model = manager.setModel(wet ? seapony : normalPony).body();
float state = wet ? 100 : 0;
- float interpolated = pony.getMetadata().getInterpolator(player.getUuid()).interpolate("seapony_state", state, 5);
+ float interpolated = pony.metadata().getInterpolator(player.getUuid()).interpolate("seapony_state", state, 5);
if (!MathUtil.compareFloats(interpolated, state)) {
double x = player.getX() + (player.getEntityWorld().getRandom().nextFloat() * 2) - 1;
diff --git a/src/main/java/com/minelittlepony/client/render/entity/feature/ElytraFeature.java b/src/main/java/com/minelittlepony/client/render/entity/feature/ElytraFeature.java
index 963aee2b..38ae2dc3 100644
--- a/src/main/java/com/minelittlepony/client/render/entity/feature/ElytraFeature.java
+++ b/src/main/java/com/minelittlepony/client/render/entity/feature/ElytraFeature.java
@@ -1,6 +1,7 @@
package com.minelittlepony.client.render.entity.feature;
import com.minelittlepony.api.model.BodyPart;
+import com.minelittlepony.api.pony.PonyPosture;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.PonyElytra;
@@ -43,7 +44,7 @@ public class ElytraFeature & IP
getContextModel().copyStateTo(elytra);
if (elytra instanceof PonyElytra) {
- ((PonyElytra)elytra).isSneaking = getContext().getEntityPony(entity).isCrouching(entity);
+ ((PonyElytra)elytra).isSneaking = PonyPosture.isCrouching(getContext().getEntityPony(entity), entity);
}
elytra.setAngles(entity, limbDistance, limbAngle, age, headYaw, headPitch);
diff --git a/src/main/java/com/minelittlepony/client/render/entity/npc/AbstractNpcRenderer.java b/src/main/java/com/minelittlepony/client/render/entity/npc/AbstractNpcRenderer.java
index a64cb666..ea530376 100644
--- a/src/main/java/com/minelittlepony/client/render/entity/npc/AbstractNpcRenderer.java
+++ b/src/main/java/com/minelittlepony/client/render/entity/npc/AbstractNpcRenderer.java
@@ -57,7 +57,7 @@ abstract class AbstractNpcRenderer
}
public void render(T entity, float entityYaw, float tickDelta, MatrixStack stack, VertexConsumerProvider renderContext, int lightUv) {
- model = manager.setModel(models.computeIfAbsent(getEntityPony(entity).getRace(), this::createModel)).body();
+ model = manager.setModel(models.computeIfAbsent(getEntityPony(entity).race(), this::createModel)).body();
super.render(entity, entityYaw, tickDelta, stack, renderContext, lightUv);
}