diff --git a/src/main/java/com/minelittlepony/api/config/PonyConfig.java b/src/main/java/com/minelittlepony/api/config/PonyConfig.java index 18879d08..1dd18610 100644 --- a/src/main/java/com/minelittlepony/api/config/PonyConfig.java +++ b/src/main/java/com/minelittlepony/api/config/PonyConfig.java @@ -52,6 +52,8 @@ public class PonyConfig extends Config { public final Setting frustrum = value("settings", "frustrum", true) .addComment("Adjust camera intersection checks to properly cull entities when they're not in view.") .addComment("Helps to prevent entities from vanishing when they're in long stacks"); + public final Setting horsieMode = value("settings", "horsieMode", false) + .addComment("Enables the alternative horsey models from the April Fools 2023 update"); public final Setting sizeOverride = value("debug", "sizeOverride", Sizes.UNSET) .addComment("Overrides pony sizes") diff --git a/src/main/java/com/minelittlepony/api/model/ModelAttributes.java b/src/main/java/com/minelittlepony/api/model/ModelAttributes.java index 3a23165f..faf7dd16 100644 --- a/src/main/java/com/minelittlepony/api/model/ModelAttributes.java +++ b/src/main/java/com/minelittlepony/api/model/ModelAttributes.java @@ -1,8 +1,7 @@ package com.minelittlepony.api.model; import com.minelittlepony.api.pony.*; -import com.minelittlepony.client.IPreviewModel; -import com.minelittlepony.client.SkinsProxy; +import com.minelittlepony.client.*; import com.minelittlepony.client.pony.PonyData; import com.minelittlepony.common.util.animation.Interpolator; import com.minelittlepony.util.MathUtil; @@ -64,6 +63,10 @@ public class ModelAttributes { * Flag indicating that this model is performing a rainboom (flight). */ public boolean isGoingFast; + /** + * Flag indicating that this model should mimic the vanilla horse models. + */ + public boolean isHorsey; /** * Vertical pitch whilst flying. @@ -149,6 +152,7 @@ public class ModelAttributes { interpolatorId = entity.getUuid(); } isLeftHanded = entity.getMainArm() == Arm.LEFT; + isHorsey = MineLittlePony.getInstance().getConfig().horsieMode.get(); featureSkins = SkinsProxy.instance.getAvailableSkins(entity); } diff --git a/src/main/java/com/minelittlepony/client/GuiPonySettings.java b/src/main/java/com/minelittlepony/client/GuiPonySettings.java index a0568d9a..8b789489 100644 --- a/src/main/java/com/minelittlepony/client/GuiPonySettings.java +++ b/src/main/java/com/minelittlepony/client/GuiPonySettings.java @@ -1,10 +1,12 @@ package com.minelittlepony.client; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.*; import com.minelittlepony.client.render.MobRenderers; +import com.minelittlepony.client.render.PonyRenderDispatcher; import com.minelittlepony.client.settings.ClientPonyConfig; import com.minelittlepony.common.client.gui.GameGui; import com.minelittlepony.common.client.gui.ScrollContainer; @@ -113,7 +115,12 @@ public class GuiPonySettings extends GameGui { boolean enabled = i != config.fillycam || allowCameraChange; Button button = content .addButton(new Toggle(LEFT, row += 20, ((Setting)i).get())) - .onChange((Setting)i) + .onChange(i == config.horsieMode ? (v -> { + v = ((Setting)i).set(v); + + PonyRenderDispatcher.getInstance().initialise(MinecraftClient.getInstance().getEntityRenderDispatcher(), true); + return v; + }) : (Setting)i) .setEnabled(enabled); button.getStyle().setText(OPTIONS_PREFIX + i.name().toLowerCase()); if (!enabled) { diff --git a/src/main/java/com/minelittlepony/client/MineLittlePony.java b/src/main/java/com/minelittlepony/client/MineLittlePony.java index 0b011afb..5c245808 100644 --- a/src/main/java/com/minelittlepony/client/MineLittlePony.java +++ b/src/main/java/com/minelittlepony/client/MineLittlePony.java @@ -94,7 +94,7 @@ public class MineLittlePony implements ClientModInitializer { } private void onClientReady(MinecraftClient client) { - renderManager.initialise(client.getEntityRenderDispatcher()); + renderManager.initialise(client.getEntityRenderDispatcher(), false); } private void onTick(MinecraftClient client) { diff --git a/src/main/java/com/minelittlepony/client/model/AbstractPonyModel.java b/src/main/java/com/minelittlepony/client/model/AbstractPonyModel.java index 7f137d8d..37bc43ee 100644 --- a/src/main/java/com/minelittlepony/client/model/AbstractPonyModel.java +++ b/src/main/java/com/minelittlepony/client/model/AbstractPonyModel.java @@ -6,6 +6,7 @@ import com.minelittlepony.api.pony.meta.Sizes; import com.minelittlepony.client.transform.PonyTransformation; import com.minelittlepony.client.util.render.RenderList; import com.minelittlepony.util.MathUtil; +import com.minelittlepony.util.MathUtil.Angles; import java.util.ArrayList; import java.util.List; @@ -37,6 +38,9 @@ public abstract class AbstractPonyModel extends ClientPo public static final Pivot BACK_LEGS_SLEEPING = new Pivot(0, 2, -6); protected final ModelPart neck; + private final ModelPart mane; + private final ModelPart nose; + private final ModelPart tailStub; public final RenderList helmetRenderList; protected final RenderList neckRenderList; @@ -55,6 +59,9 @@ public abstract class AbstractPonyModel extends ClientPo super(tree); neck = tree.getChild("neck"); + mane = neck.getChild("mane"); + nose = head.getChild("nose"); + tailStub = body.getChild("tail_stub"); mainRenderList = RenderList.of() .add(withStage(BodyPart.BODY, bodyRenderList = RenderList.of(body).add(body::rotate))) .add(withStage(BodyPart.NECK, neckRenderList = RenderList.of(neck))) @@ -105,7 +112,7 @@ public abstract class AbstractPonyModel extends ClientPo PonyModelPrepareCallback.EVENT.invoker().onPonyModelPrepared(entity, this, ModelAttributes.Mode.OTHER); super.setAngles(entity, limbAngle, limbSpeed, animationProgress, headYaw, headPitch); - head.setPivot(head.getDefaultTransform().pivotX, head.getDefaultTransform().pivotY, head.getDefaultTransform().pivotZ); + resetPivot(head, neck, leftArm, rightArm, leftLeg, rightLeg); setModelAngles(entity, limbAngle, limbSpeed, animationProgress, headYaw, headPitch); @@ -148,9 +155,6 @@ public abstract class AbstractPonyModel extends ClientPo } else { adjustBody(0, ORIGIN); - rightLeg.pivotY = FRONT_LEGS_Y; - leftLeg.pivotY = FRONT_LEGS_Y; - if (!attributes.isSleeping) { animateBreathing(animationProgress); } @@ -165,6 +169,12 @@ public abstract class AbstractPonyModel extends ClientPo ponySleep(); } + if (attributes.isHorsey) { + head.pivotY -= 3; + head.pivotZ -= 2; + head.pitch = 0.5F; + } + parts.forEach(part -> part.setPartAngles(attributes, limbAngle, limbSpeed, wobbleAmount, animationProgress)); } @@ -183,9 +193,6 @@ public abstract class AbstractPonyModel extends ClientPo rightArm.pitch -= LEG_SNEAKING_PITCH_ADJUSTMENT; leftArm.pitch -= LEG_SNEAKING_PITCH_ADJUSTMENT; - - leftLeg.pivotY = FRONT_LEGS_Y; - rightLeg.pivotY = FRONT_LEGS_Y; } protected void ponySleep() { @@ -275,6 +282,9 @@ public abstract class AbstractPonyModel extends ClientPo leftArm.pivotZ = 2 - sin; float legRPX = attributes.getMainInterpolator().interpolate("legOffset", cos - getLegOutset() - 0.001F, 2); + if (attributes.isHorsey) { + legRPX += 2; + } rightArm.pivotX = -legRPX; rightLeg.pivotX = -legRPX; @@ -285,8 +295,12 @@ public abstract class AbstractPonyModel extends ClientPo rightArm.yaw += body.yaw; leftArm.yaw += body.yaw; - rightArm.pivotY = leftArm.pivotY = 8; - rightLeg.pivotZ = leftLeg.pivotZ = 11; + if (attributes.isHorsey) { + rightArm.pivotZ = leftArm.pivotZ = -1; + rightArm.pivotY = leftArm.pivotY = 6; + rightLeg.pivotZ = leftLeg.pivotZ = 19; + rightLeg.pivotY = leftLeg.pivotY = 6; + } } /** @@ -517,7 +531,14 @@ public abstract class AbstractPonyModel extends ClientPo protected void adjustBody(float pitch, Pivot pivot) { adjustBodyComponents(pitch, pivot); - neck.setPivot(NECK_X + pitch, pivot.y(), pivot.z()); + if (!attributes.isHorsey) { + neck.setPivot(NECK_X + pitch, pivot.y(), pivot.z()); + rightLeg.pivotY = FRONT_LEGS_Y; + leftLeg.pivotY = FRONT_LEGS_Y; + } else { + neck.setPivot(NECK_X + pitch, pivot.y() - 1, pivot.z() - 2); + neck.pitch = Angles._30_DEG; + } } protected void adjustBodyComponents(float pitch, Pivot pivot) { @@ -541,16 +562,33 @@ public abstract class AbstractPonyModel extends ClientPo public void setVisible(boolean visible) { super.setVisible(visible); neck.visible = visible; + hat.visible &= !attributes.isHorsey; + mane.visible = attributes.isHorsey; + nose.visible = attributes.isHorsey; + tailStub.visible = !attributes.isHorsey; parts.forEach(part -> part.setVisible(visible, attributes)); } @Override public void transform(BodyPart part, MatrixStack stack) { + + if (attributes.isHorsey) { + stack.translate(0, 0.1F, 0); + } + if (attributes.isSleeping || attributes.isRiptide) { stack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90)); stack.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180)); } + if (attributes.isHorsey) { + if (part == BodyPart.BODY) { + stack.scale(1.5F, 1, 1.5F); + } + + neck.visible = head.visible; + } + PonyTransformation.forSize(getSize()).transform(this, part, stack); } } diff --git a/src/main/java/com/minelittlepony/client/model/ClientPonyModel.java b/src/main/java/com/minelittlepony/client/model/ClientPonyModel.java index 116b6458..38e3b47b 100644 --- a/src/main/java/com/minelittlepony/client/model/ClientPonyModel.java +++ b/src/main/java/com/minelittlepony/client/model/ClientPonyModel.java @@ -106,6 +106,16 @@ public abstract class ClientPonyModel extends MsonPlayer } + static void resetPivot(ModelPart part) { + part.setPivot(part.getDefaultTransform().pivotX, part.getDefaultTransform().pivotY, part.getDefaultTransform().pivotZ); + } + + static void resetPivot(ModelPart...parts) { + for (ModelPart part : parts) { + resetPivot(part); + } + } + public interface PosingCallback { void poseModel(ClientPonyModel model, float move, float swing, float ticks, T entity); } diff --git a/src/main/java/com/minelittlepony/client/model/ModelKeyImpl.java b/src/main/java/com/minelittlepony/client/model/ModelKeyImpl.java new file mode 100644 index 00000000..ece1b60c --- /dev/null +++ b/src/main/java/com/minelittlepony/client/model/ModelKeyImpl.java @@ -0,0 +1,106 @@ +package com.minelittlepony.client.model; + +import net.minecraft.client.model.Model; +import net.minecraft.client.model.ModelPart; +import net.minecraft.util.Identifier; +import net.minecraft.util.Util; + +import com.google.common.base.Preconditions; +import com.minelittlepony.client.MineLittlePony; +import com.minelittlepony.mson.api.*; +import com.minelittlepony.mson.api.MsonModel.Factory; +import com.minelittlepony.mson.api.model.traversal.PartSkeleton; +import com.minelittlepony.mson.api.model.traversal.SkeletonisedModel; +import com.minelittlepony.mson.api.parser.FileContent; +import com.minelittlepony.mson.api.parser.locals.LocalBlock; +import com.minelittlepony.mson.impl.model.RootContext; + +import java.util.*; +import java.util.concurrent.CompletableFuture; + +final class ModelKeyImpl implements ModelKey, LocalBlock { + + private final Map> horseModeValues = Util.make(new HashMap<>(), map -> { + map.put("head_elongation", Incomplete.completed(-1F)); + map.put("neck_dilate_z", Incomplete.completed(1.5F)); + map.put("neck_dilate_y", Incomplete.completed(3F)); + map.put("global_ear_shortening", Incomplete.completed(-0.5F)); + }); + + private final ModelKey key; + private final MsonModel.Factory constr; + + ModelKeyImpl(Identifier id, MsonModel.Factory constr) { + this.key = Mson.getInstance().registerModel(id, constr); + this.constr = constr; + } + + @Override + public Identifier getId() { + return key.getId(); + } + + @SuppressWarnings("unchecked") + @Override + public V createModel() { + return (V)createModel(constr); + } + + @Override + public V createModel(Factory factory) { + Preconditions.checkNotNull(factory, "Factory should not be null"); + + return getModelData().map(content -> { + + ModelContext ctx = getModelContext(content); + + ModelPart root = ctx.toTree(); + V t = factory.create(root); + + if (t instanceof SkeletonisedModel) { + ((SkeletonisedModel)t).setSkeleton(content.getSkeleton() + .map(s -> PartSkeleton.of(root, s)) + .orElseGet(() -> PartSkeleton.of(root))); + } + if (t instanceof MsonModel) { + if (ctx instanceof RootContext) { + ((RootContext)ctx).setModel(t); + } + ((MsonModel)t).init(ctx); + } + return t; + }) + .orElseThrow(() -> new IllegalStateException("Model file for " + getId() + " was not loaded!")); + } + + @Override + public Optional createTree() { + return getModelData().map(this::getModelContext).map(ModelContext::toTree); + } + + private ModelContext getModelContext(FileContent content) { + if (MineLittlePony.getInstance().getConfig().horsieMode.get()) { + return content.createContext(null, null, content.getLocals().extendWith(getId(), Optional.of(this), Optional.empty()).bake()); + } + return content.createContext(null, null, content.getLocals().bake()); + } + + @Override + public Optional> getModelData() { + return key.getModelData(); + } + + @Override + public Set appendKeys(Set output) { + output.addAll(horseModeValues.keySet()); + return output; + } + + @Override + public Optional>> get(String name) { + if (horseModeValues.containsKey(name)) { + return Optional.of(CompletableFuture.completedFuture(horseModeValues.get(name))); + } + return Optional.empty(); + } +} \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/client/model/ModelType.java b/src/main/java/com/minelittlepony/client/model/ModelType.java index 09556292..256a8c2f 100644 --- a/src/main/java/com/minelittlepony/client/model/ModelType.java +++ b/src/main/java/com/minelittlepony/client/model/ModelType.java @@ -68,7 +68,7 @@ public final class ModelType { public static final PlayerModelKey> ALICORN = registerPlayer("alicorn", Race.ALICORN, AlicornModel::new); public static final PlayerModelKey> UNICORN = registerPlayer("unicorn", Race.UNICORN, UnicornModel::new); - public static final PlayerModelKey> KIRIN = registerPlayer("kirin", Race.KIRIN, UnicornModel::new); + public static final PlayerModelKey> KIRIN = registerPlayer("kirin", Race.KIRIN, KirinModel::new); public static final PlayerModelKey> PEGASUS = registerPlayer("pegasus", Race.PEGASUS, PegasusModel::new); public static final PlayerModelKey> GRYPHON = registerPlayer("gryphon", Race.GRYPHON, PegasusModel::new); public static final PlayerModelKey> HIPPOGRIFF = registerPlayer("hippogriff", Race.HIPPOGRIFF, PegasusModel::new); @@ -113,7 +113,7 @@ public final class ModelType { } static ModelKey register(String name, MsonModel.Factory constructor) { - return Mson.getInstance().registerModel(new Identifier("minelittlepony", name), constructor); + return new ModelKeyImpl(new Identifier("minelittlepony", name), constructor); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/minelittlepony/client/model/PlayerModelKey.java b/src/main/java/com/minelittlepony/client/model/PlayerModelKey.java index acb9007d..0ec71298 100644 --- a/src/main/java/com/minelittlepony/client/model/PlayerModelKey.java +++ b/src/main/java/com/minelittlepony/client/model/PlayerModelKey.java @@ -12,9 +12,7 @@ import org.jetbrains.annotations.Nullable; import com.minelittlepony.api.model.IModel; import com.minelittlepony.client.model.armour.PonyArmourModel; -import com.minelittlepony.mson.api.ModelKey; -import com.minelittlepony.mson.api.Mson; -import com.minelittlepony.mson.api.MsonModel; +import com.minelittlepony.mson.api.*; import java.util.function.*; @@ -26,8 +24,8 @@ public record PlayerModelKey modelFactory, RendererFactory rendererFactory, MsonModel.Factory> armorFactory) { this( - Mson.getInstance().registerModel(new Identifier("minelittlepony", "races/steve/" + name), tree -> modelFactory.apply(tree, false)), - Mson.getInstance().registerModel(new Identifier("minelittlepony", "races/alex/" + name), tree -> modelFactory.apply(tree, true)), + new ModelKeyImpl<>(new Identifier("minelittlepony", "races/steve/" + name), tree -> modelFactory.apply(tree, false)), + new ModelKeyImpl<>(new Identifier("minelittlepony", "races/alex/" + name), tree -> modelFactory.apply(tree, true)), rendererFactory, armorFactory ); diff --git a/src/main/java/com/minelittlepony/client/model/entity/race/KirinModel.java b/src/main/java/com/minelittlepony/client/model/entity/race/KirinModel.java new file mode 100644 index 00000000..dead6554 --- /dev/null +++ b/src/main/java/com/minelittlepony/client/model/entity/race/KirinModel.java @@ -0,0 +1,23 @@ +package com.minelittlepony.client.model.entity.race; + +import net.minecraft.client.model.ModelPart; +import net.minecraft.entity.LivingEntity; + +import com.minelittlepony.api.model.Pivot; + +public class KirinModel extends UnicornModel { + + private final ModelPart beard; + + public KirinModel(ModelPart tree, boolean smallArms) { + super(tree, smallArms); + beard = neck.getChild("beard"); + } + + @Override + protected void adjustBody(float pitch, Pivot pivot) { + super.adjustBody(pitch, pivot); + beard.resetTransform(); + beard.pitch -= neck.pitch; + } +} diff --git a/src/main/java/com/minelittlepony/client/model/part/LionTail.java b/src/main/java/com/minelittlepony/client/model/part/LionTail.java index 8528f2ef..ade60d68 100644 --- a/src/main/java/com/minelittlepony/client/model/part/LionTail.java +++ b/src/main/java/com/minelittlepony/client/model/part/LionTail.java @@ -19,6 +19,7 @@ public class LionTail implements IPart { @Override public void setPartAngles(ModelAttributes attributes, float limbAngle, float limbSpeed, float bodySwing, float animationProgress) { + tail.resetTransform(); bodySwing *= 5; @@ -82,6 +83,11 @@ public class LionTail implements IPart { tail4.roll += bend; tail5.roll += bend; tail6.roll += bend; + + if (attributes.isHorsey) { + tail.pivotZ = 14; + tail.pivotY = 7; + } } @Override diff --git a/src/main/java/com/minelittlepony/client/model/part/PonyEars.java b/src/main/java/com/minelittlepony/client/model/part/PonyEars.java index a6b887ad..b28841ae 100644 --- a/src/main/java/com/minelittlepony/client/model/part/PonyEars.java +++ b/src/main/java/com/minelittlepony/client/model/part/PonyEars.java @@ -33,5 +33,15 @@ public class PonyEars implements IPart, MsonModel { public void setVisible(boolean visible, ModelAttributes attributes) { right.visible = visible && !attributes.metadata.getRace().isHuman(); left.visible = visible && !attributes.metadata.getRace().isHuman(); + + if (attributes.isHorsey) { + left.pivotX = -1; + right.pivotX = 1; + left.pivotY = right.pivotY = 1; + left.pivotZ = right.pivotZ = 1.5F; + } else { + left.resetTransform(); + right.resetTransform(); + } } } diff --git a/src/main/java/com/minelittlepony/client/model/part/PonySnout.java b/src/main/java/com/minelittlepony/client/model/part/PonySnout.java index 70d66f81..72ed035c 100644 --- a/src/main/java/com/minelittlepony/client/model/part/PonySnout.java +++ b/src/main/java/com/minelittlepony/client/model/part/PonySnout.java @@ -39,7 +39,9 @@ public class PonySnout implements IPart, MsonModel { @Override public void setVisible(boolean visible, ModelAttributes attributes) { - visible &= !attributes.metadata.getRace().isHuman() && MineLittlePony.getInstance().getConfig().snuzzles.get(); + visible &= !attributes.isHorsey + && !attributes.metadata.getRace().isHuman() + && MineLittlePony.getInstance().getConfig().snuzzles.get(); Gender gender = attributes.metadata.getGender(); mare.visible = (visible && gender.isMare()); diff --git a/src/main/java/com/minelittlepony/client/model/part/PonyTail.java b/src/main/java/com/minelittlepony/client/model/part/PonyTail.java index 57605901..85ee61e7 100644 --- a/src/main/java/com/minelittlepony/client/model/part/PonyTail.java +++ b/src/main/java/com/minelittlepony/client/model/part/PonyTail.java @@ -5,8 +5,7 @@ import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.MathHelper; -import com.minelittlepony.api.model.IPart; -import com.minelittlepony.api.model.ModelAttributes; +import com.minelittlepony.api.model.*; import com.minelittlepony.api.pony.meta.TailShape; import com.minelittlepony.client.model.AbstractPonyModel; import com.minelittlepony.mson.api.*; @@ -21,6 +20,8 @@ public class PonyTail implements IPart, MsonModel { private static final float TAIL_RIDING_Z = 13; private static final float TAIL_SNEAKING_Z = 15; + private static final Pivot HORSEY_TAIL_PIVOT = new Pivot(0, 6, -6); + private ModelPart tail; private AbstractPonyModel model; @@ -90,7 +91,7 @@ public class PonyTail implements IPart, MsonModel { tail.rotate(stack); for (int i = 0; i < segments.size(); i++) { - segments.get(i).render(this, stack, vertices, i, overlayUv, lightUv, red, green, blue, alpha); + segments.get(i).render(this, stack, vertices, i, overlayUv, lightUv, red, green, blue, alpha, attributes); } stack.pop(); @@ -103,14 +104,20 @@ public class PonyTail implements IPart, MsonModel { this.tree = tree; } - public void render(PonyTail tail, MatrixStack stack, VertexConsumer renderContext, int index, int overlayUv, int lightUv, float red, float green, float blue, float alpha) { + public void render(PonyTail tail, MatrixStack stack, VertexConsumer renderContext, int index, int overlayUv, int lightUv, float red, float green, float blue, float alpha, ModelAttributes attributes) { if (index >= tail.tailStop) { return; } - if (tail.shape == TailShape.STRAIGHT) { + if (attributes.isHorsey) { + tree.pitch = 0.5F; + HORSEY_TAIL_PIVOT.set(tree); + } else { + tree.resetTransform(); + } + + if (attributes.isHorsey || tail.shape == TailShape.STRAIGHT) { tree.yaw = 0; - tree.pivotZ = 0; tree.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha); return; } diff --git a/src/main/java/com/minelittlepony/client/render/MobRenderers.java b/src/main/java/com/minelittlepony/client/render/MobRenderers.java index ec7ded80..0f4e9aeb 100644 --- a/src/main/java/com/minelittlepony/client/render/MobRenderers.java +++ b/src/main/java/com/minelittlepony/client/render/MobRenderers.java @@ -83,7 +83,7 @@ public final class MobRenderers { public boolean set(boolean value) { value = option().set(value); - apply(PonyRenderDispatcher.getInstance()); + apply(PonyRenderDispatcher.getInstance(), false); return value; } @@ -95,9 +95,9 @@ public final class MobRenderers { return REGISTRY.computeIfAbsent(name, n -> new MobRenderers(name, changer)); } - void apply(PonyRenderDispatcher dispatcher) { + void apply(PonyRenderDispatcher dispatcher, boolean force) { boolean state = get(); - if (state != lastState) { + if (state != lastState || force) { lastState = state; changer.accept(this, dispatcher); } diff --git a/src/main/java/com/minelittlepony/client/render/PonyRenderDispatcher.java b/src/main/java/com/minelittlepony/client/render/PonyRenderDispatcher.java index ec5a2b15..547a3a28 100644 --- a/src/main/java/com/minelittlepony/client/render/PonyRenderDispatcher.java +++ b/src/main/java/com/minelittlepony/client/render/PonyRenderDispatcher.java @@ -40,13 +40,13 @@ public class PonyRenderDispatcher { /** * Registers all new player skin types. (currently only pony and slimpony). */ - public void initialise(EntityRenderDispatcher manager) { + public void initialise(EntityRenderDispatcher manager, boolean force) { Race.REGISTRY.forEach(r -> { if (!r.isHuman()) { registerPlayerSkin(manager, r); } }); - MobRenderers.REGISTRY.values().forEach(i -> i.apply(this)); + MobRenderers.REGISTRY.values().forEach(i -> i.apply(this, force)); } private void registerPlayerSkin(EntityRenderDispatcher manager, Race race) { diff --git a/src/main/java/com/minelittlepony/util/MathUtil.java b/src/main/java/com/minelittlepony/util/MathUtil.java index 7df0afa2..1c16f559 100644 --- a/src/main/java/com/minelittlepony/util/MathUtil.java +++ b/src/main/java/com/minelittlepony/util/MathUtil.java @@ -6,7 +6,8 @@ public interface MathUtil { interface Angles { float _270_DEG = 270 * MathHelper.RADIANS_PER_DEGREE, - _90_DEG = 90 * MathHelper.RADIANS_PER_DEGREE + _90_DEG = 90 * MathHelper.RADIANS_PER_DEGREE, + _30_DEG = 30 * MathHelper.RADIANS_PER_DEGREE ; } diff --git a/src/main/resources/assets/minelittlepony/lang/en_us.json b/src/main/resources/assets/minelittlepony/lang/en_us.json index f6961b6b..2bd83a93 100644 --- a/src/main/resources/assets/minelittlepony/lang/en_us.json +++ b/src/main/resources/assets/minelittlepony/lang/en_us.json @@ -21,6 +21,7 @@ "minelp.options.ponyskulls": "Pony Skulls", "minelp.options.frustrum": "Frustum checks", "minelp.options.flappyelytras": "Flap Wings whilst Gliding", + "minelp.options.horsiemode": "Horsey Horse Mode", "minelp.options.nofun": "Boring Mode", "minelp.options.button": "Display On Title Screen", "minelp.options.button.on": "Always Display\n\nBoth the pony button and HD Skins button are visible (if installed)", diff --git a/src/main/resources/assets/minelittlepony/models/entity/components/bat_ears.json b/src/main/resources/assets/minelittlepony/models/entity/components/bat_ears.json index 8a6402f4..ffb05ed0 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/components/bat_ears.json +++ b/src/main/resources/assets/minelittlepony/models/entity/components/bat_ears.json @@ -5,6 +5,7 @@ "y": 0, "z": 0, "ear_pronouncement": 0, + "ear_shortening": 0, "ear_spread": 0, "ear_spread_neg": [0, "-", "#ear_spread"] }, @@ -14,7 +15,7 @@ "pivot": ["#x", "#y", "#z"], "rotate": [0, 0, "#ear_spread"], "cubes": [ - { "from": [-4, -8, -1], "size": [2, 2, 2], "dilate": [0, "#ear_pronouncement", 0] }, + { "from": [-4, -8, -1], "size": [2, 2, 2], "dilate": [0, "#ear_pronouncement", "#ear_shortening"] }, { "from": [-3.5, -8.49, 0], "size": [1, 1, 1], "texture": {"u": 0, "v": 3}, "dilate": [0, "#ear_pronouncement", 0] }, { "from": [-2.998, -8.49, -1], "size": [1, 1, 1], "texture": {"u": 0, "v": 5}, "dilate": [0, "#ear_pronouncement", 0] } ] @@ -25,7 +26,7 @@ "mirror": [true, false, false], "rotate": [0, 0, "#ear_spread_neg"], "cubes": [ - { "from": [2, -8, -1], "size": [2, 2, 2], "dilate": [0, "#ear_pronouncement", 0] }, + { "from": [2, -8, -1], "size": [2, 2, 2], "dilate": [0, "#ear_pronouncement", "#ear_shortening"] }, { "from": [2.5, -8.49, 0], "size": [1, 1, 1], "texture": {"u": 0, "v": 3}, "dilate": [0, "#ear_pronouncement", 0] }, { "from": [1.998, -8.49, -1], "size": [1, 1, 1], "texture": {"u": 0, "v": 5}, "dilate": [0, "#ear_pronouncement", 0] } ] diff --git a/src/main/resources/assets/minelittlepony/models/entity/components/ears.json b/src/main/resources/assets/minelittlepony/models/entity/components/ears.json index 26495b7d..3696466e 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/components/ears.json +++ b/src/main/resources/assets/minelittlepony/models/entity/components/ears.json @@ -5,6 +5,7 @@ "y": 0, "z": 0, "ear_pronouncement": 0, + "ear_shortening": 0, "ear_spread": 0, "ear_spread_neg": [0, "-", "#ear_spread"] }, @@ -14,7 +15,7 @@ "pivot": ["#x", "#y", "#z"], "rotate": [0, 0, "#ear_spread"], "cubes": [ - { "from": [-4, -8, -1], "size": [2, 2, 2], "dilate": [0, "#ear_pronouncement", 0] } + { "from": [-4, -8, -1], "size": [2, 2, 2], "dilate": [0, "#ear_pronouncement", "#ear_shortening"] } ] }, "left": { @@ -23,7 +24,7 @@ "mirror": [true, false, false], "rotate": [0, 0, "#ear_spread_neg"], "cubes": [ - { "from": [2, -8, -1], "size": [2, 2, 2], "dilate": [0, "#ear_pronouncement", 0] } + { "from": [2, -8, -1], "size": [2, 2, 2], "dilate": [0, "#ear_pronouncement", "#ear_shortening"] } ] } } diff --git a/src/main/resources/assets/minelittlepony/models/entity/enderman.json b/src/main/resources/assets/minelittlepony/models/entity/enderman.json index 4b869023..792ff603 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/enderman.json +++ b/src/main/resources/assets/minelittlepony/models/entity/enderman.json @@ -7,12 +7,26 @@ }, "data": { "head": { + "pivot": [ 0, "#head_pivot_y", 0 ], + "dilate": ["#head_elongation", "#head_elongation", 0], "cubes": [ { "from": [-4, -6, -6], "size": [ 8, 8, 8] } ], "children": { + "nose": { + "dilate": [-1, 0, -1], + "cubes": [ + { "from": [-4, -6, -13], "size": [ 8, 8, 8] } + ] + }, "snout": { "data": "minelittlepony:components/snout", "implementation": "com.minelittlepony.client.model.part.PonySnout" }, - "ears": { "data": "minelittlepony:components/ears", "implementation": "com.minelittlepony.client.model.part.PonyEars" }, + "ears": { + "data": "minelittlepony:components/ears", + "implementation": "com.minelittlepony.client.model.part.PonyEars", + "locals": { + "ear_shortening": "#global_ear_shortening" + } + }, "horn": { "data": "minelittlepony:components/horn", "implementation": "com.minelittlepony.client.model.part.UnicornHorn" }, "left_horn": { "texture": {"u": 0, "v": 52}, diff --git a/src/main/resources/assets/minelittlepony/models/entity/piglin.json b/src/main/resources/assets/minelittlepony/models/entity/piglin.json index e9bfa7e3..131f4d1b 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/piglin.json +++ b/src/main/resources/assets/minelittlepony/models/entity/piglin.json @@ -3,10 +3,18 @@ "parent": "minelittlepony:zombie", "data": { "head": { + "pivot": [ 0, "#head_pivot_y", 0 ], + "dilate": ["#head_elongation", "#head_elongation", 0], "cubes": [ { "from": [-4, -6, -6], "size": [ 8, 8, 8] } ], "children": { + "nose": { + "dilate": [-1, 0, -1], + "cubes": [ + { "from": [-4, -6, -13], "size": [ 8, 8, 8] } + ] + }, "left_flap": { "name": "left_flap", "texture": {"u": 64, "v": 0}, diff --git a/src/main/resources/assets/minelittlepony/models/entity/races/steve/bat_pony.json b/src/main/resources/assets/minelittlepony/models/entity/races/steve/bat_pony.json index f6bf7b92..627779a7 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/races/steve/bat_pony.json +++ b/src/main/resources/assets/minelittlepony/models/entity/races/steve/bat_pony.json @@ -2,17 +2,28 @@ "parent": "minelittlepony:steve_pony", "data": { "head": { + "pivot": [ 0, "#head_pivot_y", 0 ], + "dilate": ["#head_elongation", "#head_elongation", 0], "cubes": [ { "from": [-4, -6, -6], "size": [ 8, 8, 8] } ], "children": { + "nose": { + "dilate": [-1, 0, -1], + "cubes": [ + { "from": [-4, -6, -13], "size": [ 8, 8, 8] } + ] + }, "snout": { "data": "minelittlepony:components/snout", "implementation": "com.minelittlepony.client.model.part.PonySnout" }, "ears": { "data": "minelittlepony:components/bat_ears", - "implementation": "com.minelittlepony.client.model.part.PonyEars" + "implementation": "com.minelittlepony.client.model.part.PonyEars", + "locals": { + "ear_shortening": "#global_ear_shortening" + } } } }, diff --git a/src/main/resources/assets/minelittlepony/models/entity/races/steve/hippogriff.json b/src/main/resources/assets/minelittlepony/models/entity/races/steve/hippogriff.json index cbaa36dd..ebb570d0 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/races/steve/hippogriff.json +++ b/src/main/resources/assets/minelittlepony/models/entity/races/steve/hippogriff.json @@ -16,10 +16,17 @@ "data": { "head": { "pivot": [ 0, "#head_pivot_y", 0 ], + "dilate": ["#head_elongation", "#head_elongation", 0], "cubes": [ { "from": [-4, -6, -6], "size": [ 8, 8, 8] } ], "children": { + "nose": { + "dilate": [-1, 0, -1], + "cubes": [ + { "from": [-4, -6, -13], "size": [ 8, 8, 8] } + ] + }, "snout": { "implementation": "com.minelittlepony.client.model.part.PonySnout", "data": "minelittlepony:components/beak" diff --git a/src/main/resources/assets/minelittlepony/models/entity/races/steve/kirin.json b/src/main/resources/assets/minelittlepony/models/entity/races/steve/kirin.json index f936b80e..cb846885 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/races/steve/kirin.json +++ b/src/main/resources/assets/minelittlepony/models/entity/races/steve/kirin.json @@ -2,10 +2,18 @@ "parent": "minelittlepony:races/steve/unicorn", "data": { "head": { + "pivot": [ 0, "#head_pivot_y", 0 ], + "dilate": ["#head_elongation", "#head_elongation", 0], "cubes": [ { "from": [-4, -6, -6], "size": [ 8, 8, 8] } ], "children": { + "nose": { + "dilate": [-1, 0, -1], + "cubes": [ + { "from": [-4, -6, -13], "size": [ 8, 8, 8] } + ] + }, "snout": { "data": "minelittlepony:components/snout", "implementation": "com.minelittlepony.client.model.part.PonySnout" @@ -30,7 +38,7 @@ }, "neck": { "type": "mson:planar", - "dilate": [ -0.3, "#neck_dilate_y", -0.3 ], + "dilate": [ -0.3, "#neck_dilate_y", "#neck_dilate_z" ], "texture": { "u": 0, "v": 16 }, "rotate": [9, 0, 0], "north": [-2, 1.199998, -2.8, 4, 4], @@ -38,10 +46,21 @@ "east": [ 2, 1.199998, -2.8, 4, 4], "west": [-2, 1.199998, -2.8, 4, 4], "children": { + "mane": { + "type": "mson:planar", + "pivot": [0, -2.9, 1.5], + "dilate": [ -0.8, 2, 0 ], + "texture": { "u": 32, "v": 0 }, + "rotate": [0, 0, 0], + "north": [-2, 1.199998, -2.8, 4, 4], + "south": [-2, 1.199998, 1.2, 4, 4], + "east": [ 2, 1.199998, -2.8, 4, 4], + "west": [-2, 1.199998, -2.8, 4, 4] + }, "beard": { "texture": { "u": 16, "v": 16 }, "pivot": [-4, 2, -2], - "rotate": [-29, 0, 0], + "rotate": [-20, 0, 0], "cubes": [ { "from": [0, 0, 0], "size": [ 8, 8, 4], "dilate": [0.5, -0.5, 0] } ] diff --git a/src/main/resources/assets/minelittlepony/models/entity/races/steve/reformed_changeling.json b/src/main/resources/assets/minelittlepony/models/entity/races/steve/reformed_changeling.json index 97a7f728..b807dfe1 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/races/steve/reformed_changeling.json +++ b/src/main/resources/assets/minelittlepony/models/entity/races/steve/reformed_changeling.json @@ -2,10 +2,18 @@ "parent": "minelittlepony:races/steve/alicorn", "data": { "head": { + "pivot": [ 0, "#head_pivot_y", 0 ], + "dilate": ["#head_elongation", "#head_elongation", 0], "cubes": [ { "from": [-4, -6, -6], "size": [ 8, 8, 8] } ], "children": { + "nose": { + "dilate": [-1, 0, -1], + "cubes": [ + { "from": [-4, -6, -13], "size": [ 8, 8, 8] } + ] + }, "snout": { "data": "minelittlepony:components/snout", "implementation": "com.minelittlepony.client.model.part.PonySnout" diff --git a/src/main/resources/assets/minelittlepony/models/entity/races/steve/sea_pony.json b/src/main/resources/assets/minelittlepony/models/entity/races/steve/sea_pony.json index ebc59191..997f699d 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/races/steve/sea_pony.json +++ b/src/main/resources/assets/minelittlepony/models/entity/races/steve/sea_pony.json @@ -32,7 +32,10 @@ "from": [-3, 5, 1], "size": [6, 7, 9] } - ] + ], + "children": { + "tail_stub": {} + } }, "tail": { "implementation": "com.minelittlepony.client.model.part.SeaponyTail", diff --git a/src/main/resources/assets/minelittlepony/models/entity/races/steve/unicorn.json b/src/main/resources/assets/minelittlepony/models/entity/races/steve/unicorn.json index 8ff4d185..8ee1735c 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/races/steve/unicorn.json +++ b/src/main/resources/assets/minelittlepony/models/entity/races/steve/unicorn.json @@ -2,12 +2,26 @@ "parent": "minelittlepony:steve_pony", "data": { "head": { + "pivot": [ 0, "#head_pivot_y", 0 ], + "dilate": ["#head_elongation", "#head_elongation", 0], "cubes": [ { "from": [-4, -6, -6], "size": [ 8, 8, 8] } ], "children": { + "nose": { + "dilate": [-1, 0, -1], + "cubes": [ + { "from": [-4, -6, -13], "size": [ 8, 8, 8] } + ] + }, "snout": { "data": "minelittlepony:components/snout", "implementation": "com.minelittlepony.client.model.part.PonySnout" }, - "ears": { "data": "minelittlepony:components/ears", "implementation": "com.minelittlepony.client.model.part.PonyEars" }, + "ears": { + "data": "minelittlepony:components/ears", + "implementation": "com.minelittlepony.client.model.part.PonyEars", + "locals": { + "ear_shortening": "#global_ear_shortening" + } + }, "horn": { "data": "minelittlepony:components/horn", "implementation": "com.minelittlepony.client.model.part.UnicornHorn" } } }, diff --git a/src/main/resources/assets/minelittlepony/models/entity/races/steve/zebra.json b/src/main/resources/assets/minelittlepony/models/entity/races/steve/zebra.json index 683532b6..8e958d65 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/races/steve/zebra.json +++ b/src/main/resources/assets/minelittlepony/models/entity/races/steve/zebra.json @@ -1,18 +1,29 @@ { "parent": "minelittlepony:steve_pony", "locals": { - "head_pivot_y": -1.2, - "neck_dilate_y": 1.6 }, "data": { "head": { "pivot": [ 0, "#head_pivot_y", 0 ], + "dilate": ["#head_elongation", "#head_elongation", 0], "cubes": [ { "from": [-4, -6, -6], "size": [ 8, 8, 8] } ], "children": { + "nose": { + "dilate": [-1, 0, -1], + "cubes": [ + { "from": [-4, -6, -13], "size": [ 8, 8, 8] } + ] + }, "snout": { "data": "minelittlepony:components/snout", "implementation": "com.minelittlepony.client.model.part.PonySnout" }, - "ears": { "data": "minelittlepony:components/ears", "implementation": "com.minelittlepony.client.model.part.PonyEars" }, + "ears": { + "data": "minelittlepony:components/ears", + "implementation": "com.minelittlepony.client.model.part.PonyEars", + "locals": { + "ear_shortening": "#global_ear_shortening" + } + }, "bristles": { "texture": {"u": 56, "v": 32}, "rotate": [17, 0, 0], diff --git a/src/main/resources/assets/minelittlepony/models/entity/steve_pony.json b/src/main/resources/assets/minelittlepony/models/entity/steve_pony.json index f582dfa9..b0d4ce48 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/steve_pony.json +++ b/src/main/resources/assets/minelittlepony/models/entity/steve_pony.json @@ -9,32 +9,46 @@ "arm_depth": 4, "arm_x": 0, "arm_x_neg": ["#arm_x", "-", "#arm_width"], - "arm_z": [2, "-", "#arm_depth"], + "arm_z": ["#arm_depth", "/", -2], "arm_rotation_x": 0, "arm_rotation_x_neg": [0, "-", "#arm_rotation_x"], "arm_rotation_y": 8, "head_pivot_y": 0, - "neck_dilate_y": -0.1 + "neck_dilate_y": -0.1, + "neck_dilate_z": -0.3, + "head_elongation": 0, + "global_ear_shortening": 0 }, "data": { "head": { "pivot": [ 0, "#head_pivot_y", 0 ], + "dilate": ["#head_elongation", "#head_elongation", 0], "cubes": [ { "from": [-4, -6, -6], "size": [ 8, 8, 8] } ], "children": { + "nose": { + "dilate": [-1, 0, -1], + "cubes": [ + { "from": [-4, -6, -13], "size": [ 8, 8, 8] } + ] + }, "snout": { "implementation": "com.minelittlepony.client.model.part.PonySnout", "data": "minelittlepony:components/snout" }, "ears": { "implementation": "com.minelittlepony.client.model.part.PonyEars", - "data": "minelittlepony:components/ears" + "data": "minelittlepony:components/ears", + "locals": { + "ear_shortening": "#global_ear_shortening" + } } } }, "hat": { "texture": { "u": 32, "v": 0 }, + "dilate": ["#head_elongation", "#head_elongation", 0], "pivot": [ 0, "#head_pivot_y", 0 ], "cubes": [ { "from": [-4, -6, -6], "size": [ 8, 8, 8], "dilate": 0.5 } @@ -161,13 +175,26 @@ }, "neck": { "type": "mson:planar", - "dilate": [ -0.3, "#neck_dilate_y", -0.3 ], + "dilate": [ -0.3, "#neck_dilate_y", "#neck_dilate_z" ], "texture": { "u": 0, "v": 16 }, "rotate": [9, 0, 0], "north": [-2, 1.199998, -2.8, 4, 4], "south": [-2, 1.199998, 1.2, 4, 4], "east": [ 2, 1.199998, -2.8, 4, 4], - "west": [-2, 1.199998, -2.8, 4, 4] + "west": [-2, 1.199998, -2.8, 4, 4], + "children": { + "mane": { + "type": "mson:planar", + "pivot": [0, -2.9, 1.5], + "dilate": [ -0.8, 2, 0 ], + "texture": { "u": 32, "v": 0 }, + "rotate": [0, 0, 0], + "north": [-2, 1.199998, -2.8, 4, 4], + "south": [-2, 1.199998, 1.2, 4, 4], + "east": [ 2, 1.199998, -2.8, 4, 4], + "west": [-2, 1.199998, -2.8, 4, 4] + } + } }, "jacket": { "texture": { "u": 24, "v": 0 }, diff --git a/src/main/resources/assets/minelittlepony/models/entity/villager.json b/src/main/resources/assets/minelittlepony/models/entity/villager.json index 09c7ee87..fdcf5bf7 100644 --- a/src/main/resources/assets/minelittlepony/models/entity/villager.json +++ b/src/main/resources/assets/minelittlepony/models/entity/villager.json @@ -2,6 +2,8 @@ "parent": "minelittlepony:races/steve/alicorn", "data": { "head": { + "pivot": [ 0, "#head_pivot_y", 0 ], + "dilate": ["#head_elongation", "#head_elongation", 0], "cubes": [ { "from": [-4, -6, -6], "size": [ 8, 8, 8] } ], @@ -16,13 +18,19 @@ "type": "mson:slot", "name": "ears", "implementation": "com.minelittlepony.client.model.part.PonyEars", - "data": "minelittlepony:components/ears" + "data": "minelittlepony:components/ears", + "locals": { + "ear_shortening": "#global_ear_shortening" + } }, "bat_ears": { "type": "mson:slot", "name": "bat_ears", "implementation": "com.minelittlepony.client.model.part.PonyEars", - "data": "minelittlepony:components/bat_ears" + "data": "minelittlepony:components/bat_ears", + "locals": { + "ear_shortening": "#global_ear_shortening" + } }, "horn": { "type": "mson:slot",