Implement armour trims

This commit is contained in:
Sollace 2023-03-21 21:38:32 +00:00
parent 5bd90a0627
commit cc1f323b95
13 changed files with 216 additions and 230 deletions

View file

@ -4,7 +4,6 @@ import net.minecraft.item.Item;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.armour.PonyArmourModel; import com.minelittlepony.client.model.armour.PonyArmourModel;
import com.minelittlepony.mson.api.ModelKey; import com.minelittlepony.mson.api.ModelKey;
import com.minelittlepony.mson.api.Mson; import com.minelittlepony.mson.api.Mson;
@ -12,8 +11,6 @@ import com.minelittlepony.mson.api.Mson;
import java.util.*; import java.util.*;
public interface ArmorModelRegistry { public interface ArmorModelRegistry {
static final Optional<ModelKey<PonyArmourModel<?>>> DEFAULT_INNER = Optional.of(ModelType.INNER_ARMOR);
static final Optional<ModelKey<PonyArmourModel<?>>> DEFAULT_OUTER = Optional.of(ModelType.OUTER_ARMOR);
static final Map<Identifier, Optional<ModelKey<PonyArmourModel<?>>>> REGISTRY = new HashMap<>(); static final Map<Identifier, Optional<ModelKey<PonyArmourModel<?>>>> REGISTRY = new HashMap<>();
public static Optional<ModelKey<PonyArmourModel<?>>> getModelKey(Item item, ArmourLayer layer) { public static Optional<ModelKey<PonyArmourModel<?>>> getModelKey(Item item, ArmourLayer layer) {
@ -25,8 +22,4 @@ public interface ArmorModelRegistry {
return Optional.of(Mson.getInstance().registerModel(i, PonyArmourModel::new)); return Optional.of(Mson.getInstance().registerModel(i, PonyArmourModel::new));
}).filter(key -> key.getModelData().isPresent()); }).filter(key -> key.getModelData().isPresent());
} }
public static Optional<ModelKey<PonyArmourModel<?>>> getDefault(ArmourLayer layer) {
return layer == ArmourLayer.INNER ? DEFAULT_INNER : DEFAULT_OUTER;
}
} }

View file

@ -16,4 +16,8 @@ public enum ArmourLayer {
public int getLegacyId() { public int getLegacyId() {
return ordinal() + 1; return ordinal() + 1;
} }
public boolean isInner() {
return this == INNER;
}
} }

View file

@ -1,6 +1,25 @@
package com.minelittlepony.api.model.armour; package com.minelittlepony.api.model.armour;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.armour.PonyArmourModel;
import com.minelittlepony.mson.api.ModelKey;
import java.util.Optional;
public enum ArmourVariant { public enum ArmourVariant {
NORMAL, NORMAL(ModelType.INNER_PONY_ARMOR, ModelType.OUTER_PONY_ARMOR),
LEGACY LEGACY(ModelType.INNER_VANILLA_ARMOR, ModelType.OUTER_VANILLA_ARMOR),
TRIM(ModelType.INNER_VANILLA_ARMOR, ModelType.OUTER_VANILLA_ARMOR);
private final Optional<ModelKey<PonyArmourModel<?>>> innerModel;
private final Optional<ModelKey<PonyArmourModel<?>>> outerModel;
ArmourVariant(ModelKey<PonyArmourModel<?>> inner, ModelKey<PonyArmourModel<?>> outer) {
this.innerModel = Optional.of(inner);
this.outerModel = Optional.of(outer);
}
public Optional<ModelKey<PonyArmourModel<?>>> getDefaultModel(ArmourLayer layer) {
return layer.isInner() ? innerModel : outerModel;
}
} }

View file

@ -1,24 +1,17 @@
package com.minelittlepony.api.model.armour; package com.minelittlepony.api.model.armour;
import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import com.minelittlepony.api.model.IModel; import com.minelittlepony.client.model.IPonyModel;
public interface IArmourModel { public interface IArmourModel<T extends LivingEntity> {
/** /**
* Called to synchronise this armour's angles with that of another. * Called to synchronise this armour's angles with that of another.
* *
* @param model The other model to mimic * @param model The other model to mimic
*/ */
void synchroniseAngles(IModel model); boolean poseModel(T entity, float limbAngle, float limbDistance, float age, float headYaw, float headPitch,
EquipmentSlot slot, ArmourLayer layer,
/** IPonyModel<T> mainModel);
* Prepares an armour model for rendering, first hiding all the pieces and then incrementally showing them as appropriate.
*
* @param slot The armour slot being rendered
* @param layer The layer. INNER/OUTER
*
* @return false to skip this render pass.
*/
boolean setVisibilities(EquipmentSlot slot, ArmourLayer layer, ArmourVariant variant);
} }

View file

@ -52,8 +52,10 @@ public final class ModelType {
public static final ModelKey<PonyElytra<?>> ELYTRA = register("elytra", PonyElytra::new); public static final ModelKey<PonyElytra<?>> ELYTRA = register("elytra", PonyElytra::new);
public static final ModelKey<ArmorStandEntityModel> ARMOUR_STAND = register("armour_stand", PonyArmourStandModel::new); public static final ModelKey<ArmorStandEntityModel> ARMOUR_STAND = register("armour_stand", PonyArmourStandModel::new);
public static final ModelKey<PonyArmourModel<?>> INNER_ARMOR = register("armor/inner_pony_armor", PonyArmourModel::new); public static final ModelKey<PonyArmourModel<?>> INNER_VANILLA_ARMOR = register("armor/inner_vanilla_armor", PonyArmourModel::new);
public static final ModelKey<PonyArmourModel<?>> OUTER_ARMOR = register("armor/outer_pony_armor", PonyArmourModel::new); public static final ModelKey<PonyArmourModel<?>> OUTER_VANILLA_ARMOR = register("armor/outer_vanilla_armor", PonyArmourModel::new);
public static final ModelKey<PonyArmourModel<?>> INNER_PONY_ARMOR = register("armor/inner_pony_armor", PonyArmourModel::new);
public static final ModelKey<PonyArmourModel<?>> OUTER_PONY_ARMOR = register("armor/outer_pony_armor", PonyArmourModel::new);
public static final GearModelKey<Stetson> STETSON = registerGear("stetson", Wearable.STETSON, Stetson::new); public static final GearModelKey<Stetson> STETSON = registerGear("stetson", Wearable.STETSON, Stetson::new);
public static final GearModelKey<SaddleBags> SADDLEBAGS_BOTH = registerGear("saddlebags", Wearable.SADDLE_BAGS_BOTH, t -> new SaddleBags(t, Wearable.SADDLE_BAGS_BOTH)); public static final GearModelKey<SaddleBags> SADDLEBAGS_BOTH = registerGear("saddlebags", Wearable.SADDLE_BAGS_BOTH, t -> new SaddleBags(t, Wearable.SADDLE_BAGS_BOTH));

View file

@ -43,8 +43,8 @@ public class ModelWrapper<T extends LivingEntity, M extends IModel> implements I
return body; return body;
} }
public Optional<PonyArmourModel<T>> getArmourModel(ItemStack stack, ArmourLayer layer) { public Optional<PonyArmourModel<T>> getArmourModel(ItemStack stack, ArmourLayer layer, ArmourVariant variant) {
return ArmorModelRegistry.getModelKey(stack.getItem(), layer).or(() -> ArmorModelRegistry.getDefault(layer).filter(l -> stack.getItem() instanceof ArmorItem)) return ArmorModelRegistry.getModelKey(stack.getItem(), layer).or(() -> variant.getDefaultModel(layer).filter(l -> stack.getItem() instanceof ArmorItem))
.map(key -> armor.computeIfAbsent(key, k -> { .map(key -> armor.computeIfAbsent(key, k -> {
return armorFactory == null ? k.createModel() : k.createModel(armorFactory); return armorFactory == null ? k.createModel() : k.createModel(armorFactory);
})); }));

View file

@ -5,108 +5,50 @@ import net.minecraft.client.render.entity.model.BipedEntityModel;
import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.armour.*; import com.minelittlepony.api.model.armour.*;
import com.minelittlepony.client.model.AbstractPonyModel; import com.minelittlepony.client.model.AbstractPonyModel;
import com.minelittlepony.client.model.IPonyModel;
public class PonyArmourModel<T extends LivingEntity> extends AbstractPonyModel<T> implements IArmourModel { public class PonyArmourModel<T extends LivingEntity> extends AbstractPonyModel<T> implements IArmourModel<T> {
private ModelPart chestPiece;
private ModelPart steveRightLeg;
private ModelPart steveLeftLeg;
public PonyArmourModel(ModelPart tree) { public PonyArmourModel(ModelPart tree) {
super(tree); super(tree);
chestPiece = tree.getChild("chestpiece");
steveRightLeg = tree.getChild("steve_right_leg");
steveLeftLeg = tree.getChild("steve_left_leg");
bodyRenderList.clear();
bodyRenderList.add(body, chestPiece);
legsRenderList.add(steveLeftLeg, steveRightLeg);
}
public IArmourTextureResolver getArmourTextureResolver() {
return DefaultArmourTextureResolver.INSTANCE;
} }
@Override @Override
protected void adjustBodyComponents(float rotateAngleX, float rotationPointY, float rotationPointZ) { public boolean poseModel(T entity, float limbAngle, float limbDistance, float age, float headYaw, float headPitch,
super.adjustBodyComponents(rotateAngleX, rotationPointY, rotationPointZ); EquipmentSlot slot, ArmourLayer layer,
IPonyModel<T> mainModel) {
chestPiece.pitch = rotateAngleX; if (!setVisibilities(slot, layer)) {
chestPiece.pivotY = rotationPointY; return false;
chestPiece.pivotZ = rotationPointZ; }
mainModel.copyAttributes(this);
setAngles(entity, limbAngle, limbDistance, age, headYaw, headPitch);
if (mainModel instanceof BipedEntityModel<?> biped) {
head.copyTransform(biped.head);
body.copyTransform(biped.body);
rightArm.copyTransform(biped.rightArm);
leftArm.copyTransform(biped.leftArm);
rightLeg.copyTransform(biped.rightLeg);
leftLeg.copyTransform(biped.leftLeg);
}
return true;
} }
@Override public boolean setVisibilities(EquipmentSlot slot, ArmourLayer layer) {
public void synchroniseAngles(IModel model) {
if (model instanceof BipedEntityModel) {
@SuppressWarnings("unchecked")
BipedEntityModel<T> mainModel = (BipedEntityModel<T>)model;
head.copyTransform(mainModel.head);
head.copyTransform(mainModel.head);
body.copyTransform(mainModel.body);
rightArm.copyTransform(mainModel.rightArm);
leftArm.copyTransform(mainModel.leftArm);
rightLeg.copyTransform(mainModel.rightLeg);
leftLeg.copyTransform(mainModel.leftLeg);
steveLeftLeg.copyTransform(mainModel.leftLeg);
steveRightLeg.copyTransform(mainModel.rightLeg);
}
}
@Override
public boolean setVisibilities(EquipmentSlot slot, ArmourLayer layer, ArmourVariant variant) {
setVisible(false); setVisible(false);
chestPiece.visible = false; body.visible = slot == EquipmentSlot.CHEST;
head.visible = false; head.visible = layer == ArmourLayer.OUTER && slot == EquipmentSlot.HEAD;
neck.visible = false;
steveLeftLeg.visible = false;
steveRightLeg.visible = false;
switch (layer) { if (slot == (layer == ArmourLayer.OUTER ? EquipmentSlot.FEET : EquipmentSlot.LEGS)) {
case OUTER:
switch (slot) {
case HEAD:
head.visible = true;
return true;
case FEET:
showLeggings(layer, variant);
return true;
case CHEST:
body.visible = variant == ArmourVariant.LEGACY;
chestPiece.visible = variant == ArmourVariant.NORMAL;
return true;
default:
return false;
}
case INNER:
switch (slot) {
case LEGS:
showLeggings(layer, variant);
return true;
case CHEST:
body.visible = variant == ArmourVariant.LEGACY;
chestPiece.visible = variant == ArmourVariant.NORMAL;
return true;
default:
return false;
}
default:
return false;
}
}
protected void showLeggings(ArmourLayer layer, ArmourVariant variant) {
rightArm.visible = true; rightArm.visible = true;
leftArm.visible = true; leftArm.visible = true;
rightLeg.visible = variant == ArmourVariant.NORMAL; rightLeg.visible = true;
leftLeg.visible = variant == ArmourVariant.NORMAL; leftLeg.visible = true;
steveLeftLeg.visible = variant == ArmourVariant.LEGACY; return true;
steveRightLeg.visible = variant == ArmourVariant.LEGACY; }
return head.visible || body.visible;
} }
} }

View file

@ -4,11 +4,11 @@ import com.minelittlepony.client.model.armour.PonyArmourModel;
import com.minelittlepony.mson.api.ModelView; import com.minelittlepony.mson.api.ModelView;
import com.minelittlepony.api.model.*; import com.minelittlepony.api.model.*;
import com.minelittlepony.api.model.armour.ArmourLayer; import com.minelittlepony.api.model.armour.ArmourLayer;
import com.minelittlepony.api.model.armour.ArmourVariant;
import com.minelittlepony.api.pony.IPony; import com.minelittlepony.api.pony.IPony;
import net.minecraft.client.model.ModelPart; import net.minecraft.client.model.ModelPart;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@ -133,9 +133,11 @@ public class SeaponyModel<T extends LivingEntity> extends UnicornModel<T> {
} }
@Override @Override
public void showLeggings(ArmourLayer layer, ArmourVariant variant) { public boolean setVisibilities(EquipmentSlot slot, ArmourLayer layer) {
rightArm.visible = true; boolean result = super.setVisibilities(slot, layer);
leftArm.visible = true; rightLeg.visible = false;
leftLeg.visible = false;
return result;
} }
@Override @Override

View file

@ -3,27 +3,29 @@ package com.minelittlepony.client.render.entity.feature;
import com.minelittlepony.api.model.armour.*; import com.minelittlepony.api.model.armour.*;
import com.minelittlepony.client.model.IPonyModel; import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.client.model.ModelWrapper; import com.minelittlepony.client.model.ModelWrapper;
import com.minelittlepony.client.model.armour.PonyArmourModel; import com.minelittlepony.client.model.armour.DefaultArmourTextureResolver;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.IPonyRenderContext;
import com.minelittlepony.common.util.Color; import com.minelittlepony.common.util.Color;
import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.*;
import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.entity.model.*;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.model.BipedEntityModel;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.render.model.BakedModelManager;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.item.*; import net.minecraft.item.*;
import net.minecraft.item.trim.ArmorTrim;
import net.minecraft.resource.featuretoggle.FeatureFlags;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & IPonyModel<T>> extends AbstractPonyFeature<T, M> { public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & IPonyModel<T>> extends AbstractPonyFeature<T, M> {
public ArmourFeature(IPonyRenderContext<T, M> renderer) { public ArmourFeature(IPonyRenderContext<T, M> context, BakedModelManager bakery) {
super(renderer); super(context);
} }
@Override @Override
@ -38,66 +40,77 @@ public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & IP
} }
} }
public static <T extends LivingEntity, V extends BipedEntityModel<T> & IArmourModel> void renderArmor( public static <T extends LivingEntity, V extends BipedEntityModel<T> & IArmourModel<T>> void renderArmor(
ModelWrapper<T, ? extends IPonyModel<T>> pony, MatrixStack stack, ModelWrapper<T, ? extends IPonyModel<T>> pony, MatrixStack matrices,
VertexConsumerProvider renderContext, int lightUv, T entity, VertexConsumerProvider renderContext, int light, T entity,
float limbDistance, float limbAngle, float limbDistance, float limbAngle,
float age, float headYaw, float headPitch, float age, float headYaw, float headPitch,
EquipmentSlot armorSlot, ArmourLayer layer) { EquipmentSlot armorSlot, ArmourLayer layer) {
ItemStack itemstack = entity.getEquippedStack(armorSlot); ItemStack stack = entity.getEquippedStack(armorSlot);
if (itemstack.isEmpty()) { if (stack.isEmpty()) {
return; return;
} }
PonyArmourModel<T> model = pony.getArmourModel(itemstack, layer).orElse(null); IArmourTextureResolver resolver = DefaultArmourTextureResolver.INSTANCE;
if (model == null) { Identifier texture = resolver.getTexture(entity, stack, armorSlot, layer, null);
return; ArmourVariant variant = resolver.getVariant(layer, texture);
}
IArmourTextureResolver resolver = model.getArmourTextureResolver(); boolean glint = stack.hasGlint();
Item item = stack.getItem();
boolean glint = itemstack.hasGlint();
Identifier texture = resolver.getTexture(entity, itemstack, armorSlot, layer, null);
Item item = itemstack.getItem();
if (model.setVisibilities(armorSlot, layer, resolver.getVariant(layer, texture))) {
model.setMetadata(pony.body().getMetadata());
pony.body().copyAttributes(model);
model.setAngles(entity, limbAngle, limbDistance, age, headYaw, headPitch);
model.synchroniseAngles(pony.body());
pony.getArmourModel(stack, layer, variant)
.filter(m -> m.poseModel(entity, limbAngle, limbDistance, age, headYaw, headPitch, armorSlot, layer, pony.body()))
.ifPresent(model -> {
float red = 1; float red = 1;
float green = 1; float green = 1;
float blue = 1; float blue = 1;
if (item instanceof DyeableArmorItem) { if (item instanceof DyeableArmorItem dyeable) {
int color = ((DyeableArmorItem)item).getColor(itemstack); int color = dyeable.getColor(stack);
red = Color.r(color); red = Color.r(color);
green = Color.g(color); green = Color.g(color);
blue = Color.b(color); blue = Color.b(color);
} }
renderArmourPart(stack, renderContext, lightUv, glint, model, red, green, blue, texture); model.render(matrices, getArmorConsumer(renderContext, texture, glint), light, OverlayTexture.DEFAULT_UV, red, green, blue, 1);
if (item instanceof DyeableArmorItem) { if (item instanceof DyeableArmorItem) {
texture = resolver.getTexture(entity, itemstack, armorSlot, layer, "overlay"); Identifier tex = resolver.getTexture(entity, stack, armorSlot, layer, "overlay");
if (model.setVisibilities(armorSlot, layer, resolver.getVariant(layer, texture))) { pony.getArmourModel(stack, layer, resolver.getVariant(layer, tex))
renderArmourPart(stack, renderContext, lightUv, false, model, 1, 1, 1, texture); .filter(m -> m.poseModel(entity, limbAngle, limbDistance, age, headYaw, headPitch, armorSlot, layer, pony.body()))
} .ifPresent(m -> {
} m.render(matrices, getArmorConsumer(renderContext, tex, false), light, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
} });
} }
private static <T extends LivingEntity, V extends BipedEntityModel<T> & IArmourModel> void renderArmourPart( if (entity.world.getEnabledFeatures().contains(FeatureFlags.UPDATE_1_20)) {
MatrixStack matrices, VertexConsumerProvider provider, if (stack.getItem() instanceof ArmorItem armor) {
int light, boolean glint, V model, float r, float g, float b, Identifier texture) { ArmorTrim.getTrim(entity.world.getRegistryManager(), stack).ifPresent(trim -> {
pony.getArmourModel(stack, layer, ArmourVariant.TRIM)
VertexConsumer vertices = ItemRenderer.getArmorGlintConsumer(provider, RenderLayer.getArmorCutoutNoCull(texture), false, glint); .filter(m -> m.poseModel(entity, limbAngle, limbDistance, age, headYaw, headPitch, armorSlot, layer, pony.body()))
.ifPresent(m -> {
model.render(matrices, vertices, light, OverlayTexture.DEFAULT_UV, r, g, b, 1); m.render(matrices, getTrimConsumer(renderContext, armor.getMaterial(), trim, layer, glint), light, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
});
});
}
}
});
}
private static VertexConsumer getArmorConsumer(VertexConsumerProvider provider, Identifier texture, boolean glint) {
return ItemRenderer.getArmorGlintConsumer(provider, RenderLayer.getArmorCutoutNoCull(texture), false, glint);
}
private static VertexConsumer getTrimConsumer(VertexConsumerProvider provider, ArmorMaterial material, ArmorTrim trim, ArmourLayer layer, boolean glint) {
SpriteAtlasTexture armorTrimsAtlas = MinecraftClient.getInstance().getBakedModelManager().getAtlas(TexturedRenderLayers.ARMOR_TRIMS_ATLAS_TEXTURE);
Sprite sprite = armorTrimsAtlas.getSprite(
layer == ArmourLayer.INNER ? trim.getLeggingsModelId(material) : trim.getGenericModelId(material)
);
return sprite.getTextureSpecificVertexConsumer(
ItemRenderer.getDirectItemGlintConsumer(provider, TexturedRenderLayers.getArmorTrims(), true, glint)
);
} }
} }

View file

@ -1,59 +1,12 @@
{ {
"parent": "minelittlepony:steve_pony", "parent": "minelittlepony:armor/inner_vanilla_armor",
"texture": {"w": 64, "h": 32},
"dilate": 0.2,
"data": { "data": {
"body": { "body": {
"texture": { "u": 16, "v": 18 },
"cubes": [
{ "from": [-4, 4, -2], "size": [ 8, 8, 4] }
],
"children": {
"upper_torso": {
"type": "mson:planar",
"texture": {"u": 24, "v": 0},
"east": [ 4, 4, 2, 8, 8, 32, 23],
"west": [ -4, 4, 2, 8, 8, 32, 23],
"south": [-4, 4, 10, 8, 8, 32, 23],
"up": [ -4, 4, 1, 8, 12, 32, 23],
"__comment": "it's a little short, so the butt tends to show. :/"
}
}
},
"chestpiece": {
"texture": {"u": 16, "v": 8}, "texture": {"u": 16, "v": 8},
"cubes": [ "cubes": [
{"from": [-4, 4, -2], "size": [8, 8, 16]} {"from": [-4, 4, -2], "size": [8, 8, 16]}
] ]
}, },
"head": {
"cubes": [
{ "from": [-4, -6, -6], "size": [ 8, 8, 8], "dilate": 0.5 },
{ "from": [-4, -8, -1], "size": [ 2, 2, 2], "texture": {"u": 0, "v": 0}, "dilate": -0.0125 },
{ "from": [ 2, -8, -1], "size": [ 2, 2, 2], "texture": {"u": 0, "v": 4}, "dilate": -0.0125 }
]
},
"right_arm": {
"pivot": ["#arm_rotation_x_neg", "#arm_rotation_y", 0],
"texture": { "u": 0, "v": 16 },
"cubes": [
{
"from": [ "#arm_x_neg", 4, "#arm_z"],
"size": [ "#arm_width", "#arm_length", "#arm_depth" ]
}
]
},
"left_arm": {
"pivot": ["#arm_rotation_x", "#arm_rotation_y", 0],
"mirror": true,
"texture": { "u": 0, "v": 16 },
"cubes": [
{
"from": [ "#arm_x", 4, "#arm_z"],
"size": [ "#arm_width", "#arm_length", "#arm_depth" ]
}
]
},
"right_leg": { "right_leg": {
"pivot": ["#arm_rotation_x_neg", 0, 0], "pivot": ["#arm_rotation_x_neg", 0, 0],
"texture": { "u": 48, "v": 8 }, "texture": { "u": 48, "v": 8 },
@ -74,27 +27,6 @@
"size": [ "#arm_width", "#arm_length", "#arm_depth" ] "size": [ "#arm_width", "#arm_length", "#arm_depth" ]
} }
] ]
},
"steve_right_leg": {
"pivot": ["#arm_rotation_x_neg", 0, 0],
"texture": { "u": 0, "v": 16 },
"cubes": [
{
"from": [ "#arm_x_neg", 4, "#arm_z"],
"size": [ "#arm_width", "#arm_length", "#arm_depth" ]
}
]
},
"steve_left_leg": {
"pivot": ["#arm_rotation_x", 0, 0],
"mirror": true,
"texture": { "u": 0, "v": 16 },
"cubes": [
{
"from": [ "#arm_x", 4, "#arm_z"],
"size": [ "#arm_width", "#arm_length", "#arm_depth" ]
}
]
} }
} }
} }

View file

@ -0,0 +1,73 @@
{
"parent": "minelittlepony:steve_pony",
"texture": {"w": 64, "h": 32},
"dilate": 0.2,
"data": {
"body": {
"texture": { "u": 16, "v": 18 },
"cubes": [
{ "from": [-4, 4, -2], "size": [ 8, 8, 4] }
],
"children": {
"upper_torso": {
"type": "mson:planar",
"texture": {"u": 24, "v": 0},
"east": [ 4, 4, 2, 8, 8, 32, 23],
"west": [ -4, 4, 2, 8, 8, 32, 23],
"south": [-4, 4, 10, 8, 8, 32, 23],
"up": [ -4, 4, 1, 8, 12, 32, 23],
"__comment": "it's a little short, so the butt tends to show. :/"
}
}
},
"head": {
"cubes": [
{ "from": [-4, -6, -6], "size": [ 8, 8, 8], "dilate": 0.5 },
{ "from": [-4, -8, -1], "size": [ 2, 2, 2], "texture": {"u": 0, "v": 0}, "dilate": -0.0125 },
{ "from": [ 2, -8, -1], "size": [ 2, 2, 2], "texture": {"u": 0, "v": 4}, "dilate": -0.0125 }
]
},
"right_arm": {
"pivot": ["#arm_rotation_x_neg", "#arm_rotation_y", 0],
"texture": { "u": 0, "v": 16 },
"cubes": [
{
"from": [ "#arm_x_neg", 4, "#arm_z"],
"size": [ "#arm_width", "#arm_length", "#arm_depth" ]
}
]
},
"left_arm": {
"pivot": ["#arm_rotation_x", "#arm_rotation_y", 0],
"mirror": true,
"texture": { "u": 0, "v": 16 },
"cubes": [
{
"from": [ "#arm_x", 4, "#arm_z"],
"size": [ "#arm_width", "#arm_length", "#arm_depth" ]
}
]
},
"right_leg": {
"pivot": ["#arm_rotation_x_neg", 0, 0],
"texture": { "u": 0, "v": 16 },
"cubes": [
{
"from": [ "#arm_x_neg", 4, "#arm_z"],
"size": [ "#arm_width", "#arm_length", "#arm_depth" ]
}
]
},
"left_leg": {
"pivot": ["#arm_rotation_x", 0, 0],
"mirror": true,
"texture": { "u": 0, "v": 16 },
"cubes": [
{
"from": [ "#arm_x", 4, "#arm_z"],
"size": [ "#arm_width", "#arm_length", "#arm_depth" ]
}
]
}
}
}

View file

@ -1,4 +1,13 @@
{ {
"parent": "minelittlepony:armor/inner_pony_armor", "parent": "minelittlepony:armor/inner_pony_armor",
"dilate": 0.4 "dilate": 0.4,
"data": {
"body": {
"texture": {"u": 16, "v": 8},
"dilate": 0.41,
"cubes": [
{"from": [-4, 4, -2], "size": [8, 8, 16]}
]
}
}
} }

View file

@ -0,0 +1,4 @@
{
"parent": "minelittlepony:armor/inner_vanilla_armor",
"dilate": 0.4
}