diff --git a/src/main/java/com/minelittlepony/api/model/ModelAttributes.java b/src/main/java/com/minelittlepony/api/model/ModelAttributes.java index 8b2b8488..807a5275 100644 --- a/src/main/java/com/minelittlepony/api/model/ModelAttributes.java +++ b/src/main/java/com/minelittlepony/api/model/ModelAttributes.java @@ -145,6 +145,7 @@ public class ModelAttributes { isGoingFast &= zMotion > 0.4F; isGoingFast |= entity.isUsingRiptide(); isGoingFast |= entity.isGliding(); + isGoingFast &= !entity.isSpectator(); motionLerp = MathUtil.clampLimit(zMotion * 30, 1); diff --git a/src/main/java/com/minelittlepony/api/model/Models.java b/src/main/java/com/minelittlepony/api/model/Models.java index b2d0c5a5..509eec92 100644 --- a/src/main/java/com/minelittlepony/api/model/Models.java +++ b/src/main/java/com/minelittlepony/api/model/Models.java @@ -4,15 +4,11 @@ import net.minecraft.client.render.entity.equipment.EquipmentModel; import net.minecraft.item.ItemStack; import net.minecraft.util.Util; -import org.jetbrains.annotations.Nullable; - import com.minelittlepony.client.model.AbstractPonyModel; -import com.minelittlepony.client.model.PlayerModelKey; import com.minelittlepony.client.model.armour.*; import com.minelittlepony.mson.api.ModelKey; +import com.minelittlepony.mson.api.MsonModel; -import java.util.*; -import java.util.function.Consumer; import java.util.function.Function; /** @@ -23,20 +19,15 @@ public record Models> ( M body ) { - public Models(PlayerModelKey playerModelKey, boolean slimArms, @Nullable Consumer initializer) { - this(Util.memoize(key -> key.createModel(playerModelKey.armorFactory())), playerModelKey.getKey(slimArms).createModel()); - if (initializer != null) { - initializer.accept(body); - } + public Models(ModelKey modelKey, MsonModel.Factory> armorFactory) { + this(Util.memoize(key -> key.createModel(armorFactory)), modelKey.createModel()); } - public Models(ModelKey key) { + public Models(ModelKey key) { this(Util.memoize(k -> k.createModel()), key.createModel()); } - public Optional> getArmourModel(ItemStack stack, EquipmentModel.LayerType layerType, ArmourVariant variant) { - return ArmorModelRegistry.getModelKey(stack.getItem(), layerType) - .or(() -> variant.getDefaultModel(layerType)) - .map(armor); + public AbstractPonyModel getArmourModel(ItemStack stack, EquipmentModel.LayerType layerType, ArmourVariant variant) { + return armor.apply(ArmorModelRegistry.getModelKey(stack.getItem(), layerType, variant)); } } diff --git a/src/main/java/com/minelittlepony/client/model/AbstractPonyModel.java b/src/main/java/com/minelittlepony/client/model/AbstractPonyModel.java index 79bb22b8..1b412700 100644 --- a/src/main/java/com/minelittlepony/client/model/AbstractPonyModel.java +++ b/src/main/java/com/minelittlepony/client/model/AbstractPonyModel.java @@ -86,6 +86,7 @@ public abstract class AbstractPonyModel extends Clien protected void setModelVisibilities(T state) { resetPivot(head, neck, leftArm, rightArm, leftLeg, rightLeg); hat.visible = head.visible && !state.attributes.isHorsey; + neck.visible = body.visible; if (state.attributes.isHorsey) { neck.visible = head.visible; } else { diff --git a/src/main/java/com/minelittlepony/client/model/PlayerModelKey.java b/src/main/java/com/minelittlepony/client/model/PlayerModelKey.java index 65d42f9f..92187a27 100644 --- a/src/main/java/com/minelittlepony/client/model/PlayerModelKey.java +++ b/src/main/java/com/minelittlepony/client/model/PlayerModelKey.java @@ -3,8 +3,6 @@ package com.minelittlepony.client.model; import net.minecraft.client.model.Model; import net.minecraft.client.model.ModelPart; -import org.jetbrains.annotations.Nullable; - import com.minelittlepony.api.model.Models; import com.minelittlepony.api.model.PonyModel; import com.minelittlepony.client.MineLittlePony; @@ -28,15 +26,15 @@ public record PlayerModelKey> ( ); } - public ModelKey getKey(boolean slimArms) { - return slimArms ? alexKey : steveKey; + public Models alex() { + return new Models(alexKey, armorFactory); } - public Models create(boolean slimArms) { - return create(slimArms, null); + public Models steve() { + return new Models(steveKey, armorFactory); } - public Models create(boolean slimArms, @Nullable Consumer initializer) { - return new Models<>(this, slimArms, initializer); + public Models create(boolean slimArms) { + return slimArms ? alex() : steve(); } } diff --git a/src/main/java/com/minelittlepony/client/model/armour/ArmorModelRegistry.java b/src/main/java/com/minelittlepony/client/model/armour/ArmorModelRegistry.java index db392773..ce2663eb 100644 --- a/src/main/java/com/minelittlepony/client/model/armour/ArmorModelRegistry.java +++ b/src/main/java/com/minelittlepony/client/model/armour/ArmorModelRegistry.java @@ -2,25 +2,35 @@ package com.minelittlepony.client.model.armour; import net.minecraft.item.Item; import net.minecraft.client.render.entity.equipment.EquipmentModel; -import net.minecraft.registry.Registries; import net.minecraft.util.Identifier; import com.minelittlepony.client.model.AbstractPonyModel; import com.minelittlepony.mson.api.ModelKey; import com.minelittlepony.mson.api.Mson; +import com.minelittlepony.util.ResourceUtil; import java.util.*; public interface ArmorModelRegistry { static final Map>>> REGISTRY = new HashMap<>(); - public static Optional>> getModelKey(Item item, EquipmentModel.LayerType layerType) { - Identifier id = Registries.ITEM.getId(item); - if (id.getNamespace().equals("minecraft")) { - return Optional.empty(); - } - return REGISTRY.computeIfAbsent(id.withPath(p -> "armor/" + layerType.name().toLowerCase(Locale.ROOT) + "_" + p + ".json"), i -> { - return Optional.of(Mson.getInstance().registerModel(i, PonyArmourModel::new)); - }).filter(key -> key.getModelData().isPresent()); + @SuppressWarnings("deprecation") + public static ModelKey> getModelKey(Item item, EquipmentModel.LayerType layerType, ArmourVariant variant) { + return item.getRegistryEntry().getKey().map(key -> key.getValue()).flatMap(id -> { + if (id.getNamespace().equals("minecraft")) { + return Optional.empty(); + } + return REGISTRY.computeIfAbsent(id.withPath(p -> ResourceUtil.format("armor/%s_%s.json", layerName(layerType), p)), i -> { + return Optional.of(Mson.getInstance().registerModel(i, PonyArmourModel::new)); + }).filter(key -> key.getModelData().isPresent()); + }).orElse(variant.getDefaultModel(layerType)); + } + + private static String layerName(EquipmentModel.LayerType layerType) { + return switch (layerType) { + case HUMANOID -> "outer"; + case HUMANOID_LEGGINGS -> "inner"; + default -> layerType.name().toLowerCase(Locale.ROOT); + }; } } diff --git a/src/main/java/com/minelittlepony/client/model/armour/ArmourTextureResolver.java b/src/main/java/com/minelittlepony/client/model/armour/ArmourTextureResolver.java index 50a8e4f9..e13d905d 100644 --- a/src/main/java/com/minelittlepony/client/model/armour/ArmourTextureResolver.java +++ b/src/main/java/com/minelittlepony/client/model/armour/ArmourTextureResolver.java @@ -18,17 +18,22 @@ import java.util.stream.Stream; /** * The default texture resolver used by Mine Little Pony. *

- * Textures found are of the format: + * Textures are resolved by taking the original path and replacing "humanoid" with "ponified". *

- * namespace:textures/models/armor/material_layer_[outer|1|inner|2](_overlay)(_custom_#)(_pony).png - *

- *

- * - Textures ending _pony are returned first if found - * - _custom_# corresponds to a CustomModelData NBT integer value on the item passed, if available - * - _overlay is used for the second layer of leather armour, or mods if they make use of it. Can be anything! Check your mod's documentation for values supported. - * - outer|1|inner|2 is the layer. outer is an alias for 1 and inner is an alias for 2. Named versions are used instead of numbers if available. - * - the "minecraft" namespace is always replaced with "minelittlepony" + * For example: + * + * assets/minecraft/textures/entity/equipment/humanoid/iron.png + * Becomes: assets/minecraft/textures/entity/equipment/ponified/iron.png + * + * assets/minecraft/textures/entity/equipment/humanoid_leggings/iron.png + * Becomes: assets/minecraft/textures/entity/equipment/ponified_leggings/iron.png *

+ * In addition to the above, unlike in vanilla, all pony armour pieces make use of both the regular and leggings textures to show in two different layers. + * In general, the textures are distributed as follows: + * Helmet = ponified_leggings + * Chestplate = ponified (banner) + ponified_leggings (body plates) + * Leggings = ponified_leggings (leg chainmail) + * Boots = ponified (knee guards and boots) */ public class ArmourTextureResolver implements ArmourTextureLookup, IdentifiableResourceReloadListener { public static final Identifier ID = MineLittlePony.id("armor_textures"); diff --git a/src/main/java/com/minelittlepony/client/model/armour/ArmourVariant.java b/src/main/java/com/minelittlepony/client/model/armour/ArmourVariant.java index 55c6f1c2..6cce33d6 100644 --- a/src/main/java/com/minelittlepony/client/model/armour/ArmourVariant.java +++ b/src/main/java/com/minelittlepony/client/model/armour/ArmourVariant.java @@ -6,22 +6,20 @@ import com.minelittlepony.client.model.AbstractPonyModel; import com.minelittlepony.client.model.ModelType; import com.minelittlepony.mson.api.ModelKey; -import java.util.Optional; - public enum ArmourVariant { NORMAL(ModelType.INNER_PONY_ARMOR, ModelType.OUTER_PONY_ARMOR), LEGACY(ModelType.INNER_VANILLA_ARMOR, ModelType.OUTER_VANILLA_ARMOR), TRIM(ModelType.INNER_VANILLA_ARMOR, ModelType.OUTER_VANILLA_ARMOR); - private final Optional>> innerModel; - private final Optional>> outerModel; + private final ModelKey> innerModel; + private final ModelKey> outerModel; ArmourVariant(ModelKey> inner, ModelKey> outer) { - this.innerModel = Optional.of(inner); - this.outerModel = Optional.of(outer); + this.innerModel = inner; + this.outerModel = outer; } - public Optional>> getDefaultModel(EquipmentModel.LayerType layerType) { + public ModelKey> getDefaultModel(EquipmentModel.LayerType layerType) { return layerType == EquipmentModel.LayerType.HUMANOID_LEGGINGS ? innerModel : outerModel; } } diff --git a/src/main/java/com/minelittlepony/client/model/armour/PonifiedEquipmentRenderer.java b/src/main/java/com/minelittlepony/client/model/armour/PonifiedEquipmentRenderer.java index 31dbb47e..060889f7 100644 --- a/src/main/java/com/minelittlepony/client/model/armour/PonifiedEquipmentRenderer.java +++ b/src/main/java/com/minelittlepony/client/model/armour/PonifiedEquipmentRenderer.java @@ -82,7 +82,7 @@ public class PonifiedEquipmentRenderer extends EquipmentRenderer { VertexConsumer armorConsumer = getArmorVertexConsumer(plugin, equipmentSlot, vertices, layerTexture, layerType, hasGlint); if (armorConsumer != null) { ArmourVariant variant = layer.usePlayerTexture() ? ArmourVariant.LEGACY : armorTexture.variant(); - AbstractPonyModel model = models.getArmourModel(stack, layerType, variant).orElse(null); + AbstractPonyModel model = models.getArmourModel(stack, layerType, variant); if (model != null) { model.setAngles(entity); models.body().copyTransforms(model); diff --git a/src/main/java/com/minelittlepony/client/model/part/PonyEars.java b/src/main/java/com/minelittlepony/client/model/part/PonyEars.java index deefe4dd..b1cc3339 100644 --- a/src/main/java/com/minelittlepony/client/model/part/PonyEars.java +++ b/src/main/java/com/minelittlepony/client/model/part/PonyEars.java @@ -57,8 +57,8 @@ public class PonyEars implements SubModel, MsonModel { @Override public void setVisible(boolean visible, PonyRenderState state) { - right.visible = visible && !state.race.isHuman(); - left.visible = visible && !state.race.isHuman(); + right.visible = !state.race.isHuman(); + left.visible = !state.race.isHuman(); if (state.attributes.isHorsey) { left.pivotX = -1; diff --git a/src/main/java/com/minelittlepony/client/model/part/PonySnout.java b/src/main/java/com/minelittlepony/client/model/part/PonySnout.java index d5e599ea..f46d0aea 100644 --- a/src/main/java/com/minelittlepony/client/model/part/PonySnout.java +++ b/src/main/java/com/minelittlepony/client/model/part/PonySnout.java @@ -39,7 +39,7 @@ public class PonySnout implements SubModel, MsonModel { @Override public void setVisible(boolean visible, PonyRenderState state) { - visible &= !state.attributes.isHorsey + visible = !state.attributes.isHorsey && !state.attributes.metadata.race().isHuman() && PonyConfig.getInstance().snuzzles.get(); Gender gender = state.attributes.metadata.gender(); diff --git a/src/main/java/com/minelittlepony/client/model/part/PonyTail.java b/src/main/java/com/minelittlepony/client/model/part/PonyTail.java index b91acb7e..bed4ac64 100644 --- a/src/main/java/com/minelittlepony/client/model/part/PonyTail.java +++ b/src/main/java/com/minelittlepony/client/model/part/PonyTail.java @@ -92,14 +92,16 @@ public class PonyTail implements SubModel, MsonModel { @Override public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlay, int light, int color) { - stack.push(); - tail.rotate(stack); + if (tail.visible) { + stack.push(); + tail.rotate(stack); - for (int i = 0; i < segments.size(); i++) { - segments.get(i).render(stack, vertices, i, overlay, light, color); + for (int i = 0; i < segments.size(); i++) { + segments.get(i).render(stack, vertices, i, overlay, light, color); + } + + stack.pop(); } - - stack.pop(); } public static class Segment { diff --git a/src/main/java/com/minelittlepony/client/render/EquineRenderManager.java b/src/main/java/com/minelittlepony/client/render/EquineRenderManager.java index 08286329..365f222d 100644 --- a/src/main/java/com/minelittlepony/client/render/EquineRenderManager.java +++ b/src/main/java/com/minelittlepony/client/render/EquineRenderManager.java @@ -67,9 +67,8 @@ public class EquineRenderManager< context.setModel(models.body()); } - @SuppressWarnings({"rawtypes", "unchecked"}) public EquineRenderManager(PonyRenderContext context, Transformer transformer, ModelKey key) { - this(context, transformer, new Models(key)); + this(context, transformer, new Models<>(key)); } public void setModelsLookup(Function> modelsLookup) { diff --git a/src/main/java/com/minelittlepony/client/render/blockentity/skull/PlayerPonySkull.java b/src/main/java/com/minelittlepony/client/render/blockentity/skull/PlayerPonySkull.java index a7ae1265..46cefd3c 100644 --- a/src/main/java/com/minelittlepony/client/render/blockentity/skull/PlayerPonySkull.java +++ b/src/main/java/com/minelittlepony/client/render/blockentity/skull/PlayerPonySkull.java @@ -62,7 +62,7 @@ public class PlayerPonySkull implements ISkull { return false; } } - ponyHead = modelCache.computeIfAbsent(ModelType.getPlayerModel(race), key -> key.getKey(false).createModel()); + ponyHead = modelCache.computeIfAbsent(ModelType.getPlayerModel(race), key -> key.steveKey().createModel()); state.pony = pony; state.race = pony.race(); state.attributes.size = pony.size(); diff --git a/src/main/java/com/minelittlepony/client/render/entity/EnderStallionRenderer.java b/src/main/java/com/minelittlepony/client/render/entity/EnderStallionRenderer.java index a34155b6..6e9c2d10 100644 --- a/src/main/java/com/minelittlepony/client/render/entity/EnderStallionRenderer.java +++ b/src/main/java/com/minelittlepony/client/render/entity/EnderStallionRenderer.java @@ -8,7 +8,6 @@ import com.minelittlepony.client.model.entity.EnderStallionModel; import com.minelittlepony.client.render.entity.feature.GlowingEyesFeature; import com.minelittlepony.client.render.entity.feature.HeldItemFeature; import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier; -import com.minelittlepony.client.render.entity.feature.GlowingEyesFeature.IGlowingRenderer; import net.minecraft.block.BlockState; import net.minecraft.client.item.ItemModelManager; @@ -26,7 +25,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Random; -public class EnderStallionRenderer extends PonyRenderer implements IGlowingRenderer { +public class EnderStallionRenderer extends PonyRenderer { public static final Identifier ENDERMAN = MineLittlePony.id("textures/entity/enderman/enderman_pony.png"); private static final Identifier EYES = MineLittlePony.id("textures/entity/enderman/enderman_pony_eyes.png"); @@ -43,8 +42,7 @@ public class EnderStallionRenderer extends PonyRenderer((PonyRenderer)this, context)); - addPonyFeature(new GlowingEyesFeature(this)); - + addPonyFeature(new GlowingEyesFeature(this, EYES)); } @Override @@ -89,11 +87,6 @@ public class EnderStallionRenderer extends PonyRenderer & IGlowingRenderer> GlowingEyesFeature(V renderer) { - super(renderer); - layer = RenderLayer.getEyes(renderer.getEyeTexture()); + public GlowingEyesFeature(PonyRenderContext context, Identifier texture) { + super(context.upcast()); + layer = RenderLayer.getEyes(texture); } @Override public RenderLayer getEyesTexture() { return layer; } - - public interface IGlowingRenderer { - Identifier getEyeTexture(); - } } diff --git a/src/main/java/com/minelittlepony/client/render/entity/feature/SkullFeature.java b/src/main/java/com/minelittlepony/client/render/entity/feature/SkullFeature.java index 617422cd..46849200 100644 --- a/src/main/java/com/minelittlepony/client/render/entity/feature/SkullFeature.java +++ b/src/main/java/com/minelittlepony/client/render/entity/feature/SkullFeature.java @@ -25,13 +25,10 @@ public class SkullFeature< protected final ItemModelManager itemModelResolver; private final HeadFeatureRenderer.HeadTransformation headTransformation; - private final boolean scaleForChild; - public SkullFeature(PonyRenderContext context, ItemModelManager itemModelResolver, HeadFeatureRenderer.HeadTransformation headTransformation, boolean scaleForChild) { super(context); this.itemModelResolver = itemModelResolver; this.headTransformation = headTransformation; - this.scaleForChild = scaleForChild; } @Override diff --git a/src/main/java/com/minelittlepony/client/render/entity/npc/AbstractNpcRenderer.java b/src/main/java/com/minelittlepony/client/render/entity/npc/AbstractNpcRenderer.java index 88df81e9..33b4dd0c 100644 --- a/src/main/java/com/minelittlepony/client/render/entity/npc/AbstractNpcRenderer.java +++ b/src/main/java/com/minelittlepony/client/render/entity/npc/AbstractNpcRenderer.java @@ -5,6 +5,7 @@ import net.minecraft.entity.mob.MobEntity; import net.minecraft.util.Identifier; import net.minecraft.village.*; +import com.minelittlepony.api.model.Models; import com.minelittlepony.api.model.gear.Gear; import com.minelittlepony.api.pony.meta.Race; import com.minelittlepony.api.pony.meta.Wearable; @@ -19,13 +20,15 @@ abstract class AbstractNpcRenderer< private final NpcClothingFeature, AbstractNpcRenderer> clothing; public AbstractNpcRenderer(EntityRendererFactory.Context context, String type, TextureSupplier textureSupplier, TextureSupplier formatter) { - super(context, ModelType.getPlayerModel(Race.EARTH).getKey(false), SillyPonyTextureSupplier.create(textureSupplier, formatter)); + super(context, ModelType.getPlayerModel(Race.EARTH).steveKey(), SillyPonyTextureSupplier.create(textureSupplier, formatter)); clothing = new NpcClothingFeature<>(this, type); this.manager.setModelsLookup(race -> { if (race.isHuman()) { race = Race.EARTH; } - return ModelType.getPlayerModel(race).create(false, this::initializeModel); + Models> models = ModelType.getPlayerModel(race).steve(); + initializeModel(models.body()); + return models; }); addFeature(clothing); } diff --git a/src/main/java/com/minelittlepony/client/render/entity/npc/TraderRenderer.java b/src/main/java/com/minelittlepony/client/render/entity/npc/TraderRenderer.java index af741842..cd266247 100644 --- a/src/main/java/com/minelittlepony/client/render/entity/npc/TraderRenderer.java +++ b/src/main/java/com/minelittlepony/client/render/entity/npc/TraderRenderer.java @@ -15,7 +15,7 @@ public class TraderRenderer extends PonyRenderer