From 960b98eac9a06ce18522dbe919391edb62985140 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 8 Dec 2022 20:53:30 +0000 Subject: [PATCH] A bunch of refactoring and cleaning up of old patterns --- .../api/model/ModelAttributes.java | 11 +- .../com/minelittlepony/api/pony/IPony.java | 74 +------ .../minelittlepony/api/pony/IPonyManager.java | 11 + .../minelittlepony/api/pony/PonyPosture.java | 85 ++++++++ .../api/pony/network/fabric/Channel.java | 2 +- .../pony/network/fabric/PonyDataCallback.java | 2 +- .../com/minelittlepony/client/HorseCam.java | 2 +- .../com/minelittlepony/client/PonyBounds.java | 50 +++++ .../com/minelittlepony/client/SkinsProxy.java | 2 +- .../client/hdskins/DummyPony.java | 5 +- .../client/hdskins/PonyPreview.java | 2 +- .../client/mixin/MixinCamera.java | 4 +- .../client/mixin/MixinClientPlayerEntity.java | 4 +- .../client/mixin/MixinDefaultPlayerSkin.java | 2 +- .../mixin/MixinEntityRenderDispatcher.java | 2 +- .../com/minelittlepony/client/pony/Pony.java | 194 +----------------- .../client/pony/PonyManager.java | 29 ++- .../render/DebugBoundingBoxRenderer.java | 3 +- .../client/render/EquineRenderManager.java | 31 ++- .../client/render/FrustrumCheck.java | 8 +- .../client/render/IPonyRenderContext.java | 4 +- .../client/render/LevitatingItemRenderer.java | 4 +- .../render/blockentity/skull/MobSkull.java | 2 +- .../blockentity/skull/PlayerPonySkull.java | 6 +- .../render/entity/PlayerPonyRenderer.java | 4 +- .../render/entity/PlayerSeaponyRenderer.java | 5 +- .../render/entity/feature/ElytraFeature.java | 3 +- .../entity/npc/AbstractNpcRenderer.java | 2 +- 28 files changed, 255 insertions(+), 298 deletions(-) create mode 100644 src/main/java/com/minelittlepony/api/pony/PonyPosture.java create mode 100644 src/main/java/com/minelittlepony/client/PonyBounds.java 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); }