mirror of
https://github.com/MineLittlePony/MineLittlePony.git
synced 2024-11-22 04:27:59 +01:00
April fools 2023
This commit is contained in:
parent
32d1ffbe7c
commit
d9769e32ee
31 changed files with 401 additions and 54 deletions
|
@ -52,6 +52,8 @@ public class PonyConfig extends Config {
|
|||
public final Setting<Boolean> 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<Boolean> horsieMode = value("settings", "horsieMode", false)
|
||||
.addComment("Enables the alternative horsey models from the April Fools 2023 update");
|
||||
|
||||
public final Setting<Sizes> sizeOverride = value("debug", "sizeOverride", Sizes.UNSET)
|
||||
.addComment("Overrides pony sizes")
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Boolean>)i).get()))
|
||||
.onChange((Setting<Boolean>)i)
|
||||
.onChange(i == config.horsieMode ? (v -> {
|
||||
v = ((Setting<Boolean>)i).set(v);
|
||||
|
||||
PonyRenderDispatcher.getInstance().initialise(MinecraftClient.getInstance().getEntityRenderDispatcher(), true);
|
||||
return v;
|
||||
}) : (Setting<Boolean>)i)
|
||||
.setEnabled(enabled);
|
||||
button.getStyle().setText(OPTIONS_PREFIX + i.name().toLowerCase());
|
||||
if (!enabled) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<T extends LivingEntity> 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<T extends LivingEntity> 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<T extends LivingEntity> 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<T extends LivingEntity> 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<T extends LivingEntity> 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<T extends LivingEntity> 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<T extends LivingEntity> 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<T extends LivingEntity> 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<T extends LivingEntity> extends ClientPo
|
|||
|
||||
protected void adjustBody(float pitch, Pivot pivot) {
|
||||
adjustBodyComponents(pitch, pivot);
|
||||
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<T extends LivingEntity> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,6 +106,16 @@ public abstract class ClientPonyModel<T extends LivingEntity> 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<T extends LivingEntity> {
|
||||
void poseModel(ClientPonyModel<T> model, float move, float swing, float ticks, T entity);
|
||||
}
|
||||
|
|
106
src/main/java/com/minelittlepony/client/model/ModelKeyImpl.java
Normal file
106
src/main/java/com/minelittlepony/client/model/ModelKeyImpl.java
Normal file
|
@ -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<M extends Model> implements ModelKey<M>, LocalBlock {
|
||||
|
||||
private final Map<String, Incomplete<Float>> 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<M> key;
|
||||
private final MsonModel.Factory<M> constr;
|
||||
|
||||
ModelKeyImpl(Identifier id, MsonModel.Factory<M> constr) {
|
||||
this.key = Mson.getInstance().registerModel(id, constr);
|
||||
this.constr = constr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return key.getId();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <V extends M> V createModel() {
|
||||
return (V)createModel(constr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V extends M> V createModel(Factory<V> 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<ModelPart> 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<FileContent<?>> getModelData() {
|
||||
return key.getModelData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> appendKeys(Set<String> output) {
|
||||
output.addAll(horseModeValues.keySet());
|
||||
return output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CompletableFuture<Incomplete<Float>>> get(String name) {
|
||||
if (horseModeValues.containsKey(name)) {
|
||||
return Optional.of(CompletableFuture.completedFuture(horseModeValues.get(name)));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
|
@ -68,7 +68,7 @@ public final class ModelType {
|
|||
|
||||
public static final PlayerModelKey<LivingEntity, AlicornModel<?>> ALICORN = registerPlayer("alicorn", Race.ALICORN, AlicornModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, UnicornModel<?>> UNICORN = registerPlayer("unicorn", Race.UNICORN, UnicornModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, UnicornModel<?>> KIRIN = registerPlayer("kirin", Race.KIRIN, UnicornModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, KirinModel<?>> KIRIN = registerPlayer("kirin", Race.KIRIN, KirinModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> PEGASUS = registerPlayer("pegasus", Race.PEGASUS, PegasusModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> GRYPHON = registerPlayer("gryphon", Race.GRYPHON, PegasusModel::new);
|
||||
public static final PlayerModelKey<LivingEntity, PegasusModel<?>> HIPPOGRIFF = registerPlayer("hippogriff", Race.HIPPOGRIFF, PegasusModel::new);
|
||||
|
@ -113,7 +113,7 @@ public final class ModelType {
|
|||
}
|
||||
|
||||
static <T extends Model> ModelKey<T> register(String name, MsonModel.Factory<T> constructor) {
|
||||
return Mson.getInstance().registerModel(new Identifier("minelittlepony", name), constructor);
|
||||
return new ModelKeyImpl<T>(new Identifier("minelittlepony", name), constructor);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -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<T extends LivingEntity, M extends Model & MsonModel
|
|||
) {
|
||||
PlayerModelKey(String name, BiFunction<ModelPart, Boolean, M> modelFactory, RendererFactory rendererFactory, MsonModel.Factory<PonyArmourModel<T>> 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
|
||||
);
|
||||
|
|
|
@ -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<T extends LivingEntity> extends UnicornModel<T> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)",
|
||||
|
|
|
@ -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] }
|
||||
]
|
||||
|
|
|
@ -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"] }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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] }
|
||||
]
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -32,7 +32,10 @@
|
|||
"from": [-3, 5, 1],
|
||||
"size": [6, 7, 9]
|
||||
}
|
||||
]
|
||||
],
|
||||
"children": {
|
||||
"tail_stub": {}
|
||||
}
|
||||
},
|
||||
"tail": {
|
||||
"implementation": "com.minelittlepony.client.model.part.SeaponyTail",
|
||||
|
|
|
@ -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" }
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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],
|
||||
"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 },
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue