Add support for custom armour models

This commit is contained in:
Sollace 2023-02-15 19:09:59 +00:00
parent c68d484d42
commit a9f070226f
22 changed files with 175 additions and 240 deletions

View file

@ -4,7 +4,6 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import com.minelittlepony.api.config.PonyConfig; import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.model.armour.IArmour;
import com.minelittlepony.api.pony.IPonyData; import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.meta.*; import com.minelittlepony.api.pony.meta.*;
@ -19,11 +18,6 @@ public interface IModel {
*/ */
Size getSize(); Size getSize();
/**
* Returns a new pony armour to go with this model. Called on startup by a model wrapper.
*/
IArmour<?> createArmour();
/** /**
* Gets the transitive properties of this model. * Gets the transitive properties of this model.
*/ */

View file

@ -0,0 +1,32 @@
package com.minelittlepony.api.model.armour;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
import net.minecraft.util.Identifier;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.armour.PonyArmourModel;
import com.minelittlepony.mson.api.ModelKey;
import com.minelittlepony.mson.api.Mson;
import java.util.*;
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<>();
public static Optional<ModelKey<PonyArmourModel<?>>> getModelKey(Item item, ArmourLayer layer) {
Identifier id = Registries.ITEM.getId(item);
if (id.getNamespace().equals("minecraft")) {
return Optional.empty();
}
return REGISTRY.computeIfAbsent(id.withPath(p -> "models/armor/" + layer.name().toLowerCase() + "_" + p + ".json"), i -> {
return Optional.of(Mson.getInstance().registerModel(i, PonyArmourModel::new));
}).filter(key -> key.getModelData().isPresent());
}
public static Optional<ModelKey<PonyArmourModel<?>>> getDefault(ArmourLayer layer) {
return layer == ArmourLayer.INNER ? DEFAULT_INNER : DEFAULT_OUTER;
}
}

View file

@ -1,18 +0,0 @@
package com.minelittlepony.api.model.armour;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.*;
import net.minecraft.util.Identifier;
import com.mojang.serialization.Lifecycle;
@Deprecated
public final class ArmourRegistry {
private ArmourRegistry() {}
static final Registry<IArmour<?>> REGISTRY = new SimpleRegistry<>(RegistryKey.ofRegistry(new Identifier("minelittlepony", "armour")), Lifecycle.stable());
@SuppressWarnings("unchecked")
public static <T extends IArmourModel> IArmour<T> getArmour(ItemStack stack, IArmour<T> fallback) {
return (IArmour<T>)REGISTRY.getOrEmpty(Registries.ITEM.getId(stack.getItem())).orElse(fallback);
}
}

View file

@ -1,51 +0,0 @@
package com.minelittlepony.api.model.armour;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.model.IModelWrapper;
import com.minelittlepony.api.pony.IPonyData;
/**
* Wrapper for an armour model and texture.
*
* @param <V> The type of the contained armour model.
*/
@Deprecated
public interface IArmour<V extends IArmourModel> extends IModelWrapper {
/**
* Registers a custom armour for the supplied item.
*
* Mods can register their own armour here if they wish to override the default handling.
*
* Only one registration per item allowed.
*/
public static <T extends IArmourModel> IArmour<T> register(IArmour<T> armour, Item item) {
return Registry.register(ArmourRegistry.REGISTRY, Registries.ITEM.getId(item), armour);
}
/**
* Gets the armour model to render for the given layer.
* <p>
* Return null to preserve the default behaviour or override and return your custom model.
*/
@Nullable
V getModel(ArmourLayer layer);
/**
* Override this to specify your own textures.
*
* The default resolver will simply attempt to ponify the vanilla locations.
*/
default IArmourTextureResolver getTextureResolver(IArmourTextureResolver defaultResolver) {
return defaultResolver;
}
@Override
default IArmour<V> applyMetadata(IPonyData meta) {
return this;
}
}

View file

@ -1,11 +1,8 @@
package com.minelittlepony.client.model; package com.minelittlepony.client.model;
import com.minelittlepony.client.model.armour.PonyArmourModel;
import com.minelittlepony.api.model.*; import com.minelittlepony.api.model.*;
import com.minelittlepony.api.model.armour.IArmour;
import com.minelittlepony.api.model.fabric.PonyModelPrepareCallback; import com.minelittlepony.api.model.fabric.PonyModelPrepareCallback;
import com.minelittlepony.api.pony.meta.Sizes; import com.minelittlepony.api.pony.meta.Sizes;
import com.minelittlepony.client.model.armour.ArmourWrapper;
import com.minelittlepony.client.transform.PonyTransformation; import com.minelittlepony.client.transform.PonyTransformation;
import com.minelittlepony.client.util.render.RenderList; import com.minelittlepony.client.util.render.RenderList;
import com.minelittlepony.mson.util.PartUtil; import com.minelittlepony.mson.util.PartUtil;
@ -57,11 +54,6 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
.add(withStage(BodyPart.HEAD, helmetRenderList = RenderList.of(hat))); .add(withStage(BodyPart.HEAD, helmetRenderList = RenderList.of(hat)));
} }
@Override
public IArmour<?> createArmour() {
return ArmourWrapper.of(PonyArmourModel::new);
}
protected RenderList forPart(Supplier<IPart> part) { protected RenderList forPart(Supplier<IPart> part) {
return (stack, vertices, overlayUv, lightUv, red, green, blue, alpha) -> { return (stack, vertices, overlayUv, lightUv, red, green, blue, alpha) -> {
part.get().renderPart(stack, vertices, overlayUv, lightUv, red, green, blue, alpha, attributes); part.get().renderPart(stack, vertices, overlayUv, lightUv, red, green, blue, alpha, attributes);

View file

@ -10,7 +10,6 @@ import net.minecraft.util.Arm;
import com.minelittlepony.api.model.BodyPart; import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.IUnicorn; import com.minelittlepony.api.model.IUnicorn;
import com.minelittlepony.api.model.ModelAttributes; import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.model.armour.IArmour;
import com.minelittlepony.api.pony.IPony; import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.IPonyData; import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.meta.Size; import com.minelittlepony.api.pony.meta.Size;
@ -59,11 +58,6 @@ public interface IPonyMixinModel<T extends LivingEntity, M extends IPonyModel<T>
return mixin().getSize(); return mixin().getSize();
} }
@Override
default IArmour<?> createArmour() {
return mixin().createArmour();
}
@Override @Override
default void setMetadata(IPonyData meta) { default void setMetadata(IPonyData meta) {
mixin().setMetadata(meta); mixin().setMetadata(meta);

View file

@ -8,6 +8,7 @@ import net.minecraft.entity.mob.VexEntity;
import net.minecraft.entity.passive.*; import net.minecraft.entity.passive.*;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.gear.IGear; import com.minelittlepony.api.model.gear.IGear;
import com.minelittlepony.api.pony.meta.Race; import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.api.pony.meta.Wearable; import com.minelittlepony.api.pony.meta.Wearable;
@ -51,8 +52,8 @@ 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<?>> ARMOUR_INNER = register("armour_inner", PonyArmourModel::new); public static final ModelKey<PonyArmourModel<?>> INNER_ARMOR = register("armor/inner_pony_armor", PonyArmourModel::new);
public static final ModelKey<PonyArmourModel<?>> ARMOUR_OUTER = register("armour_outer", PonyArmourModel::new); public static final ModelKey<PonyArmourModel<?>> OUTER_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));
@ -63,27 +64,37 @@ public final class ModelType {
public static final GearModelKey<WitchHat> WITCH_HAT = registerGear("witch_hat", Wearable.HAT, WitchHat::new); public static final GearModelKey<WitchHat> WITCH_HAT = registerGear("witch_hat", Wearable.HAT, WitchHat::new);
public static final GearModelKey<ChristmasHat> ANTLERS = registerGear("antlers", Wearable.ANTLERS, ChristmasHat::new); public static final GearModelKey<ChristmasHat> ANTLERS = registerGear("antlers", Wearable.ANTLERS, ChristmasHat::new);
public static final PlayerModelKey<?, AlicornModel<?>> ALICORN = registerPlayer("alicorn", Race.ALICORN, AlicornModel::new); public static final PlayerModelKey<LivingEntity, AlicornModel<?>> ALICORN = registerPlayer("alicorn", Race.ALICORN, AlicornModel::new);
public static final PlayerModelKey<?, UnicornModel<?>> UNICORN = registerPlayer("unicorn", Race.UNICORN, UnicornModel::new); public static final PlayerModelKey<LivingEntity, UnicornModel<?>> UNICORN = registerPlayer("unicorn", Race.UNICORN, UnicornModel::new);
public static final PlayerModelKey<?, UnicornModel<?>> KIRIN = registerPlayer("kirin", Race.KIRIN, UnicornModel::new); public static final PlayerModelKey<LivingEntity, UnicornModel<?>> KIRIN = registerPlayer("kirin", Race.KIRIN, UnicornModel::new);
public static final PlayerModelKey<?, PegasusModel<?>> PEGASUS = registerPlayer("pegasus", Race.PEGASUS, PegasusModel::new); public static final PlayerModelKey<LivingEntity, PegasusModel<?>> PEGASUS = registerPlayer("pegasus", Race.PEGASUS, PegasusModel::new);
public static final PlayerModelKey<?, PegasusModel<?>> GRYPHON = registerPlayer("gryphon", Race.GRYPHON, PegasusModel::new); public static final PlayerModelKey<LivingEntity, PegasusModel<?>> GRYPHON = registerPlayer("gryphon", Race.GRYPHON, PegasusModel::new);
public static final PlayerModelKey<?, PegasusModel<?>> HIPPOGRIFF = registerPlayer("hippogriff", Race.HIPPOGRIFF, PegasusModel::new); public static final PlayerModelKey<LivingEntity, PegasusModel<?>> HIPPOGRIFF = registerPlayer("hippogriff", Race.HIPPOGRIFF, PegasusModel::new);
public static final PlayerModelKey<?, EarthPonyModel<?>> EARTH_PONY = registerPlayer("earth_pony", Race.EARTH, EarthPonyModel::new); public static final PlayerModelKey<LivingEntity, EarthPonyModel<?>> EARTH_PONY = registerPlayer("earth_pony", Race.EARTH, EarthPonyModel::new);
public static final PlayerModelKey<?, SeaponyModel<?>> SEA_PONY = registerPlayer("sea_pony", Race.SEAPONY, SeaponyModel::new, PlayerSeaponyRenderer::new); public static final PlayerModelKey<LivingEntity, SeaponyModel<?>> SEA_PONY = registerPlayer("sea_pony", Race.SEAPONY, SeaponyModel::new, SeaponyModel.Armour::new, PlayerSeaponyRenderer::new);
public static final PlayerModelKey<?, PegasusModel<?>> BAT_PONY = registerPlayer("bat_pony", Race.BATPONY, PegasusModel::new); public static final PlayerModelKey<LivingEntity, PegasusModel<?>> BAT_PONY = registerPlayer("bat_pony", Race.BATPONY, PegasusModel::new);
public static final PlayerModelKey<?, ChangelingModel<?>> CHANGELING = registerPlayer("changeling", Race.CHANGELING, ChangelingModel::new); public static final PlayerModelKey<LivingEntity, ChangelingModel<?>> CHANGELING = registerPlayer("changeling", Race.CHANGELING, ChangelingModel::new);
public static final PlayerModelKey<?, ChangelingModel<?>> CHANGEDLING = registerPlayer("reformed_changeling", Race.CHANGEDLING, ChangelingModel::new); public static final PlayerModelKey<LivingEntity, ChangelingModel<?>> CHANGEDLING = registerPlayer("reformed_changeling", Race.CHANGEDLING, ChangelingModel::new);
public static final PlayerModelKey<?, EarthPonyModel<?>> ZEBRA = registerPlayer("zebra", Race.ZEBRA, EarthPonyModel::new); public static final PlayerModelKey<LivingEntity, EarthPonyModel<?>> ZEBRA = registerPlayer("zebra", Race.ZEBRA, EarthPonyModel::new);
static <E extends LivingEntity, T extends Model & MsonModel> PlayerModelKey<E, T> registerPlayer(String name, Race race, BiFunction<ModelPart, Boolean, T> constructor) { static <E extends LivingEntity, T extends Model & MsonModel & IModel> PlayerModelKey<E, T> registerPlayer(String name, Race race,
BiFunction<ModelPart, Boolean, T> constructor) {
return registerPlayer(name, race, constructor, PlayerPonyRenderer::new); return registerPlayer(name, race, constructor, PlayerPonyRenderer::new);
} }
static <E extends LivingEntity, T extends Model & MsonModel & IModel> PlayerModelKey<E, T> registerPlayer(String name, Race race,
BiFunction<ModelPart, Boolean, T> constructor,
PlayerModelKey.RendererFactory rendererFactory) {
return registerPlayer(name, race, constructor, PonyArmourModel::new, rendererFactory);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static <E extends LivingEntity, T extends Model & MsonModel> PlayerModelKey<E, T> registerPlayer(String name, Race race, BiFunction<ModelPart, Boolean, T> constructor, PlayerModelKey.RendererFactory rendererFactory) { static <E extends LivingEntity, T extends Model & MsonModel & IModel> PlayerModelKey<E, T> registerPlayer(String name, Race race,
BiFunction<ModelPart, Boolean, T> constructor,
MsonModel.Factory<PonyArmourModel<E>> armorFactory,
PlayerModelKey.RendererFactory rendererFactory) {
return (PlayerModelKey<E, T>)PLAYER_MODELS.computeIfAbsent(race, r -> { return (PlayerModelKey<E, T>)PLAYER_MODELS.computeIfAbsent(race, r -> {
return new PlayerModelKey<>(name, constructor, rendererFactory); return new PlayerModelKey<>(name, constructor, rendererFactory, armorFactory);
}); });
} }
@ -105,7 +116,7 @@ public final class ModelType {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Nullable @Nullable
public static <E extends LivingEntity, T extends Model & MsonModel> PlayerModelKey<E, T> getPlayerModel(Race race) { public static <E extends LivingEntity, T extends Model & MsonModel & IModel> PlayerModelKey<E, T> getPlayerModel(Race race) {
return (PlayerModelKey<E, T>)PLAYER_MODELS.get(race); return (PlayerModelKey<E, T>)PLAYER_MODELS.get(race);
} }

View file

@ -1,44 +1,59 @@
package com.minelittlepony.client.model; package com.minelittlepony.client.model;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.ItemStack;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.model.IModel; import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.IModelWrapper; import com.minelittlepony.api.model.IModelWrapper;
import com.minelittlepony.api.model.armour.IArmour; import com.minelittlepony.api.model.armour.*;
import com.minelittlepony.api.pony.IPonyData; import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.mson.api.ModelKey; import com.minelittlepony.client.model.armour.PonyArmourModel;
import com.minelittlepony.mson.api.*;
import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
* Container class for the various models and their associated piece of armour. * Container class for the various models and their associated piece of armour.
*/ */
public record ModelWrapper<T extends LivingEntity, M extends IModel> ( public class ModelWrapper<T extends LivingEntity, M extends IModel> implements IModelWrapper {
M body, @Nullable
IArmour<?> armor private final MsonModel.Factory<PonyArmourModel<T>> armorFactory;
) implements IModelWrapper { private final Map<ModelKey<PonyArmourModel<?>>, PonyArmourModel<T>> armor = new HashMap<>();
/**
* Creates a new model wrapper to contain the given pony. private final M body;
*/
public static <T extends LivingEntity, M extends IModel> ModelWrapper<T, M> of(ModelKey<?> key) { public ModelWrapper(PlayerModelKey<T, ?> playerModelKey, boolean slimArms, @Nullable Consumer<M> initializer) {
return of(key, null); this.armorFactory = playerModelKey.armorFactory();
this.body = playerModelKey.getKey(slimArms).createModel();
if (initializer != null) {
initializer.accept(this.body);
}
} }
public static <T extends LivingEntity, M extends IModel> ModelWrapper<T, M> of(ModelKey<?> key, @Nullable Consumer<M> initializer) { public ModelWrapper(ModelKey<M> key) {
@SuppressWarnings("unchecked") this.armorFactory = null;
M body = (M)key.createModel(); this.body = key.createModel();
if (initializer != null) initializer.accept(body); }
IArmour<?> armor = body.createArmour();
armor.applyMetadata(body.getMetadata()); public M body() {
return new ModelWrapper<>(body, armor); return body;
}
public Optional<PonyArmourModel<T>> getArmourModel(ItemStack stack, ArmourLayer layer) {
return ArmorModelRegistry.getModelKey(stack.getItem(), layer).or(() -> ArmorModelRegistry.getDefault(layer).filter(l -> stack.getItem() instanceof ArmorItem))
.map(key -> armor.computeIfAbsent(key, k -> {
return armorFactory == null ? k.createModel() : k.createModel(armorFactory);
}));
} }
@Override @Override
public ModelWrapper<T, M> applyMetadata(IPonyData meta) { public ModelWrapper<T, M> applyMetadata(IPonyData meta) {
body.setMetadata(meta); body.setMetadata(meta);
armor.applyMetadata(meta); armor.values().forEach(a -> a.setMetadata(meta));
return this; return this;
} }
} }

View file

@ -8,23 +8,28 @@ import net.minecraft.client.render.entity.PlayerEntityRenderer;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
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.ModelKey;
import com.minelittlepony.mson.api.Mson; import com.minelittlepony.mson.api.Mson;
import com.minelittlepony.mson.api.MsonModel; import com.minelittlepony.mson.api.MsonModel;
import java.util.function.BiFunction; import java.util.function.*;
import java.util.function.Function;
public record PlayerModelKey<T extends LivingEntity, M extends Model & MsonModel> ( public record PlayerModelKey<T extends LivingEntity, M extends Model & MsonModel & IModel> (
ModelKey<M> steveKey, ModelKey<M> steveKey,
ModelKey<M> alexKey, ModelKey<M> alexKey,
RendererFactory factory RendererFactory factory,
MsonModel.Factory<PonyArmourModel<T>> armorFactory
) { ) {
PlayerModelKey(String name, BiFunction<ModelPart, Boolean, M> modelFactory, RendererFactory rendererFactory) { PlayerModelKey(String name, BiFunction<ModelPart, Boolean, M> modelFactory, RendererFactory rendererFactory, MsonModel.Factory<PonyArmourModel<T>> armorFactory) {
this( this(
Mson.getInstance().registerModel(new Identifier("minelittlepony", "races/steve/" + name), tree -> modelFactory.apply(tree, false)), 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)), Mson.getInstance().registerModel(new Identifier("minelittlepony", "races/alex/" + name), tree -> modelFactory.apply(tree, true)),
rendererFactory rendererFactory,
armorFactory
); );
} }
@ -32,16 +37,25 @@ public record PlayerModelKey<T extends LivingEntity, M extends Model & MsonModel
return slimArms ? alexKey : steveKey; return slimArms ? alexKey : steveKey;
} }
public <K extends T, N extends M> ModelWrapper<K, N> create(boolean slimArms) {
return create(slimArms, null);
}
@SuppressWarnings({"rawtypes", "unchecked"})
public <K extends T, N extends M> ModelWrapper<K, N> create(boolean slimArms, @Nullable Consumer<N> initializer) {
return new ModelWrapper(this, slimArms, initializer);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Function<EntityRendererFactory.Context, PlayerEntityRenderer> getFactory(boolean slimArms) { public Function<EntityRendererFactory.Context, PlayerEntityRenderer> getFactory(boolean slimArms) {
return d -> factory.create(d, slimArms, (ModelKey<? extends ClientPonyModel<AbstractClientPlayerEntity>>)getKey(slimArms)); return d -> factory.create(d, slimArms, (PlayerModelKey<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>>)this);
} }
public interface RendererFactory { public interface RendererFactory {
PlayerEntityRenderer create( PlayerEntityRenderer create(
EntityRendererFactory.Context context, EntityRendererFactory.Context context,
boolean slim, boolean slim,
ModelKey<? extends ClientPonyModel<AbstractClientPlayerEntity>> key PlayerModelKey<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> key
); );
} }
} }

View file

@ -1,33 +0,0 @@
package com.minelittlepony.client.model.armour;
import net.minecraft.entity.LivingEntity;
import com.minelittlepony.api.model.armour.ArmourLayer;
import com.minelittlepony.api.model.armour.IArmour;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.mson.api.MsonModel;
public record ArmourWrapper<T extends LivingEntity> (
PonyArmourModel<T> outerLayer,
PonyArmourModel<T> innerLayer
) implements IArmour<PonyArmourModel<T>> {
public static <T extends LivingEntity> ArmourWrapper<T> of(MsonModel.Factory<PonyArmourModel<T>> supplier) {
return new ArmourWrapper<>(
ModelType.ARMOUR_OUTER.createModel(supplier),
ModelType.ARMOUR_INNER.createModel(supplier)
);
}
@Override
public ArmourWrapper<T> applyMetadata(IPonyData meta) {
outerLayer.setMetadata(meta);
innerLayer.setMetadata(meta);
return this;
}
@Override
public PonyArmourModel<T> getModel(ArmourLayer layer) {
return layer == ArmourLayer.INNER ? innerLayer : outerLayer;
}
}

View file

@ -5,8 +5,7 @@ import net.minecraft.client.render.entity.model.BipedEntityModel;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import com.minelittlepony.api.model.IModel; import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.armour.ArmourVariant; import com.minelittlepony.api.model.armour.*;
import com.minelittlepony.api.model.armour.IArmourModel;
import com.minelittlepony.client.model.AbstractPonyModel; import com.minelittlepony.client.model.AbstractPonyModel;
public class PonyArmourModel<T extends LivingEntity> extends AbstractPonyModel<T> implements IArmourModel { public class PonyArmourModel<T extends LivingEntity> extends AbstractPonyModel<T> implements IArmourModel {
@ -29,6 +28,10 @@ public class PonyArmourModel<T extends LivingEntity> extends AbstractPonyModel<T
legsRenderList.add(steveLeftLeg, steveRightLeg); legsRenderList.add(steveLeftLeg, steveRightLeg);
} }
public IArmourTextureResolver getArmourTextureResolver() {
return IArmourTextureResolver.DEFAULT;
}
@Override @Override
protected void adjustBodyComponents(float rotateAngleX, float rotationPointY, float rotationPointZ) { protected void adjustBodyComponents(float rotateAngleX, float rotationPointY, float rotationPointZ) {
super.adjustBodyComponents(rotateAngleX, rotationPointY, rotationPointZ); super.adjustBodyComponents(rotateAngleX, rotationPointY, rotationPointZ);

View file

@ -4,9 +4,7 @@ import com.minelittlepony.client.model.armour.PonyArmourModel;
import com.minelittlepony.mson.api.ModelContext; import com.minelittlepony.mson.api.ModelContext;
import com.minelittlepony.api.model.BodyPart; import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.ModelAttributes; import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.model.armour.IArmour;
import com.minelittlepony.api.pony.IPony; import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.client.model.armour.ArmourWrapper;
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;
@ -41,11 +39,6 @@ public class SeaponyModel<T extends LivingEntity> extends UnicornModel<T> {
bodyRenderList.add(body, abdomin).add(body::rotate).add(forPart(tail)).add(leftFin, centerFin, rightFin); bodyRenderList.add(body, abdomin).add(body::rotate).add(forPart(tail)).add(leftFin, centerFin, rightFin);
} }
@Override
public IArmour<?> createArmour() {
return ArmourWrapper.of(Armour::new);
}
@Override @Override
public void updateLivingState(T entity, IPony pony, ModelAttributes.Mode mode) { public void updateLivingState(T entity, IPony pony, ModelAttributes.Mode mode) {
super.updateLivingState(entity, pony, mode); super.updateLivingState(entity, pony, mode);
@ -138,7 +131,7 @@ public class SeaponyModel<T extends LivingEntity> extends UnicornModel<T> {
rightFin.visible = visible; rightFin.visible = visible;
} }
class Armour extends PonyArmourModel<T> { public static class Armour<T extends LivingEntity> extends PonyArmourModel<T> {
public Armour(ModelPart tree) { public Armour(ModelPart tree) {
super(tree); super(tree);

View file

@ -144,8 +144,9 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
return playerModel; return playerModel;
} }
public ModelWrapper<T, M> setModel(ModelKey<?> key) { @SuppressWarnings({"rawtypes", "unchecked"})
return setModel(ModelWrapper.of(key)); public ModelWrapper<T, M> setModel(ModelKey<? super M> key) {
return setModel(new ModelWrapper(key));
} }
public ModelWrapper<T, M> setModel(ModelWrapper<T, M> wrapper) { public ModelWrapper<T, M> setModel(ModelWrapper<T, M> wrapper) {

View file

@ -5,8 +5,7 @@ import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.meta.Race; import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.api.pony.meta.Wearable; import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.SkinsProxy; import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.client.model.ClientPonyModel; import com.minelittlepony.client.model.*;
import com.minelittlepony.client.model.ModelWrapper;
import com.minelittlepony.client.model.gear.SaddleBags; import com.minelittlepony.client.model.gear.SaddleBags;
import com.minelittlepony.client.render.DebugBoundingBoxRenderer; import com.minelittlepony.client.render.DebugBoundingBoxRenderer;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.IPonyRenderContext;
@ -19,7 +18,6 @@ import com.minelittlepony.client.render.entity.feature.ArmourFeature;
import com.minelittlepony.client.render.entity.feature.CapeFeature; import com.minelittlepony.client.render.entity.feature.CapeFeature;
import com.minelittlepony.client.render.entity.feature.SkullFeature; import com.minelittlepony.client.render.entity.feature.SkullFeature;
import com.minelittlepony.client.render.entity.feature.ElytraFeature; import com.minelittlepony.client.render.entity.feature.ElytraFeature;
import com.minelittlepony.mson.api.ModelKey;
import java.util.List; import java.util.List;
@ -43,10 +41,10 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
protected final EquineRenderManager<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> manager = new EquineRenderManager<>(this); protected final EquineRenderManager<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> manager = new EquineRenderManager<>(this);
public PlayerPonyRenderer(EntityRendererFactory.Context context, boolean slim, ModelKey<? extends ClientPonyModel<AbstractClientPlayerEntity>> key) { public PlayerPonyRenderer(EntityRendererFactory.Context context, boolean slim, PlayerModelKey<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> key) {
super(context, slim); super(context, slim);
this.model = manager.setModel(key).body(); this.model = manager.setModel(key.create(slim)).body();
addLayers(context); addLayers(context);
} }

View file

@ -4,10 +4,7 @@ import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.PonyPosture; import com.minelittlepony.api.pony.PonyPosture;
import com.minelittlepony.api.pony.meta.Race; import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.SkinsProxy; import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.client.model.ClientPonyModel; import com.minelittlepony.client.model.*;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.ModelWrapper;
import com.minelittlepony.mson.api.ModelKey;
import com.minelittlepony.util.MathUtil; import com.minelittlepony.util.MathUtil;
import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.AbstractClientPlayerEntity;
@ -21,11 +18,12 @@ public class PlayerSeaponyRenderer extends PlayerPonyRenderer {
private final ModelWrapper<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> seapony; private final ModelWrapper<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> seapony;
private final ModelWrapper<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> normalPony; private final ModelWrapper<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> normalPony;
public PlayerSeaponyRenderer(EntityRendererFactory.Context context, boolean slim, ModelKey<? extends ClientPonyModel<AbstractClientPlayerEntity>> key) { public PlayerSeaponyRenderer(EntityRendererFactory.Context context, boolean slim,
PlayerModelKey<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> key) {
super(context, slim, key); super(context, slim, key);
normalPony = ModelWrapper.of(ModelType.<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>>getPlayerModel(Race.UNICORN).getKey(slim)); normalPony = ModelType.getPlayerModel(Race.UNICORN).<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>>create(slim);
seapony = this.manager.getModelWrapper(); seapony = getModelWrapper();
} }
@Override @Override

View file

@ -13,8 +13,8 @@ import com.minelittlepony.client.render.entity.feature.HeldItemFeature;
import com.minelittlepony.client.render.entity.feature.GlowingItemFeature; import com.minelittlepony.client.render.entity.feature.GlowingItemFeature;
import com.minelittlepony.client.render.entity.feature.ArmourFeature; import com.minelittlepony.client.render.entity.feature.ArmourFeature;
import com.minelittlepony.client.render.entity.feature.SkullFeature; import com.minelittlepony.client.render.entity.feature.SkullFeature;
import com.minelittlepony.client.render.entity.feature.ElytraFeature;
import com.minelittlepony.mson.api.ModelKey; import com.minelittlepony.mson.api.ModelKey;
import com.minelittlepony.client.render.entity.feature.ElytraFeature;
import java.util.*; import java.util.*;
@ -38,9 +38,7 @@ public abstract class PonyRenderer<T extends MobEntity, M extends EntityModel<T>
public PonyRenderer(EntityRendererFactory.Context context, ModelKey<? super M> key) { public PonyRenderer(EntityRendererFactory.Context context, ModelKey<? super M> key) {
super(context, null, 0.5F); super(context, null, 0.5F);
this.model = manager.setModel(key).body(); this.model = manager.setModel(key).body();
addLayers(context); addLayers(context);
} }
@ -149,7 +147,7 @@ public abstract class PonyRenderer<T extends MobEntity, M extends EntityModel<T>
public abstract static class Proxy<T extends MobEntity, M extends EntityModel<T> & IPonyModel<T>> extends PonyRenderer<T, M> { public abstract static class Proxy<T extends MobEntity, M extends EntityModel<T> & IPonyModel<T>> extends PonyRenderer<T, M> {
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
public Proxy(List exportedLayers, EntityRendererFactory.Context context, ModelKey<M> key) { public Proxy(List exportedLayers, EntityRendererFactory.Context context, ModelKey<? super M> key) {
super(context, key); super(context, key);
exportedLayers.addAll(features); exportedLayers.addAll(features);

View file

@ -54,7 +54,7 @@ public class PonyStandRenderer extends ArmorStandEntityRenderer {
} }
class Armour extends ArmorFeatureRenderer<ArmorStandEntity, ArmorStandArmorEntityModel, ArmorStandArmorEntityModel> { class Armour extends ArmorFeatureRenderer<ArmorStandEntity, ArmorStandArmorEntityModel, ArmorStandArmorEntityModel> {
private final ModelWrapper<ArmorStandEntity, EarthPonyModel<ArmorStandEntity>> pony = ModelWrapper.of(ModelType.EARTH_PONY.getKey(false)); private final ModelWrapper<ArmorStandEntity, EarthPonyModel<ArmorStandEntity>> pony = ModelType.EARTH_PONY.<ArmorStandEntity, EarthPonyModel<ArmorStandEntity>>create(false);
public Armour(FeatureRendererContext<ArmorStandEntity, ArmorStandArmorEntityModel> renderer, EntityRendererFactory.Context context) { public Armour(FeatureRendererContext<ArmorStandEntity, ArmorStandArmorEntityModel> renderer, EntityRendererFactory.Context context) {
super(renderer, super(renderer,

View file

@ -1,12 +1,9 @@
package com.minelittlepony.client.render.entity.feature; package com.minelittlepony.client.render.entity.feature;
import com.minelittlepony.api.model.armour.ArmourLayer; import com.minelittlepony.api.model.armour.*;
import com.minelittlepony.api.model.armour.ArmourRegistry;
import com.minelittlepony.api.model.armour.IArmour;
import com.minelittlepony.api.model.armour.IArmourModel;
import com.minelittlepony.api.model.armour.IArmourTextureResolver;
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.render.IPonyRenderContext; import com.minelittlepony.client.render.IPonyRenderContext;
import com.minelittlepony.common.util.Color; import com.minelittlepony.common.util.Color;
@ -20,9 +17,7 @@ import net.minecraft.client.render.item.ItemRenderer;
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.ArmorItem; import net.minecraft.item.*;
import net.minecraft.item.DyeableArmorItem;
import net.minecraft.item.ItemStack;
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> {
@ -43,7 +38,6 @@ public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & IP
} }
} }
@SuppressWarnings("unchecked")
public static <T extends LivingEntity, V extends BipedEntityModel<T> & IArmourModel> void renderArmor( public static <T extends LivingEntity, V extends BipedEntityModel<T> & IArmourModel> void renderArmor(
ModelWrapper<T, ? extends IPonyModel<T>> pony, MatrixStack stack, ModelWrapper<T, ? extends IPonyModel<T>> pony, MatrixStack stack,
VertexConsumerProvider renderContext, int lightUv, T entity, VertexConsumerProvider renderContext, int lightUv, T entity,
@ -53,22 +47,23 @@ public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & IP
ItemStack itemstack = entity.getEquippedStack(armorSlot); ItemStack itemstack = entity.getEquippedStack(armorSlot);
if (!itemstack.isEmpty() && itemstack.getItem() instanceof ArmorItem) { if (itemstack.isEmpty()) {
IArmour<V> armour = ArmourRegistry.getArmour(itemstack, (IArmour<V>)pony.armor()); return;
armour.applyMetadata(pony.body().getMetadata());
V model = armour.getModel(layer);
if (model == null) {
model = ((IArmour<V>)pony.armor()).getModel(layer);
} }
PonyArmourModel<T> model = pony.getArmourModel(itemstack, layer).orElse(null);
if (model == null) {
return;
}
model.setMetadata(pony.body().getMetadata());
if (model.prepareToRender(armorSlot, layer)) { if (model.prepareToRender(armorSlot, layer)) {
pony.body().copyAttributes(model); pony.body().copyAttributes(model);
model.setAngles(entity, limbAngle, limbDistance, age, headYaw, headPitch); model.setAngles(entity, limbAngle, limbDistance, age, headYaw, headPitch);
model.synchroniseAngles(pony.body()); model.synchroniseAngles(pony.body());
ArmorItem item = (ArmorItem) itemstack.getItem(); Item item = itemstack.getItem();
float red = 1; float red = 1;
float green = 1; float green = 1;
@ -81,7 +76,7 @@ public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & IP
blue = Color.b(color); blue = Color.b(color);
} }
IArmourTextureResolver resolver = armour.getTextureResolver(IArmourTextureResolver.DEFAULT); IArmourTextureResolver resolver = model.getArmourTextureResolver();
boolean glint = itemstack.hasGlint(); boolean glint = itemstack.hasGlint();
@ -92,7 +87,6 @@ public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & IP
} }
} }
} }
}
private static <T extends LivingEntity, V extends BipedEntityModel<T> & IArmourModel> void renderArmourPart( private static <T extends LivingEntity, V extends BipedEntityModel<T> & IArmourModel> void renderArmourPart(
MatrixStack matrices, VertexConsumerProvider provider, MatrixStack matrices, VertexConsumerProvider provider,

View file

@ -75,7 +75,7 @@ abstract class AbstractNpcRenderer<T extends MobEntity & VillagerDataContainer>
if (race.isHuman()) { if (race.isHuman()) {
race = Race.EARTH; race = Race.EARTH;
} }
return ModelWrapper.<T, ClientPonyModel<T>>of(ModelType.getPlayerModel(race).getKey(false), this::initializeModel); return ModelType.getPlayerModel(race).create(false, this::initializeModel);
} }
protected void initializeModel(ClientPonyModel<T> model) { protected void initializeModel(ClientPonyModel<T> model) {

View file

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

View file

@ -1,4 +0,0 @@
{
"parent": "minelittlepony:armour_inner",
"dilate": 0.3
}