Rewrites round tri

This commit is contained in:
Sollace 2023-09-26 15:59:07 +01:00
parent 0e30b2c8dd
commit b37ffa9860
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
54 changed files with 417 additions and 567 deletions

View file

@ -3,6 +3,7 @@ package com.minelittlepony.api.config;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import com.minelittlepony.api.pony.meta.*; import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.common.client.gui.VisibilityMode;
import com.minelittlepony.common.util.GamePaths; import com.minelittlepony.common.util.GamePaths;
import com.minelittlepony.common.util.settings.*; import com.minelittlepony.common.util.settings.*;
@ -54,7 +55,7 @@ public class PonyConfig extends Config {
public final Setting<Boolean> horsieMode = value("settings", "horsieMode", false) public final Setting<Boolean> horsieMode = value("settings", "horsieMode", false)
.addComment("Enables the alternative horsey models from the April Fools 2023 update"); .addComment("Enables the alternative horsey models from the April Fools 2023 update");
public final Setting<Sizes> sizeOverride = value("debug", "sizeOverride", Sizes.UNSET) public final Setting<SizePreset> sizeOverride = value("debug", "sizeOverride", SizePreset.UNSET)
.addComment("Overrides pony sizes") .addComment("Overrides pony sizes")
.addComment("Possible values: TALL, BULKY, LANKY, NORMAL, YEARLING, FOAL, UNSET (default)"); .addComment("Possible values: TALL, BULKY, LANKY, NORMAL, YEARLING, FOAL, UNSET (default)");
@ -72,6 +73,12 @@ public class PonyConfig extends Config {
.addComment("Disables certain easter eggs and secrets (party pooper)") .addComment("Disables certain easter eggs and secrets (party pooper)")
.addComment("Turning this off may help with compatibility in some cases"); .addComment("Turning this off may help with compatibility in some cases");
public final Setting<VisibilityMode> horseButton = value("horseButton", VisibilityMode.AUTO)
.addComment("Whether to show the mine little pony settings button on the main menu")
.addComment("AUTO (default) - only show when HDSkins is not installed")
.addComment("ON - always show")
.addComment("OFF - never show");
public PonyConfig(Path path) { public PonyConfig(Path path) {
super(HEIRARCHICAL_JSON_ADAPTER, path); super(HEIRARCHICAL_JSON_ADAPTER, path);
instance = this; instance = this;
@ -132,14 +139,14 @@ public class PonyConfig extends Config {
} }
public static Size getEffectiveSize(Size size) { public static Size getEffectiveSize(Size size) {
Sizes sz = instance.sizeOverride.get(); SizePreset sz = instance.sizeOverride.get();
if (sz != Sizes.UNSET) { if (sz != SizePreset.UNSET) {
return sz; return sz;
} }
if (size == Sizes.UNSET || !instance.sizes.get()) { if (size == SizePreset.UNSET || !instance.sizes.get()) {
return Sizes.NORMAL; return SizePreset.NORMAL;
} }
return size; return size;

View file

@ -23,7 +23,7 @@ public class MsgPonyData {
new MsgSize(buffer), new MsgSize(buffer),
buffer.readInt(), buffer.readInt(),
buffer.readBoolean(), buffer.readBoolean(),
Flags.read(Wearable.class, buffer) Flags.read(Wearable.NONE, buffer)
); );
} }

View file

@ -165,7 +165,7 @@ public class ModelAttributes {
} }
public Interpolator getMainInterpolator() { public Interpolator getMainInterpolator() {
return metadata.getInterpolator(interpolatorId); return Interpolator.linear(interpolatorId);
} }
public boolean shouldLiftArm(ArmPose pose, ArmPose complement, float sigma) { public boolean shouldLiftArm(ArmPose pose, ArmPose complement, float sigma) {

View file

@ -79,7 +79,7 @@ public interface PonyModel<T extends LivingEntity> extends MsonModel, ModelWithH
* i.e. Used to change wing rendering when using saddlebags. * i.e. Used to change wing rendering when using saddlebags.
*/ */
default boolean isEmbedded(Wearable wearable) { default boolean isEmbedded(Wearable wearable) {
return getAttributes().metadata.isWearing(wearable); return getAttributes().metadata.gear().matches(wearable);
} }
} }

View file

@ -6,7 +6,6 @@ import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ComparisonChain; import com.google.common.collect.ComparisonChain;
import com.minelittlepony.api.pony.meta.*; import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.common.util.animation.Interpolator;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
@ -53,64 +52,40 @@ public record PonyData (
/** /**
* Gets the trigger pixel values as they appeared in the underlying image. * Gets the trigger pixel values as they appeared in the underlying image.
*/ */
Map<String, TriggerPixelType<?>> attributes Map<String, TValue<?>> attributes
) implements Comparable<PonyData> { ) implements Comparable<PonyData> {
private static final Function<Race, PonyData> OF_RACE = Util.memoize(race -> { public static final int DEFAULT_MAGIC_COLOR = 0x4444aa;
return new PonyData(race, TailLength.FULL, TailShape.STRAIGHT, Gender.MARE, Sizes.NORMAL, 0x4444aa, Wearable.EMPTY_FLAGS, true, Util.make(new TreeMap<>(), attributes -> { private static final Function<Race, PonyData> OF_RACE = Util.memoize(race -> new PonyData(race, TailLength.FULL, TailShape.STRAIGHT, Gender.MARE, SizePreset.NORMAL, DEFAULT_MAGIC_COLOR, true, Wearable.EMPTY_FLAGS));
attributes.put("race", race);
attributes.put("tailLength", TailLength.FULL);
attributes.put("tailShape", TailShape.STRAIGHT);
attributes.put("gender", Gender.MARE);
attributes.put("size", Sizes.NORMAL);
attributes.put("magic", TriggerPixelType.of(0x4444aa));
attributes.put("gear", TriggerPixelType.of(0));
}));
});
public static final PonyData NULL = OF_RACE.apply(Race.HUMAN); public static final PonyData NULL = OF_RACE.apply(Race.HUMAN);
public static PonyData emptyOf(Race race) { public static PonyData emptyOf(Race race) {
return OF_RACE.apply(race); return OF_RACE.apply(race);
} }
public PonyData(TriggerPixel.Mat image, boolean noSkin) {
public PonyData(Race race, TailLength tailLength, TailShape tailShape, Gender gender, Size size, int glowColor, boolean noSkin, Flags<Wearable> wearables) { this(
this(race, tailLength, tailShape, gender, size, glowColor, wearables, noSkin, Util.make(new TreeMap<>(), map -> { TriggerPixel.RACE.read(image),
map.put("race", race); TriggerPixel.TAIL.read(image),
map.put("tailLength", tailLength); TriggerPixel.TAIL_SHAPE.read(image),
map.put("tailShape", tailShape); TriggerPixel.GENDER.read(image),
map.put("gender", gender); TriggerPixel.SIZE.read(image),
map.put("size", size); TriggerPixel.GLOW.read(image),
map.put("magic", TriggerPixelType.of(glowColor)); noSkin,
map.put("gear", TriggerPixelType.of(wearables.colorCode())); TriggerPixel.WEARABLES.read(image)
}));
}
public PonyData(Race race, TailLength tailLength, TailShape tailShape, Gender gender, Size size, int glowColor, TriggerPixelType.Multiple<Wearable> wearables, boolean noSkin) {
this(race, tailLength, tailShape, gender, size, glowColor,
Flags.of(Wearable.class, wearables.colorCode(), wearables.value()),
noSkin, Util.make(new TreeMap<>(), map -> {
map.put("race", race);
map.put("tailLength", tailLength);
map.put("tailShape", tailShape);
map.put("gender", gender);
map.put("size", size);
map.put("magic", TriggerPixelType.of(glowColor));
map.put("gear", wearables);
})
); );
} }
/** public PonyData(Race race, TailLength tailLength, TailShape tailShape, Gender gender, Size size, int glowColor, boolean noSkin, Flags<Wearable> wearables) {
* Checks it this pony is wearing the given accessory. this(race, tailLength, tailShape, gender, size, glowColor, wearables, noSkin, Util.make(new TreeMap<>(), map -> {
*/ map.put("race", race);
public boolean isWearing(Wearable wearable) { map.put("tailLength", tailLength);
return gear().includes(wearable); map.put("tailShape", tailShape);
} map.put("gender", gender);
map.put("size", size);
/** map.put("magic", new TValue.Numeric(glowColor));
* Gets an interpolator for interpolating values. map.put("gear", wearables);
*/ })
public Interpolator getInterpolator(UUID interpolatorId) { );
return Interpolator.linear(interpolatorId);
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package com.minelittlepony.api.pony; package com.minelittlepony.api.pony;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -10,8 +11,7 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
/** /**
* The PonyManager is responsible for reading and recoding all the pony data associated with an entity of skin. * The PonyManager is responsible for reading and recoding all the pony data associated with the skin of an entity.
*
*/ */
public interface PonyManager { public interface PonyManager {
/** /**
@ -19,7 +19,25 @@ public interface PonyManager {
* *
* If the supplied entity is null or can't be determined to be a pony, returns the empty optional. * If the supplied entity is null or can't be determined to be a pony, returns the empty optional.
*/ */
Optional<Pony> getPony(@Nullable Entity entity); default Optional<Pony> getPony(@Nullable Entity entity) {
return entity instanceof LivingEntity living ? getPony(living) : Optional.empty();
}
/**
* Gets a pony representation of the passed in entity.
*
* If the supplied entity is null or can't be determined to be a pony, returns the empty optional.
*/
Optional<Pony> getPony(LivingEntity entity);
/**
* Gets a random background pony determined by the given uuid.
*
* Useful for mods that offer customisation, especially ones that have a whole lot of NPCs.
*
* @param uuid id of a player
*/
Pony getBackgroundPony(UUID uuid);
/** /**
* Gets or creates a pony for the given player. * Gets or creates a pony for the given player.
@ -29,13 +47,6 @@ public interface PonyManager {
*/ */
Pony getPony(PlayerEntity player); Pony getPony(PlayerEntity player);
/**
* Gets or creates a pony for the given skin resource and vanilla model type.
*
* @param resource A texture resource
*/
Pony getPony(Identifier resource);
/** /**
* Gets or creates a pony for the given skin resource and entity id. * Gets or creates a pony for the given skin resource and entity id.
* *
@ -46,23 +57,16 @@ public interface PonyManager {
* @param resource A texture resource * @param resource A texture resource
* @param uuid id of a player * @param uuid id of a player
*/ */
Pony getPony(Identifier resource, UUID uuid); Pony getPony(@Nullable Identifier resource, @Nullable UUID uuid);
/** /**
* Gets a random background pony determined by the given uuid. * Gets or creates a pony for the given skin resource and vanilla model type.
* *
* Useful for mods that offer customisation, especially ones that have a whole lot of NPCs. * @param resource A texture resource
*
* @param uuid A UUID. Either a user or an entity.
*/ */
Pony getBackgroundPony(UUID uuid); default Pony getPony(Identifier resource) {
return getPony(resource, null);
/** }
* De-registers a pony from the cache.
*/
void removePony(Identifier resource);
void clearCache();
interface ForcedPony {} interface ForcedPony {}

View file

@ -4,30 +4,30 @@ import net.minecraft.network.PacketByteBuf;
import java.util.*; import java.util.*;
public record Flags<T extends Enum<T>> ( public record Flags<T extends Enum<T> & TValue<T>> (
boolean[] flags, T def,
List<T> values, Set<T> values,
int colorCode int colorCode
) implements Comparable<Flags<T>> { ) implements Comparable<Flags<T>>, TValue<T> {
public static <T extends Enum<T>> Flags<T> of(Class<T> type) { public static <T extends Enum<T> & TValue<T>> Flags<T> of(T def) {
return new Flags<>(new boolean[type.getEnumConstants().length], List.<T>of(), 0); return new Flags<>(def, Set.<T>of(), 0);
} }
public static <T extends Enum<T>> Flags<T> of(Class<T> type, int colorCode, boolean...flags) { public static <T extends Enum<T> & TValue<T>> Flags<T> of(T def, int colorCode, Set<T> values) {
return new Flags<>(flags, flags(type.getEnumConstants(), flags), colorCode); return new Flags<>(def, values, colorCode);
} }
public static <T extends Enum<T>> Flags<T> read(Class<T> type, PacketByteBuf buffer) { public static <T extends Enum<T> & TValue<T>> Flags<T> read(T def, PacketByteBuf buffer) {
int length = buffer.readVarInt(); int length = buffer.readVarInt();
List<T> values = new ArrayList<>(); @SuppressWarnings("unchecked")
T[] all = type.getEnumConstants(); Set<T> values = EnumSet.noneOf((Class<T>)def.getClass());
boolean[] flags = new boolean[all.length]; @SuppressWarnings("unchecked")
T[] all = (T[])def.getClass().getEnumConstants();
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
values.add(all[buffer.readInt()]); values.add(all[buffer.readInt()]);
flags[i] = true;
} }
return new Flags<>(flags, values, buffer.readInt()); return new Flags<>(def, values, buffer.readInt());
} }
public static <T> List<T> flags(T[] values, boolean[] flags) { public static <T> List<T> flags(T[] values, boolean[] flags) {
@ -38,16 +38,30 @@ public record Flags<T extends Enum<T>> (
return wears; return wears;
} }
public boolean includes(T t) {
return flags[t.ordinal()];
}
public int compareTo(Flags<T> other) {
return Arrays.compare(flags, other.flags);
}
public void write(PacketByteBuf buffer) { public void write(PacketByteBuf buffer) {
buffer.writeCollection(values, (buf, value) -> buf.writeInt(value.ordinal())); buffer.writeCollection(values, (buf, value) -> buf.writeInt(value.ordinal()));
buffer.writeInt(colorCode); buffer.writeInt(colorCode);
} }
@Override
public String name() {
return "[Flags " + values + "]";
}
@Override
public List<TValue<T>> getOptions() {
return def.getOptions();
}
@SuppressWarnings("unchecked")
@Override
public boolean matches(TValue<?> o) {
return o.getClass() == def.getClass() && values.contains((T)o);
}
@Override
public int compareTo(Flags<T> other) {
return Integer.compare(colorCode(), other.colorCode());
}
} }

View file

@ -1,6 +1,6 @@
package com.minelittlepony.api.pony.meta; package com.minelittlepony.api.pony.meta;
public enum Gender implements TriggerPixelType<Gender> { public enum Gender implements TValue<Gender> {
MARE(0), MARE(0),
STALLION(0xffffff), STALLION(0xffffff),
ABOMONATION(0x888888); ABOMONATION(0x888888);

View file

@ -1,8 +1,6 @@
package com.minelittlepony.api.pony.meta; package com.minelittlepony.api.pony.meta;
import java.util.*; public enum Race implements TValue<Race> {
public enum Race implements TriggerPixelType<Race> {
HUMAN (0x000000, false, false), HUMAN (0x000000, false, false),
EARTH (0xf9b131, false, false), EARTH (0xf9b131, false, false),
PEGASUS (0x88caf0, true, false), PEGASUS (0x88caf0, true, false),
@ -17,16 +15,13 @@ public enum Race implements TriggerPixelType<Race> {
BATPONY (0xeeeeee, true, false), BATPONY (0xeeeeee, true, false),
SEAPONY (0x3655dd, false, true); SEAPONY (0x3655dd, false, true);
private boolean wings; private final boolean wings;
private boolean horn; private final boolean horn;
private int triggerPixel; private final int colorCode;
public static final List<Race> REGISTRY = Arrays.asList(values());
Race(int triggerPixel, boolean wings, boolean horn) {
this.triggerPixel = triggerPixel;
Race(int colorCode, boolean wings, boolean horn) {
this.colorCode = colorCode;
this.wings = wings; this.wings = wings;
this.horn = horn; this.horn = horn;
} }
@ -68,6 +63,6 @@ public enum Race implements TriggerPixelType<Race> {
@Override @Override
public int colorCode() { public int colorCode() {
return triggerPixel; return colorCode;
} }
} }

View file

@ -3,13 +3,13 @@ package com.minelittlepony.api.pony.meta;
/** /**
* Represents the different model sizes that are possible. * Represents the different model sizes that are possible.
* *
* For a list of possible presets, look at {@link Sizes}. * For a list of possible presets, look at {@link SizePreset}.
* This interface exists for servers so they can work with this information even though they might not have access to the client config. * This interface exists for servers so they can work with this information even though they might not have access to the client config.
* *
*/ */
public interface Size extends TriggerPixelType<Size> { public interface Size extends TValue<Size> {
/** /**
* The Enum index of this size. May be used on the client to convert to an instance of Sizes or use {@link Sizes#of} * The Enum index of this size. May be used on the client to convert to an instance of Sizes or use {@link SizePreset#of}
* *
* Made to be compatible with the enum variant. * Made to be compatible with the enum variant.
*/ */

View file

@ -9,7 +9,7 @@ import com.minelittlepony.api.config.PonyConfig;
* *
* For spooky things at a distance, use {@link Size} instead. * For spooky things at a distance, use {@link Size} instead.
*/ */
public enum Sizes implements Size { public enum SizePreset implements Size {
TALL (0x534b76, 0.45f, 1.1F, 1.15F), TALL (0x534b76, 0.45f, 1.1F, 1.15F),
BULKY (0xce3254, 0.5f, 1, 1.05F), BULKY (0xce3254, 0.5f, 1, 1.05F),
LANKY (0x3254ce, 0.45F, 0.85F, 0.9F), LANKY (0x3254ce, 0.45F, 0.85F, 0.9F),
@ -18,13 +18,12 @@ public enum Sizes implements Size {
FOAL (0xffbe53, 0.25f, 0.6F, 0.5F), FOAL (0xffbe53, 0.25f, 0.6F, 0.5F),
UNSET (0x000000, 1, 1, 1); UNSET (0x000000, 1, 1, 1);
private int triggerValue; private final int triggerValue;
private final float shadowSize;
private final float scale;
private final float camera;
private float shadowSize; SizePreset(int pixel, float shadowSz, float scaleF, float cameraF) {
private float scale;
private float camera;
Sizes(int pixel, float shadowSz, float scaleF, float cameraF) {
triggerValue = pixel; triggerValue = pixel;
shadowSize = shadowSz; shadowSize = shadowSz;
scale = scaleF; scale = scaleF;
@ -58,5 +57,4 @@ public enum Sizes implements Size {
public float eyeDistanceFactor() { public float eyeDistanceFactor() {
return eyeHeightFactor(); return eyeHeightFactor();
} }
} }

View file

@ -0,0 +1,66 @@
package com.minelittlepony.api.pony.meta;
import java.util.Arrays;
import java.util.List;
/**
* Interface for enums that can be parsed from an image trigger pixel value.
*/
public interface TValue<T> {
/**
* Gets the pixel colour matching this enum value.
*/
int colorCode();
/**
* Gets the pixel colour matching this enum value, adjusted to fill all three channels.
*/
default int getChannelAdjustedColorCode() {
return colorCode();
}
/**
* Gets a string representation of this value.
*/
String name();
default String getHexValue() {
return toHex(colorCode());
}
/**
* Returns a list of possible values this trigger pixel can accept.
*/
@SuppressWarnings("unchecked")
default List<TValue<T>> getOptions() {
if (this instanceof Enum) {
// cast is required because gradle's compiler is more strict
return Arrays.asList(getClass().getEnumConstants());
}
return List.of();
}
default boolean matches(TValue<?> o) {
return o != null && colorCode() == o.colorCode();
}
static String toHex(int color) {
String v = Integer.toHexString(color).toUpperCase();
while (v.length() < 6) {
v = "0" + v;
}
return "#" + v;
}
public record Numeric(int colorCode) implements TValue<Integer> {
@Override
public String name() {
return "[Numeric " + getHexValue() + "]";
}
@Override
public List<TValue<Integer>> getOptions() {
return List.of();
}
}
}

View file

@ -1,6 +1,6 @@
package com.minelittlepony.api.pony.meta; package com.minelittlepony.api.pony.meta;
public enum TailLength implements TriggerPixelType<TailLength> { public enum TailLength implements TValue<TailLength> {
STUB (0x425844), STUB (0x425844),
QUARTER (0xd19fe4), QUARTER (0xd19fe4),
HALF (0x534b76), HALF (0x534b76),

View file

@ -1,6 +1,6 @@
package com.minelittlepony.api.pony.meta; package com.minelittlepony.api.pony.meta;
public enum TailShape implements TriggerPixelType<TailShape> { public enum TailShape implements TValue<TailShape> {
STRAIGHT(0), STRAIGHT(0),
BUMPY (0xfc539f), BUMPY (0xfc539f),
SWIRLY (0x3eff22), SWIRLY (0x3eff22),

View file

@ -1,112 +1,91 @@
package com.minelittlepony.api.pony.meta; package com.minelittlepony.api.pony.meta;
import net.minecraft.client.texture.NativeImage; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minecraft.util.math.ColorHelper;
import org.joml.Vector2i;
import com.minelittlepony.common.util.Color; import com.minelittlepony.common.util.Color;
import java.util.Arrays; import java.util.*;
/** /**
* Individual trigger pixels for a pony skin. * Individual trigger pixels for a pony skin.
*
*/ */
@SuppressWarnings("unchecked") public interface TriggerPixel<T> {
public enum TriggerPixel { Vector2i MAX_COORDS = new Vector2i();
RACE(Race.HUMAN, Channel.ALL, 0, 0),
TAIL(TailLength.FULL, Channel.ALL, 1, 0),
GENDER(Gender.MARE, Channel.ALL, 2, 0),
SIZE(Sizes.NORMAL, Channel.ALL, 3, 0),
GLOW(null, Channel.RAW, 0, 1),
WEARABLES(Wearable.NONE, Channel.RAW, 1, 1),
TAIL_SHAPE(TailShape.STRAIGHT, Channel.ALL, 2, 1);
private final int x; TriggerPixel<Race> RACE = ofOptions(0, 0, Race.HUMAN, Race.values());
private final int y; TriggerPixel<TailLength> TAIL = ofOptions(1, 0, TailLength.FULL, TailLength.values());
TriggerPixel<Gender> GENDER = ofOptions(2, 0, Gender.MARE, Gender.values());
TriggerPixel<TailShape> TAIL_SHAPE = ofOptions(2, 1, TailShape.STRAIGHT, TailShape.values());
TriggerPixel<Size> SIZE = ofOptions(3, 0, SizePreset.NORMAL, SizePreset.values());
TriggerPixel<Integer> GLOW = ofColor(0, 1);
TriggerPixel<Flags<Wearable>> WEARABLES = ofFlags(1, 1, Wearable.EMPTY_FLAGS, Wearable.values());
private final Channel channel; static <T extends TValue<T>> TriggerPixel<T> ofOptions(int x, int y, T def, T[] options) {
MAX_COORDS.x = Math.max(MAX_COORDS.x, x);
MAX_COORDS.y = Math.max(MAX_COORDS.y, y);
Int2ObjectOpenHashMap<T> lookup = buildLookup(options);
return image -> {
int color = Color.abgrToArgb(image.getColor(x, y));
private final TriggerPixelType<?> def; if (ColorHelper.Argb.getAlpha(color) < 255) {
return (T)def;
private static final TriggerPixel[] VALUES = values(); }
private static final int MAX_READ_X = Arrays.stream(VALUES).mapToInt(i -> i.x).max().getAsInt(); return lookup.getOrDefault(color & 0x00FFFFFF, def);
private static final int MAX_READ_Y = Arrays.stream(VALUES).mapToInt(i -> i.y).max().getAsInt(); };
TriggerPixel(TriggerPixelType<?> def, Channel channel, int x, int y) {
this.def = def;
this.channel = channel;
this.x = x;
this.y = y;
} }
/** static TriggerPixel<Integer> ofColor(int x, int y) {
* Reads this trigger pixel's value and returns the raw colour. MAX_COORDS.x = Math.max(MAX_COORDS.x, x);
* MAX_COORDS.y = Math.max(MAX_COORDS.y, y);
* @param image Image to read return image -> Color.abgrToArgb(image.getColor(x, y));
*/
public int readColor(NativeImage image) {
return channel.readValue(x, y, image);
} }
/** static <T extends Enum<T> & TValue<T>> TriggerPixel<Flags<T>> ofFlags(int x, int y, Flags<T> def, T[] options) {
* Reads this trigger pixel's value and parses it to an Enum instance. MAX_COORDS.x = Math.max(MAX_COORDS.x, x);
* MAX_COORDS.y = Math.max(MAX_COORDS.y, y);
* @param image Image to read Int2ObjectOpenHashMap<T> lookup = buildLookup(options);
*/ var flagReader = new Object() {
public <T extends TriggerPixelType<T>> T readValue(NativeImage image) { boolean readFlag(int color, Set<T> values) {
int color = readColor(image); T value = lookup.get(color);
return value != null && values.add(value);
}
};
return image -> {
int color = Color.abgrToArgb(image.getColor(x, y));
if (ColorHelper.Argb.getAlpha(color) < 255) {
return def;
}
@SuppressWarnings("unchecked")
Set<T> values = EnumSet.noneOf((Class<T>)def.def().getClass());
if (flagReader.readFlag(ColorHelper.Argb.getRed(color), values)
|| flagReader.readFlag(ColorHelper.Argb.getGreen(color), values)
|| flagReader.readFlag(ColorHelper.Argb.getBlue(color), values)) {
return new Flags<>(def.def(), values, color & 0x00FFFFFF);
}
return def;
};
}
if (Channel.ALPHA.readValue(x, y, image) < 255) { static <T extends TValue<T>> Int2ObjectOpenHashMap<T> buildLookup(T[] options) {
return (T)def; Int2ObjectOpenHashMap<T> lookup = new Int2ObjectOpenHashMap<>();
for (int i = 0; i < options.length; i++) {
lookup.put(options[i].colorCode(), options[i]);
} }
return lookup;
return TriggerPixelType.getByTriggerPixel((T)def, color);
} }
public <T extends Enum<T> & TriggerPixelType<T>> TriggerPixelType.Multiple<T> readFlags(NativeImage image) {
boolean[] out = new boolean[def.getClass().getEnumConstants().length]; T read(Mat image);
readFlags(out, image);
return new TriggerPixelType.Multiple<>(readColor(image), (T)def, out); static boolean isTriggerPixelCoord(int x, int y) {
return x <= MAX_COORDS.x && y <= MAX_COORDS.y;
} }
public <T extends Enum<T> & TriggerPixelType<T>> void readFlags(boolean[] out, NativeImage image) { interface Mat {
readFlag(out, Channel.RED, image); int getColor(int x, int y);
readFlag(out, Channel.GREEN, image);
readFlag(out, Channel.BLUE, image);
} }
private <T extends Enum<T> & TriggerPixelType<T>> void readFlag(boolean[] out, Channel channel, NativeImage image) {
if (Channel.ALPHA.readValue(x, y, image) < 255) {
return;
}
T value = TriggerPixelType.getByTriggerPixel((T)def, channel.readValue(x, y, image));
out[value.ordinal()] |= value != def;
}
public static boolean isTriggerPixelCoord(int x, int y) {
return x <= MAX_READ_X && y <= MAX_READ_Y;
}
enum Channel {
RAW (0xFFFFFFFF, 0),
ALL (0x00FFFFFF, 0),
ALPHA(0x000000FF, 24),
RED (0x000000FF, 0),
GREEN(0x000000FF, 8),
BLUE (0x000000FF, 16);
private int mask;
private int offset;
Channel(int mask, int offset) {
this.mask = mask;
this.offset = offset;
}
public int readValue(int x, int y, NativeImage image) {
return (Color.abgrToArgb(image.getColor(x, y)) >> offset) & mask;
}
}
} }

View file

@ -1,96 +0,0 @@
package com.minelittlepony.api.pony.meta;
import java.util.Arrays;
import java.util.List;
/**
* Interface for enums that can be parsed from an image trigger pixel value.
*/
public interface TriggerPixelType<T extends TriggerPixelType<T>> {
/**
* Gets the pixel colour matching this enum value.
*/
int colorCode();
/**
* Gets the pixel colour matching this enum value, adjusted to fill all three channels.
*/
default int getChannelAdjustedColorCode() {
return colorCode();
}
/**
* Gets a string representation of this value.
*/
default String name() {
return "[Numeric " + getHexValue() + "]";
}
default String getHexValue() {
return toHex(colorCode());
}
/**
* Returns a list of possible values this trigger pixel can accept.
*/
@SuppressWarnings("unchecked")
default List<TriggerPixelType<T>> getOptions() {
if (this instanceof Enum) {
// cast is required because gradle's compiler is more strict
return Arrays.asList(getClass().getEnumConstants());
}
return List.of();
}
default boolean matches(Object o) {
return equals(o);
}
/**
* Gets the enum value corresponding to the given enum type and pixel value.
* If none are found, the first parameter is returned as the default.
*
* @param type Return type and default value.
* @param pixelValue The pixel colour to search for.
*/
@SuppressWarnings("unchecked")
static <T extends TriggerPixelType<T>> T getByTriggerPixel(T type, int pixelValue) {
return (T)type.getOptions().stream()
.filter(i -> i.colorCode() == pixelValue)
.findFirst()
.orElse(type);
}
static <T extends TriggerPixelType<T>> TriggerPixelType<T> of(int color) {
return () -> color;
}
static String toHex(int color) {
String v = Integer.toHexString(color).toUpperCase();
while (v.length() < 6) {
v = "0" + v;
}
return "#" + v;
}
public record Multiple<T extends Enum<T> & TriggerPixelType<T>> (
int colorCode,
T def,
boolean[] value
) implements TriggerPixelType<T> {
@Override
public String name() {
return "[Flags " + Arrays.toString(value) + "]";
}
@Override
public List<TriggerPixelType<T>> getOptions() {
return def.getOptions();
}
@Override
public boolean matches(Object o) {
return o.getClass() == def.getClass() && value()[((Enum<?>)o).ordinal()];
}
}
}

View file

@ -1,14 +1,13 @@
package com.minelittlepony.api.pony.meta; package com.minelittlepony.api.pony.meta;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.ColorHelper;
import com.minelittlepony.common.util.Color;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public enum Wearable implements TriggerPixelType<Wearable> { public enum Wearable implements TValue<Wearable> {
NONE (0x00, null), NONE (0x00, null),
CROWN (0x16, new Identifier("minelittlepony", "textures/models/crown.png")), CROWN (0x16, new Identifier("minelittlepony", "textures/models/crown.png")),
MUFFIN (0x32, new Identifier("minelittlepony", "textures/models/muffin.png")), MUFFIN (0x32, new Identifier("minelittlepony", "textures/models/muffin.png")),
@ -22,13 +21,11 @@ public enum Wearable implements TriggerPixelType<Wearable> {
private int triggerValue; private int triggerValue;
private final Identifier id; private final Identifier id;
private final Identifier texture; private final Identifier texture;
public static final List<Wearable> VALUES = Arrays.stream(values()).toList(); public static final Map<Identifier, Wearable> REGISTRY = Arrays.stream(values()).collect(Collectors.toMap(Wearable::getId, Function.identity()));
public static final Map<Identifier, Wearable> REGISTRY = VALUES.stream().collect(Collectors.toMap(Wearable::getId, Function.identity()));
public static final Flags<Wearable> EMPTY_FLAGS = Flags.of(Wearable.class); public static final Flags<Wearable> EMPTY_FLAGS = Flags.of(NONE);
Wearable(int pixel, Identifier texture) { Wearable(int pixel, Identifier texture) {
triggerValue = pixel; triggerValue = pixel;
@ -55,6 +52,6 @@ public enum Wearable implements TriggerPixelType<Wearable> {
@Override @Override
public int getChannelAdjustedColorCode() { public int getChannelAdjustedColorCode() {
return triggerValue == 0 ? 0 : Color.argbToHex(255, triggerValue, triggerValue, triggerValue); return triggerValue == 0 ? 0 : ColorHelper.Argb.getArgb(255, triggerValue, triggerValue, triggerValue);
} }
} }

View file

@ -1,38 +0,0 @@
package com.minelittlepony.client;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.client.model.armour.ArmourTextureResolver;
import com.minelittlepony.client.render.MobRenderers;
import com.minelittlepony.common.client.gui.VisibilityMode;
import com.minelittlepony.common.util.settings.Setting;
import java.nio.file.Path;
class ClientPonyConfig extends PonyConfig {
/**
* Visibility mode for the horse button.
*/
public final Setting<VisibilityMode> horseButton = value("horseButton", VisibilityMode.AUTO)
.addComment("Whether to show the mine little pony settings button on the main menu")
.addComment("AUTO (default) - only show when HDSkins is not installed")
.addComment("ON - always show")
.addComment("OFF - never show");
public ClientPonyConfig(Path path) {
super(path);
MobRenderers.REGISTRY.values().forEach(r -> value("entities", r.name, true));
disablePonifiedArmour.onChanged(t -> ArmourTextureResolver.INSTANCE.invalidate());
}
@Override
public void save() {
super.save();
PlayerEntity player = MinecraftClient.getInstance().player;
if (player != null) {
player.calculateDimensions();
}
}
}

View file

@ -1,8 +1,10 @@
package com.minelittlepony.client; package com.minelittlepony.client;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.events.Channel; import com.minelittlepony.api.events.Channel;
import com.minelittlepony.api.pony.PonyManager;
import com.minelittlepony.client.model.ModelType; import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.armour.ArmourTextureResolver;
import com.minelittlepony.client.render.MobRenderers;
import com.minelittlepony.client.render.PonyRenderDispatcher; import com.minelittlepony.client.render.PonyRenderDispatcher;
import com.minelittlepony.common.client.gui.VisibilityMode; import com.minelittlepony.common.client.gui.VisibilityMode;
import com.minelittlepony.common.client.gui.element.Button; import com.minelittlepony.common.client.gui.element.Button;
@ -12,6 +14,8 @@ import com.minelittlepony.common.event.ScreenInitCallback;
import com.minelittlepony.common.event.SkinFilterCallback; import com.minelittlepony.common.event.SkinFilterCallback;
import com.minelittlepony.common.util.GamePaths; import com.minelittlepony.common.util.GamePaths;
import java.nio.file.Path;
import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
@ -22,6 +26,7 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.TitleScreen;
import net.minecraft.client.option.KeyBinding; import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil; import net.minecraft.client.util.InputUtil;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.resource.ResourceType; import net.minecraft.resource.ResourceType;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@ -37,7 +42,6 @@ public class MineLittlePony implements ClientModInitializer {
public static final Logger logger = LogManager.getLogger("MineLittlePony"); public static final Logger logger = LogManager.getLogger("MineLittlePony");
private ClientPonyConfig config;
private PonyManagerImpl ponyManager; private PonyManagerImpl ponyManager;
private VariatedTextureSupplier variatedTextures; private VariatedTextureSupplier variatedTextures;
@ -64,7 +68,7 @@ public class MineLittlePony implements ClientModInitializer {
hasHdSkins = FabricLoader.getInstance().isModLoaded("hdskins"); hasHdSkins = FabricLoader.getInstance().isModLoaded("hdskins");
hasModMenu = FabricLoader.getInstance().isModLoaded("modmenu"); hasModMenu = FabricLoader.getInstance().isModLoaded("modmenu");
config = new ClientPonyConfig(GamePaths.getConfigDirectory().resolve("minelp.json")); PonyConfig config = new ClientPonyConfig(GamePaths.getConfigDirectory().resolve("minelp.json"));
ponyManager = new PonyManagerImpl(config); ponyManager = new PonyManagerImpl(config);
variatedTextures = new VariatedTextureSupplier(); variatedTextures = new VariatedTextureSupplier();
@ -108,7 +112,7 @@ public class MineLittlePony implements ClientModInitializer {
private void onScreenInit(Screen screen, ScreenInitCallback.ButtonList buttons) { private void onScreenInit(Screen screen, ScreenInitCallback.ButtonList buttons) {
if (screen instanceof TitleScreen) { if (screen instanceof TitleScreen) {
VisibilityMode mode = config.horseButton.get(); VisibilityMode mode = ClientPonyConfig.getInstance().horseButton.get();
boolean show = mode == VisibilityMode.ON || (mode == VisibilityMode.AUTO boolean show = mode == VisibilityMode.ON || (mode == VisibilityMode.AUTO
&& !(hasHdSkins || hasModMenu && !(hasHdSkins || hasModMenu
)); ));
@ -129,7 +133,7 @@ public class MineLittlePony implements ClientModInitializer {
} }
} }
public PonyManager getManager() { public PonyManagerImpl getManager() {
return ponyManager; return ponyManager;
} }
@ -143,5 +147,22 @@ public class MineLittlePony implements ClientModInitializer {
public PonyRenderDispatcher getRenderDispatcher() { public PonyRenderDispatcher getRenderDispatcher() {
return renderDispatcher; return renderDispatcher;
} }
private static final class ClientPonyConfig extends PonyConfig {
public ClientPonyConfig(Path path) {
super(path);
MobRenderers.REGISTRY.values().forEach(r -> value("entities", r.name, true));
disablePonifiedArmour.onChanged(t -> ArmourTextureResolver.INSTANCE.invalidate());
}
@Override
public void save() {
super.save();
PlayerEntity player = MinecraftClient.getInstance().player;
if (player != null) {
player.calculateDimensions();
}
}
}
} }

View file

@ -6,7 +6,6 @@ import net.minecraft.util.Identifier;
import com.google.gson.*; import com.google.gson.*;
import com.minelittlepony.api.pony.PonyData; import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.client.util.render.NativeUtil; import com.minelittlepony.client.util.render.NativeUtil;
import java.io.IOException; import java.io.IOException;
@ -53,16 +52,7 @@ class PonyDataLoader {
}).map(PonyDataLoader::loaded).orElseGet(() -> { }).map(PonyDataLoader::loaded).orElseGet(() -> {
return load(callback -> { return load(callback -> {
NativeUtil.parseImage(identifier, image -> { NativeUtil.parseImage(identifier, image -> {
callback.accept(new PonyData( callback.accept(new PonyData(image, noSkin));
TriggerPixel.RACE.readValue(image),
TriggerPixel.TAIL.readValue(image),
TriggerPixel.TAIL_SHAPE.readValue(image),
TriggerPixel.GENDER.readValue(image),
TriggerPixel.SIZE.readValue(image),
TriggerPixel.GLOW.readColor(image),
TriggerPixel.WEARABLES.readFlags(image),
noSkin
));
}, e -> { }, e -> {
MineLittlePony.logger.fatal("Unable to read {} metadata", identifier, e); MineLittlePony.logger.fatal("Unable to read {} metadata", identifier, e);
callback.accept(PonyData.NULL); callback.accept(PonyData.NULL);

View file

@ -9,10 +9,10 @@ import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener; import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.util.DefaultSkinHelper; import net.minecraft.client.util.DefaultSkinHelper;
import net.minecraft.resource.ResourceManager; import net.minecraft.resource.ResourceManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -22,25 +22,18 @@ import java.util.UUID;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceReloadListener {
* The PonyManager is responsible for reading and recoding all the pony data associated with an entity of skin.
*/
class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceReloadListener {
private static final Identifier ID = new Identifier("minelittlepony", "background_ponies"); private static final Identifier ID = new Identifier("minelittlepony", "background_ponies");
private final PonyConfig config; private final PonyConfig config;
private final LoadingCache<Identifier, Pony> defaultedPoniesCache = CacheBuilder.newBuilder() private final LoadingCache<Identifier, Pony> defaultedPoniesCache = CacheBuilder.newBuilder()
.expireAfterAccess(30, TimeUnit.SECONDS) .expireAfterAccess(30, TimeUnit.SECONDS)
.build(CacheLoader.from(resource -> { .build(CacheLoader.from(resource -> new Pony(resource, PonyDataLoader.parse(resource, true))));
return new Pony(resource, PonyDataLoader.parse(resource, true));
}));
private final LoadingCache<Identifier, Pony> poniesCache = CacheBuilder.newBuilder() private final LoadingCache<Identifier, Pony> poniesCache = CacheBuilder.newBuilder()
.expireAfterAccess(30, TimeUnit.SECONDS) .expireAfterAccess(30, TimeUnit.SECONDS)
.build(CacheLoader.from(resource -> { .build(CacheLoader.from(resource -> new Pony(resource, PonyDataLoader.parse(resource, false))));
return new Pony(resource, PonyDataLoader.parse(resource, false));
}));
public PonyManagerImpl(PonyConfig config) { public PonyManagerImpl(PonyConfig config) {
this.config = config; this.config = config;
@ -56,78 +49,62 @@ class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceReloadLis
} }
@Override @Override
public Pony getPony(Identifier resource) { public Pony getPony(PlayerEntity player) {
return loadPony(resource, false); clearCache();
return getPony(getSkin(player), player instanceof ForcedPony ? null : player.getGameProfile() == null ? player.getUuid() : player.getGameProfile().getId());
} }
@Override @Override
public Optional<Pony> getPony(@Nullable Entity entity) { public Optional<Pony> getPony(LivingEntity entity) {
if (entity instanceof PlayerEntity player) { if (entity instanceof PlayerEntity player) {
return Optional.of(getPony(player)); return Optional.of(getPony(player));
} }
Identifier skin = getSkin(entity);
if (entity instanceof LivingEntity living) { return skin == null ? Optional.empty() : Optional.of(getPony(skin, null));
return Optional.ofNullable(MineLittlePony.getInstance().getRenderDispatcher().getPonyRenderer(living)).map(d -> d.getEntityPony(living));
}
return Optional.empty();
} }
@Override @Override
public Pony getPony(PlayerEntity player) { public Pony getPony(@Nullable Identifier resource, @Nullable UUID uuid) {
Identifier skin = getSkin(player); if (resource == null) {
UUID uuid = player.getGameProfile() == null ? player.getUuid() : player.getGameProfile().getId(); return uuid == null ? loadPony(DefaultSkinHelper.getTexture(), true) : getBackgroundPony(uuid);
if (skin != null) {
if (player instanceof PonyManager.ForcedPony) {
return getPony(skin);
}
return getPony(skin, uuid);
} }
if (config.ponyLevel.get() == PonyLevel.PONIES) { Pony pony = loadPony(resource, false);
if (uuid != null && PonyConfig.getInstance().ponyLevel.get() == PonyLevel.PONIES && pony.metadata().race().isHuman()) {
return getBackgroundPony(uuid); return getBackgroundPony(uuid);
} }
return loadPony(DefaultSkinHelper.getTexture(uuid).texture(), true);
}
@Override
public Pony getPony(Identifier resource, UUID uuid) {
Pony pony = getPony(resource);
if (config.ponyLevel.get() == PonyLevel.PONIES && pony.metadata().race().isHuman()) {
return getBackgroundPony(uuid);
}
return pony; return pony;
} }
@Override @Override
public Pony getBackgroundPony(UUID uuid) { public Pony getBackgroundPony(@Nullable UUID uuid) {
return loadPony(MineLittlePony.getInstance().getVariatedTextures().get(VariatedTextureSupplier.BACKGROUND_PONIES_POOL, uuid).orElse(DefaultSkinHelper.getTexture(uuid).texture()), true); if (config.ponyLevel.get() == PonyLevel.PONIES) {
return loadPony(MineLittlePony.getInstance().getVariatedTextures().get(VariatedTextureSupplier.BACKGROUND_PONIES_POOL, uuid).orElse(DefaultSkinHelper.getTexture(uuid).texture()), true);
}
return loadPony(DefaultSkinHelper.getTexture(uuid).texture(), true);
} }
@Nullable @Nullable
private Identifier getSkin(PlayerEntity player) { private Identifier getSkin(LivingEntity entity) {
if (player.getGameProfile() == null) { if (entity instanceof PlayerEntity player) {
return null; if (player.getGameProfile() != null && player instanceof AbstractClientPlayerEntity clientPlayer) {
} return clientPlayer.method_52814().texture();
if (player instanceof AbstractClientPlayerEntity) { }
return ((AbstractClientPlayerEntity)player).method_52814().texture(); } else {
if (MineLittlePony.getInstance().getRenderDispatcher().getPonyRenderer(entity) != null) {
return MinecraftClient.getInstance().getEntityRenderDispatcher().getRenderer(entity).getTexture(entity);
}
} }
return null; return null;
} }
@Override
public void removePony(Identifier resource) { public void removePony(Identifier resource) {
poniesCache.invalidate(resource); poniesCache.invalidate(resource);
defaultedPoniesCache.invalidate(resource); defaultedPoniesCache.invalidate(resource);
} }
@Override
public void clearCache() { public void clearCache() {
MineLittlePony.logger.info("Flushed {} cached ponies.", poniesCache.size()); MineLittlePony.logger.info("Flushed {} cached ponies.", poniesCache.size());
poniesCache.invalidateAll(); poniesCache.invalidateAll();

View file

@ -35,7 +35,7 @@ public class PonySettingsscreen extends GameGui {
public static final Text SCALE_SHOW = Text.translatable("minelp.debug.scale.sa"); public static final Text SCALE_SHOW = Text.translatable("minelp.debug.scale.sa");
public static final Text SCALE_MIN = Text.translatable("minelp.debug.scale.min"); public static final Text SCALE_MIN = Text.translatable("minelp.debug.scale.min");
private ClientPonyConfig config; private final PonyConfig config = PonyConfig.getInstance();
private final ScrollContainer content = new ScrollContainer(); private final ScrollContainer content = new ScrollContainer();
@ -43,9 +43,6 @@ public class PonySettingsscreen extends GameGui {
public PonySettingsscreen(@Nullable Screen parent) { public PonySettingsscreen(@Nullable Screen parent) {
super(Text.literal(OPTIONS_PREFIX + "title"), parent); super(Text.literal(OPTIONS_PREFIX + "title"), parent);
config = (ClientPonyConfig)PonyConfig.getInstance();
content.margin.top = 30; content.margin.top = 30;
content.margin.bottom = 30; content.margin.bottom = 30;
content.getContentPadding().top = 10; content.getContentPadding().top = 10;

View file

@ -1,6 +1,5 @@
package com.minelittlepony.client.compat.hdskins; package com.minelittlepony.client.compat.hdskins;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.PonySettingsscreen; import com.minelittlepony.client.PonySettingsscreen;
import com.minelittlepony.client.MineLittlePony; import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.common.client.gui.dimension.Bounds; import com.minelittlepony.common.client.gui.dimension.Bounds;
@ -29,13 +28,13 @@ class GuiSkinsMineLP extends GuiSkins {
chooser.addSkinChangedEventListener(type -> { chooser.addSkinChangedEventListener(type -> {
MineLittlePony.logger.debug("Invalidating old local skin, checking updated local skin"); MineLittlePony.logger.debug("Invalidating old local skin, checking updated local skin");
if (type == SkinType.SKIN) { if (type == SkinType.SKIN) {
Pony.getManager().removePony(previewer.getLocal().getSkins().get(SkinType.SKIN).getId()); MineLittlePony.getInstance().getManager().removePony(previewer.getLocal().getSkins().get(SkinType.SKIN).getId());
} }
}); });
uploader.addSkinLoadedEventListener((type, location, profileTexture) -> { uploader.addSkinLoadedEventListener((type, location, profileTexture) -> {
MineLittlePony.logger.debug("Invalidating old remote skin, checking updated remote skin"); MineLittlePony.logger.debug("Invalidating old remote skin, checking updated remote skin");
if (type == SkinType.SKIN) { if (type == SkinType.SKIN) {
Pony.getManager().removePony(location); MineLittlePony.getInstance().getManager().removePony(location);
} }
}); });
} }

View file

@ -4,7 +4,7 @@ import net.minecraft.client.gui.DrawContext;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import com.minelittlepony.api.pony.*; import com.minelittlepony.api.pony.*;
import com.minelittlepony.api.pony.meta.TriggerPixelType; import com.minelittlepony.api.pony.meta.TValue;
import com.minelittlepony.common.client.gui.ITextContext; import com.minelittlepony.common.client.gui.ITextContext;
import com.minelittlepony.common.client.gui.dimension.Bounds; import com.minelittlepony.common.client.gui.dimension.Bounds;
import com.minelittlepony.hdskins.client.gui.Carousel; import com.minelittlepony.hdskins.client.gui.Carousel;
@ -37,7 +37,7 @@ class LegendOverlayWidget implements Carousel.Element, ITextContext {
}); });
} }
private void drawLegendBlock(DrawContext context, int index, int x, int y, int mouseX, int mouseY, String key, TriggerPixelType<?> value) { private void drawLegendBlock(DrawContext context, int index, int x, int y, int mouseX, int mouseY, String key, TValue<?> value) {
context.fill(0, 0, LEGEND_BLOCK_BOUNDS.width, LEGEND_BLOCK_BOUNDS.height, 0xFF003333); context.fill(0, 0, LEGEND_BLOCK_BOUNDS.width, LEGEND_BLOCK_BOUNDS.height, 0xFF003333);
context.fill(1, 1, LEGEND_BLOCK_BOUNDS.width - 1, LEGEND_BLOCK_BOUNDS.height - 1, value.colorCode() | 0xFF000000); context.fill(1, 1, LEGEND_BLOCK_BOUNDS.width - 1, LEGEND_BLOCK_BOUNDS.height - 1, value.colorCode() | 0xFF000000);

View file

@ -43,7 +43,7 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
SkinsProxy.instance = this; SkinsProxy.instance = this;
seaponySkinType = SkinType.register(AquaticPlayerPonyRenderer.SKIN_TYPE_ID, Items.COD_BUCKET.getDefaultStack()); seaponySkinType = SkinType.register(AquaticPlayerPonyRenderer.SKIN_TYPE_ID, Items.COD_BUCKET.getDefaultStack());
Wearable.VALUES.forEach(wearable -> { Wearable.REGISTRY.values().forEach(wearable -> {
if (wearable != Wearable.NONE) { if (wearable != Wearable.NONE) {
wearableTypes.put(SkinType.register(wearable.getId(), Items.BUNDLE.getDefaultStack()), wearable); wearableTypes.put(SkinType.register(wearable.getId(), Items.BUNDLE.getDefaultStack()), wearable);
} }
@ -100,7 +100,7 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
PlayerSkin main = dummy.getTextures().get(SkinType.SKIN); PlayerSkin main = dummy.getTextures().get(SkinType.SKIN);
Wearable wearable = Wearable.REGISTRY.getOrDefault(type.getId(), Wearable.NONE); Wearable wearable = Wearable.REGISTRY.getOrDefault(type.getId(), Wearable.NONE);
PonyData metadata = Pony.getManager().getPony(main.getId()).metadata(); PonyData metadata = Pony.getManager().getPony(main.getId()).metadata();
if (wearable != Wearable.NONE && metadata.isWearing(wearable)) { if (wearable != Wearable.NONE && metadata.gear().matches(wearable)) {
if (wearable.isSaddlebags() && metadata.race().supportsLegacySaddlebags()) { if (wearable.isSaddlebags() && metadata.race().supportsLegacySaddlebags()) {
return Optional.of(main.getId()); return Optional.of(main.getId());

View file

@ -2,7 +2,7 @@ package com.minelittlepony.client.model;
import com.minelittlepony.api.model.*; import com.minelittlepony.api.model.*;
import com.minelittlepony.api.events.PonyModelPrepareCallback; import com.minelittlepony.api.events.PonyModelPrepareCallback;
import com.minelittlepony.api.pony.meta.Sizes; import com.minelittlepony.api.pony.meta.SizePreset;
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.util.MathUtil; import com.minelittlepony.util.MathUtil;
@ -450,10 +450,10 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
arm.pivotX -= 6 * sigma; arm.pivotX -= 6 * sigma;
arm.pivotZ -= 2; arm.pivotZ -= 2;
} }
if (getSize() == Sizes.TALL) { if (getSize() == SizePreset.TALL) {
arm.pivotY += 1; arm.pivotY += 1;
} }
if (getSize() == Sizes.FOAL) { if (getSize() == SizePreset.FOAL) {
arm.pivotY -= 2; arm.pivotY -= 2;
} }
@ -558,7 +558,7 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
@Override @Override
public float getRiderYOffset() { public float getRiderYOffset() {
switch ((Sizes)getSize()) { switch ((SizePreset)getSize()) {
case NORMAL: return 0.4F; case NORMAL: return 0.4F;
case FOAL: case FOAL:
case TALL: case TALL:

View file

@ -13,7 +13,7 @@ import com.minelittlepony.api.model.*;
import com.minelittlepony.api.pony.Pony; import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyData; import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.Size; import com.minelittlepony.api.pony.meta.Size;
import com.minelittlepony.api.pony.meta.Sizes; import com.minelittlepony.api.pony.meta.SizePreset;
import com.minelittlepony.mson.api.model.biped.MsonPlayer; import com.minelittlepony.mson.api.model.biped.MsonPlayer;
/** /**
@ -79,7 +79,7 @@ public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer
@Override @Override
public Size getSize() { public Size getSize() {
return child ? Sizes.FOAL : PonyModel.super.getSize(); return child ? SizePreset.FOAL : PonyModel.super.getSize();
} }
@Override @Override

View file

@ -3,7 +3,7 @@ package com.minelittlepony.client.model.entity.race;
import com.minelittlepony.api.config.PonyConfig; import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.model.*; import com.minelittlepony.api.model.*;
import com.minelittlepony.api.pony.meta.Size; import com.minelittlepony.api.pony.meta.Size;
import com.minelittlepony.api.pony.meta.Sizes; import com.minelittlepony.api.pony.meta.SizePreset;
import com.minelittlepony.client.model.part.UnicornHorn; import com.minelittlepony.client.model.part.UnicornHorn;
import com.minelittlepony.client.util.render.RenderList; import com.minelittlepony.client.util.render.RenderList;
import com.minelittlepony.mson.api.ModelView; import com.minelittlepony.mson.api.ModelView;
@ -101,9 +101,9 @@ public class UnicornModel<T extends LivingEntity> extends EarthPonyModel<T> impl
float x = 0.3F; float x = 0.3F;
float z = -0.4F; float z = -0.4F;
if (size == Sizes.TALL || size == Sizes.YEARLING) { if (size == SizePreset.TALL || size == SizePreset.YEARLING) {
z += 0.05F; z += 0.05F;
} else if (size == Sizes.FOAL) { } else if (size == SizePreset.FOAL) {
x -= 0.1F; x -= 0.1F;
z -= 0.1F; z -= 0.1F;
} }

View file

@ -59,7 +59,7 @@ public class SaddleBags extends WearableGear {
strap.visible = wearable == Wearable.SADDLE_BAGS_BOTH; strap.visible = wearable == Wearable.SADDLE_BAGS_BOTH;
dropAmount = hangLow ? 0.15F : 0; dropAmount = hangLow ? 0.15F : 0;
dropAmount = model.getAttributes().metadata.getInterpolator(interpolatorId).interpolate("dropAmount", dropAmount, 3); dropAmount = model.getAttributes().getMainInterpolator().interpolate("dropAmount", dropAmount, 3);
} }
@Override @Override

View file

@ -26,7 +26,7 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
private ModelWrapper<T, M> playerModel; private ModelWrapper<T, M> playerModel;
private final IPonyRenderContext<T, M> renderer; private final PonyRenderContext<T, M> renderer;
private final FrustrumCheck<T> frustrum = new FrustrumCheck<>(this); private final FrustrumCheck<T> frustrum = new FrustrumCheck<>(this);
@ -34,11 +34,11 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
RenderSystem.disableBlend(); RenderSystem.disableBlend();
} }
public EquineRenderManager(IPonyRenderContext<T, M> renderer) { public EquineRenderManager(PonyRenderContext<T, M> renderer) {
this.renderer = renderer; this.renderer = renderer;
} }
public IPonyRenderContext<T, M> getContext() { public PonyRenderContext<T, M> getContext() {
return renderer; return renderer;
} }
@ -95,7 +95,7 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
if (entity.hasVehicle() && entity.getVehicle() instanceof LivingEntity) { if (entity.hasVehicle() && entity.getVehicle() instanceof LivingEntity) {
LivingEntity ridingEntity = (LivingEntity) entity.getVehicle(); LivingEntity ridingEntity = (LivingEntity) entity.getVehicle();
IPonyRenderContext<LivingEntity, ?> renderer = MineLittlePony.getInstance().getRenderDispatcher().getPonyRenderer(ridingEntity); PonyRenderContext<LivingEntity, ?> renderer = MineLittlePony.getInstance().getRenderDispatcher().getPonyRenderer(ridingEntity);
if (renderer != null) { if (renderer != null) {
// negate vanilla translations so the rider begins at the ridees feet. // negate vanilla translations so the rider begins at the ridees feet.
@ -141,6 +141,10 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
return getModel().getSize().scaleFactor(); return getModel().getSize().scaleFactor();
} }
public float getShadowSize() {
return getModel().getSize().shadowSize();
}
public double getNamePlateYOffset(T entity) { public double getNamePlateYOffset(T entity) {
// We start by negating the height calculation done by mahjong. // We start by negating the height calculation done by mahjong.

View file

@ -10,7 +10,7 @@ import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
public interface IPonyRenderContext<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends Gear.Context<T, M> { public interface PonyRenderContext<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends Gear.Context<T, M> {
Pony getEntityPony(T entity); Pony getEntityPony(T entity);

View file

@ -6,8 +6,8 @@ import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.pony.Pony; import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyPosture; import com.minelittlepony.api.pony.PonyPosture;
import com.minelittlepony.client.mixin.MixinEntityRenderers; import com.minelittlepony.client.mixin.MixinEntityRenderers;
import com.minelittlepony.client.render.entity.PlayerPonyRenderer;
import com.minelittlepony.client.render.entity.AquaticPlayerPonyRenderer; import com.minelittlepony.client.render.entity.AquaticPlayerPonyRenderer;
import com.minelittlepony.client.render.entity.PlayerPonyRenderer;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -83,15 +83,15 @@ public class PonyRenderDispatcher {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Nullable @Nullable
public <T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> IPonyRenderContext<T, M> getPonyRenderer(@Nullable T entity) { public <T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> PonyRenderContext<T, M> getPonyRenderer(@Nullable T entity) {
if (entity == null) { if (entity == null) {
return null; return null;
} }
EntityRenderer<?> renderer = MinecraftClient.getInstance().getEntityRenderDispatcher().getRenderer(entity); EntityRenderer<?> renderer = MinecraftClient.getInstance().getEntityRenderDispatcher().getRenderer(entity);
if (renderer instanceof IPonyRenderContext) { if (renderer instanceof PonyRenderContext) {
return (IPonyRenderContext<T, M>) renderer; return (PonyRenderContext<T, M>) renderer;
} }
return null; return null;

View file

@ -5,7 +5,7 @@ import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.meta.Wearable; import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.model.*; import com.minelittlepony.client.model.*;
import com.minelittlepony.client.render.DebugBoundingBoxRenderer; import com.minelittlepony.client.render.DebugBoundingBoxRenderer;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
import com.minelittlepony.client.render.EquineRenderManager; import com.minelittlepony.client.render.EquineRenderManager;
import com.minelittlepony.client.render.entity.feature.*; import com.minelittlepony.client.render.entity.feature.*;
import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier; import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier;
@ -27,7 +27,7 @@ import net.minecraft.entity.mob.MobEntity;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
public abstract class AbstractPonyRenderer<T extends MobEntity, M extends EntityModel<T> & PonyModel<T> & ModelWithArms> extends MobEntityRenderer<T, M> implements IPonyRenderContext<T, M> { public abstract class AbstractPonyRenderer<T extends MobEntity, M extends EntityModel<T> & PonyModel<T> & ModelWithArms> extends MobEntityRenderer<T, M> implements PonyRenderContext<T, M> {
protected final EquineRenderManager<T, M> manager = new EquineRenderManager<>(this); protected final EquineRenderManager<T, M> manager = new EquineRenderManager<>(this);
@ -91,7 +91,7 @@ public abstract class AbstractPonyRenderer<T extends MobEntity, M extends Entity
@Override @Override
public void scale(T entity, MatrixStack stack, float tickDelta) { public void scale(T entity, MatrixStack stack, float tickDelta) {
shadowRadius = manager.getModel().getSize().shadowSize(); shadowRadius = manager.getShadowSize();
if (entity.isBaby()) { if (entity.isBaby()) {
shadowRadius *= 3; // undo vanilla shadow scaling shadowRadius *= 3; // undo vanilla shadow scaling

View file

@ -69,12 +69,11 @@ public class AquaticPlayerPonyRenderer extends PlayerPonyRenderer {
} }
private void updateSeaponyState(AbstractClientPlayerEntity player) { private void updateSeaponyState(AbstractClientPlayerEntity player) {
Pony pony = getEntityPony(player);
wet = PonyPosture.isSeaponyModifier(player); wet = PonyPosture.isSeaponyModifier(player);
if (!(player instanceof PreviewModel)) { if (!(player instanceof PreviewModel)) {
float state = wet ? 100 : 0; float state = wet ? 100 : 0;
float interpolated = pony.metadata().getInterpolator(player.getUuid()).interpolate("seapony_state", state, 5); float interpolated = getInternalRenderer().getModel().getAttributes().getMainInterpolator().interpolate("seapony_state", state, 5);
if (!MathUtil.compareFloats(interpolated, state)) { if (!MathUtil.compareFloats(interpolated, state)) {
double x = player.getEntityWorld().getRandom().nextTriangular(player.getX(), 1); double x = player.getEntityWorld().getRandom().nextTriangular(player.getX(), 1);

View file

@ -8,7 +8,7 @@ import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.SkinsProxy; import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.client.model.*; import com.minelittlepony.client.model.*;
import com.minelittlepony.client.render.DebugBoundingBoxRenderer; import com.minelittlepony.client.render.DebugBoundingBoxRenderer;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
import com.minelittlepony.client.render.entity.feature.*; import com.minelittlepony.client.render.entity.feature.*;
import com.minelittlepony.client.util.render.RenderLayerUtil; import com.minelittlepony.client.util.render.RenderLayerUtil;
@ -29,7 +29,7 @@ import net.minecraft.text.Text;
import net.minecraft.util.*; import net.minecraft.util.*;
import net.minecraft.util.math.*; import net.minecraft.util.math.*;
public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRenderContext<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> { public class PlayerPonyRenderer extends PlayerEntityRenderer implements PonyRenderContext<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> {
protected final EquineRenderManager<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> manager = new EquineRenderManager<>(this); protected final EquineRenderManager<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> manager = new EquineRenderManager<>(this);
@ -81,7 +81,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
Pony pony = getEntityPony(entity); Pony pony = getEntityPony(entity);
model = manager.setModel(modelsCache.apply(getPlayerRace(entity, pony))).body(); model = manager.setModel(modelsCache.apply(getPlayerRace(entity, pony))).body();
// EntityModelFeatures: We have to force it to use our models otherwise EMF overrides it and breaks pony rendering // EntityModelFeatures: We have to force it to use our models otherwise EMF overrides it and breaks pony rendering
shadowRadius = manager.getModel().getSize().shadowSize(); shadowRadius = manager.getShadowSize();
super.render(entity, entityYaw, tickDelta, stack, renderContext, lightUv); super.render(entity, entityYaw, tickDelta, stack, renderContext, lightUv);
DebugBoundingBoxRenderer.render(pony, this, entity, stack, renderContext, tickDelta); DebugBoundingBoxRenderer.render(pony, this, entity, stack, renderContext, tickDelta);
@ -89,7 +89,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
// (shadows are drawn after us) // (shadows are drawn after us)
if (!entity.hasVehicle() && !entity.isSleeping()) { if (!entity.hasVehicle() && !entity.isSleeping()) {
float yaw = MathHelper.lerpAngleDegrees(tickDelta, entity.prevBodyYaw, entity.bodyYaw); float yaw = MathHelper.lerpAngleDegrees(tickDelta, entity.prevBodyYaw, entity.bodyYaw);
float l = entity.getWidth() / 2 * pony.size().scaleFactor(); float l = entity.getWidth() / 2 * manager.getScaleFactor();
stack.multiply(RotationAxis.NEGATIVE_Y.rotationDegrees(yaw)); stack.multiply(RotationAxis.NEGATIVE_Y.rotationDegrees(yaw));
stack.translate(0, 0, -l); stack.translate(0, 0, -l);

View file

@ -2,7 +2,7 @@ package com.minelittlepony.client.render.entity.feature;
import com.minelittlepony.api.model.ModelWrapper; import com.minelittlepony.api.model.ModelWrapper;
import com.minelittlepony.api.model.PonyModel; import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.feature.FeatureRenderer; import net.minecraft.client.render.entity.feature.FeatureRenderer;
@ -13,10 +13,10 @@ import net.minecraft.entity.LivingEntity;
public abstract class AbstractPonyFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends FeatureRenderer<T, M> { public abstract class AbstractPonyFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends FeatureRenderer<T, M> {
private final IPonyRenderContext<T, M> context; private final PonyRenderContext<T, M> context;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public AbstractPonyFeature(IPonyRenderContext<T, M> context) { public AbstractPonyFeature(PonyRenderContext<T, M> context) {
super((FeatureRendererContext<T, M>)context); super((FeatureRendererContext<T, M>)context);
this.context = context; this.context = context;
} }
@ -39,7 +39,7 @@ public abstract class AbstractPonyFeature<T extends LivingEntity, M extends Enti
public abstract void render(MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, T entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch); public abstract void render(MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, T entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected <C extends IPonyRenderContext<T, M> & FeatureRendererContext<T, M>> C getContext() { protected <C extends PonyRenderContext<T, M> & FeatureRendererContext<T, M>> C getContext() {
return (C)context; return (C)context;
} }

View file

@ -3,7 +3,7 @@ package com.minelittlepony.client.render.entity.feature;
import com.minelittlepony.api.model.ModelWrapper; import com.minelittlepony.api.model.ModelWrapper;
import com.minelittlepony.api.model.PonyModel; import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.client.model.armour.*; import com.minelittlepony.client.model.armour.*;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
import com.minelittlepony.common.util.Color; import com.minelittlepony.common.util.Color;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
@ -22,7 +22,7 @@ import net.minecraft.util.Identifier;
public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends AbstractPonyFeature<T, M> { public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends AbstractPonyFeature<T, M> {
public ArmourFeature(IPonyRenderContext<T, M> context, BakedModelManager bakery) { public ArmourFeature(PonyRenderContext<T, M> context, BakedModelManager bakery) {
super(context); super(context);
} }

View file

@ -2,7 +2,7 @@ package com.minelittlepony.client.render.entity.feature;
import com.minelittlepony.api.model.BodyPart; import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.client.model.ClientPonyModel; import com.minelittlepony.client.model.ClientPonyModel;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.OverlayTexture;
@ -17,7 +17,7 @@ import net.minecraft.entity.EquipmentSlot;
public class CapeFeature<M extends ClientPonyModel<AbstractClientPlayerEntity>> extends AbstractPonyFeature<AbstractClientPlayerEntity, M> { public class CapeFeature<M extends ClientPonyModel<AbstractClientPlayerEntity>> extends AbstractPonyFeature<AbstractClientPlayerEntity, M> {
public CapeFeature(IPonyRenderContext<AbstractClientPlayerEntity, M> context) { public CapeFeature(PonyRenderContext<AbstractClientPlayerEntity, M> context) {
super(context); super(context);
} }

View file

@ -11,13 +11,13 @@ import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.api.model.BodyPart; import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.PonyModel; import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.client.model.DJPon3EarsModel; import com.minelittlepony.client.model.DJPon3EarsModel;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
public class DJPon3Feature<T extends AbstractClientPlayerEntity, M extends EntityModel<T> & PonyModel<T>> extends AbstractPonyFeature<T, M> { public class DJPon3Feature<T extends AbstractClientPlayerEntity, M extends EntityModel<T> & PonyModel<T>> extends AbstractPonyFeature<T, M> {
private final DJPon3EarsModel deadMau5 = ModelType.DJ_PON_3.createModel(); private final DJPon3EarsModel deadMau5 = ModelType.DJ_PON_3.createModel();
public DJPon3Feature(IPonyRenderContext<T, M> context) { public DJPon3Feature(PonyRenderContext<T, M> context) {
super(context); super(context);
} }

View file

@ -5,7 +5,7 @@ import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.pony.PonyPosture; import com.minelittlepony.api.pony.PonyPosture;
import com.minelittlepony.client.model.ModelType; import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.PonyElytra; import com.minelittlepony.client.model.PonyElytra;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.OverlayTexture;
@ -29,7 +29,7 @@ public class ElytraFeature<T extends LivingEntity, M extends EntityModel<T> & Po
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private final PonyElytra<T> modelElytra = (PonyElytra<T>)ModelType.ELYTRA.createModel(); private final PonyElytra<T> modelElytra = (PonyElytra<T>)ModelType.ELYTRA.createModel();
public ElytraFeature(IPonyRenderContext<T, M> rp) { public ElytraFeature(PonyRenderContext<T, M> rp) {
super(rp); super(rp);
} }

View file

@ -15,7 +15,7 @@ import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.gear.Gear; import com.minelittlepony.api.model.gear.Gear;
import com.minelittlepony.api.pony.meta.Wearable; import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.model.ModelType; import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -42,7 +42,7 @@ public class GearFeature<T extends LivingEntity, M extends EntityModel<T> & Pony
return randomizedOrder; return randomizedOrder;
})); }));
public GearFeature(IPonyRenderContext<T, M> renderer) { public GearFeature(PonyRenderContext<T, M> renderer) {
super(renderer); super(renderer);
} }

View file

@ -8,13 +8,13 @@ import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import com.minelittlepony.api.model.PonyModel; import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
public class GlowingEyesFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends EyesFeatureRenderer<T, M> { public class GlowingEyesFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends EyesFeatureRenderer<T, M> {
private final RenderLayer layer; private final RenderLayer layer;
public <V extends FeatureRendererContext<T, M> & IPonyRenderContext<T, M> & IGlowingRenderer> GlowingEyesFeature(V renderer) { public <V extends FeatureRendererContext<T, M> & PonyRenderContext<T, M> & IGlowingRenderer> GlowingEyesFeature(V renderer) {
super(renderer); super(renderer);
layer = RenderLayer.getEyes(renderer.getEyeTexture()); layer = RenderLayer.getEyes(renderer.getEyeTexture());
} }

View file

@ -2,7 +2,7 @@ package com.minelittlepony.client.render.entity.feature;
import com.minelittlepony.api.model.BodyPart; import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.PonyModel; import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.feature.FeatureRendererContext; import net.minecraft.client.render.entity.feature.FeatureRendererContext;
@ -18,10 +18,10 @@ import net.minecraft.util.Arm;
public class HeldItemFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T> & ModelWithArms> extends HeldItemFeatureRenderer<T, M> { public class HeldItemFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T> & ModelWithArms> extends HeldItemFeatureRenderer<T, M> {
private final IPonyRenderContext<T, M> context; private final PonyRenderContext<T, M> context;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public HeldItemFeature(IPonyRenderContext<T, M> context, HeldItemRenderer renderer) { public HeldItemFeature(PonyRenderContext<T, M> context, HeldItemRenderer renderer) {
super((FeatureRendererContext<T, M>)context, renderer); super((FeatureRendererContext<T, M>)context, renderer);
this.context = context; this.context = context;
} }

View file

@ -6,11 +6,11 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.mob.IllagerEntity; import net.minecraft.entity.mob.IllagerEntity;
import com.minelittlepony.client.model.entity.race.AlicornModel; import com.minelittlepony.client.model.entity.race.AlicornModel;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
public class IllagerHeldItemFeature<T extends IllagerEntity, M extends AlicornModel<T>> extends HeldItemFeature<T, M> { public class IllagerHeldItemFeature<T extends IllagerEntity, M extends AlicornModel<T>> extends HeldItemFeature<T, M> {
public IllagerHeldItemFeature(IPonyRenderContext<T,M> livingPony, HeldItemRenderer renderer) { public IllagerHeldItemFeature(PonyRenderContext<T,M> livingPony, HeldItemRenderer renderer) {
super(livingPony, renderer); super(livingPony, renderer);
} }

View file

@ -17,7 +17,7 @@ import net.minecraft.util.Identifier;
import com.minelittlepony.api.model.BodyPart; import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.client.model.ClientPonyModel; import com.minelittlepony.client.model.ClientPonyModel;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
import java.util.Optional; import java.util.Optional;
@ -25,7 +25,7 @@ public class PassengerFeature<T extends PlayerEntity, M extends ClientPonyModel<
private final ParrotEntityModel model; private final ParrotEntityModel model;
public PassengerFeature(IPonyRenderContext<T, M> renderer, EntityRendererFactory.Context context) { public PassengerFeature(PonyRenderContext<T, M> renderer, EntityRendererFactory.Context context) {
super(renderer); super(renderer);
model = new ParrotEntityModel(context.getPart(EntityModelLayers.PARROT)); model = new ParrotEntityModel(context.getPart(EntityModelLayers.PARROT));
} }

View file

@ -3,7 +3,7 @@ package com.minelittlepony.client.render.entity.feature;
import com.minelittlepony.api.model.BodyPart; import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.PonyModel; import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.client.model.AbstractPonyModel; import com.minelittlepony.client.model.AbstractPonyModel;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import java.util.Map; import java.util.Map;
@ -34,7 +34,7 @@ public class SkullFeature<T extends LivingEntity, M extends EntityModel<T> & Pon
private final Map<SkullBlock.SkullType, SkullBlockEntityModel> headModels; private final Map<SkullBlock.SkullType, SkullBlockEntityModel> headModels;
public SkullFeature(IPonyRenderContext<T, M> renderPony, EntityModelLoader entityModelLoader) { public SkullFeature(PonyRenderContext<T, M> renderPony, EntityModelLoader entityModelLoader) {
super(renderPony); super(renderPony);
headModels = SkullBlockEntityRenderer.getModels(entityModelLoader); headModels = SkullBlockEntityRenderer.getModels(entityModelLoader);
} }

View file

@ -20,17 +20,12 @@ import com.minelittlepony.client.render.entity.npc.textures.*;
import java.util.*; import java.util.*;
abstract class AbstractNpcRenderer<T extends MobEntity & VillagerDataContainer> extends PonyRenderer<T, ClientPonyModel<T>> { abstract class AbstractNpcRenderer<T extends MobEntity & VillagerDataContainer> extends PonyRenderer<T, ClientPonyModel<T>> {
private final String entityType;
private final Map<Race, ModelWrapper<T, ClientPonyModel<T>>> models = new EnumMap<>(Race.class); private final Map<Race, ModelWrapper<T, ClientPonyModel<T>>> models = new EnumMap<>(Race.class);
private final NpcClothingFeature<T, ClientPonyModel<T>, AbstractNpcRenderer<T>> clothing; private final NpcClothingFeature<T, ClientPonyModel<T>, AbstractNpcRenderer<T>> clothing;
public AbstractNpcRenderer(EntityRendererFactory.Context context, String type, TextureSupplier<T> textureSupplier, TextureSupplier<String> formatter) { public AbstractNpcRenderer(EntityRendererFactory.Context context, String type, TextureSupplier<T> textureSupplier, TextureSupplier<String> formatter) {
super(context, ModelType.getPlayerModel(Race.EARTH).getKey(false), new SillyPonyTextureSupplier<>(textureSupplier, formatter)); super(context, ModelType.getPlayerModel(Race.EARTH).getKey(false), SillyPonyTextureSupplier.create(textureSupplier, formatter));
entityType = type; clothing = new NpcClothingFeature<>(this, type);
clothing = new NpcClothingFeature<>(this, entityType);
addFeature(clothing); addFeature(clothing);
} }
@ -42,12 +37,9 @@ abstract class AbstractNpcRenderer<T extends MobEntity & VillagerDataContainer>
@Override @Override
public boolean shouldRender(ClientPonyModel<T> model, T entity, Wearable wearable, Gear gear) { public boolean shouldRender(ClientPonyModel<T> model, T entity, Wearable wearable, Gear gear) {
boolean special = SillyPonyTextureSupplier.isBestPony(entity);
if (wearable == Wearable.SADDLE_BAGS_BOTH) { if (wearable == Wearable.SADDLE_BAGS_BOTH) {
VillagerProfession profession = entity.getVillagerData().getProfession(); VillagerProfession profession = entity.getVillagerData().getProfession();
return !special && profession != VillagerProfession.NONE && ( return !SillyPonyTextureSupplier.isBestPony(entity) && profession != VillagerProfession.NONE && (
profession == VillagerProfession.CARTOGRAPHER profession == VillagerProfession.CARTOGRAPHER
|| profession == VillagerProfession.FARMER || profession == VillagerProfession.FARMER
|| profession == VillagerProfession.FISHERMAN || profession == VillagerProfession.FISHERMAN

View file

@ -17,7 +17,7 @@ import net.minecraft.village.VillagerProfession;
import net.minecraft.village.VillagerType; import net.minecraft.village.VillagerType;
import com.minelittlepony.api.model.PonyModel; import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.client.render.IPonyRenderContext; import com.minelittlepony.client.render.PonyRenderContext;
import com.minelittlepony.client.render.entity.feature.AbstractPonyFeature; import com.minelittlepony.client.render.entity.feature.AbstractPonyFeature;
import com.minelittlepony.client.util.render.TextureFlattener; import com.minelittlepony.client.util.render.TextureFlattener;
import com.minelittlepony.util.ResourceUtil; import com.minelittlepony.util.ResourceUtil;
@ -27,7 +27,7 @@ import java.util.*;
class NpcClothingFeature< class NpcClothingFeature<
T extends LivingEntity & VillagerDataContainer, T extends LivingEntity & VillagerDataContainer,
M extends EntityModel<T> & PonyModel<T>, M extends EntityModel<T> & PonyModel<T>,
C extends FeatureRendererContext<T, M> & IPonyRenderContext<T, M>> extends AbstractPonyFeature<T, M> { C extends FeatureRendererContext<T, M> & PonyRenderContext<T, M>> extends AbstractPonyFeature<T, M> {
private static final Int2ObjectMap<Identifier> LEVEL_TO_ID = Util.make(new Int2ObjectOpenHashMap<>(), a -> { private static final Int2ObjectMap<Identifier> LEVEL_TO_ID = Util.make(new Int2ObjectOpenHashMap<>(), a -> {
a.put(1, new Identifier("stone")); a.put(1, new Identifier("stone"));

View file

@ -1,7 +1,6 @@
package com.minelittlepony.client.render.entity.npc; package com.minelittlepony.client.render.entity.npc;
import net.minecraft.client.render.entity.EntityRendererFactory; import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.entity.passive.MerchantEntity;
import net.minecraft.entity.passive.VillagerEntity; import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@ -10,12 +9,10 @@ import com.minelittlepony.client.model.ClientPonyModel;
import com.minelittlepony.client.render.entity.npc.textures.*; import com.minelittlepony.client.render.entity.npc.textures.*;
public class VillagerPonyRenderer extends AbstractNpcRenderer<VillagerEntity> { public class VillagerPonyRenderer extends AbstractNpcRenderer<VillagerEntity> {
private static final String TYPE = "villager";
private static final TextureSupplier<String> FORMATTER = TextureSupplier.formatted("minelittlepony", "textures/entity/villager/%s.png"); private static final TextureSupplier<String> FORMATTER = TextureSupplier.formatted("minelittlepony", "textures/entity/villager/%s.png");
public VillagerPonyRenderer(EntityRendererFactory.Context context) { public VillagerPonyRenderer(EntityRendererFactory.Context context) {
super(context, TYPE, super(context, "villager",
TextureSupplier.ofPool(VariatedTextureSupplier.BACKGROUND_PONIES_POOL, TextureSupplier.ofPool(VariatedTextureSupplier.BACKGROUND_PONIES_POOL,
PlayerTextureSupplier.create(ProfessionTextureSupplier.create(FORMATTER))), FORMATTER); PlayerTextureSupplier.create(ProfessionTextureSupplier.create(FORMATTER))), FORMATTER);
} }
@ -25,9 +22,7 @@ public class VillagerPonyRenderer extends AbstractNpcRenderer<VillagerEntity> {
model.onSetModelAngles((m, move, swing, ticks, entity) -> { model.onSetModelAngles((m, move, swing, ticks, entity) -> {
m.getAttributes().visualHeight += SillyPonyTextureSupplier.isCrownPony(entity) ? 0.3F : -0.1F; m.getAttributes().visualHeight += SillyPonyTextureSupplier.isCrownPony(entity) ? 0.3F : -0.1F;
boolean isHeadRolling = entity instanceof MerchantEntity && ((MerchantEntity)entity).getHeadRollingTimeLeft() > 0; if (entity.getHeadRollingTimeLeft() > 0) {
if (isHeadRolling) {
m.head.yaw = 0.3F * MathHelper.sin(0.45F * ticks); m.head.yaw = 0.3F * MathHelper.sin(0.45F * ticks);
} }
}); });

View file

@ -11,12 +11,10 @@ import com.minelittlepony.client.model.ClientPonyModel;
import com.minelittlepony.client.render.entity.npc.textures.*; import com.minelittlepony.client.render.entity.npc.textures.*;
public class ZomponyVillagerRenderer extends AbstractNpcRenderer<ZombieVillagerEntity> { public class ZomponyVillagerRenderer extends AbstractNpcRenderer<ZombieVillagerEntity> {
private static final String TYPE = "zombie_villager";
private static final TextureSupplier<String> FORMATTER = TextureSupplier.formatted("minelittlepony", "textures/entity/zombie_villager/zombie_%s.png"); private static final TextureSupplier<String> FORMATTER = TextureSupplier.formatted("minelittlepony", "textures/entity/zombie_villager/zombie_%s.png");
public ZomponyVillagerRenderer(EntityRendererFactory.Context context) { public ZomponyVillagerRenderer(EntityRendererFactory.Context context) {
super(context, TYPE, super(context, "zombie_villager",
TextureSupplier.ofPool(VariatedTextureSupplier.BACKGROUND_ZOMPONIES_POOL, TextureSupplier.ofPool(VariatedTextureSupplier.BACKGROUND_ZOMPONIES_POOL,
TextureSupplier.ofPool(VariatedTextureSupplier.BACKGROUND_PONIES_POOL, TextureSupplier.ofPool(VariatedTextureSupplier.BACKGROUND_PONIES_POOL,
PlayerTextureSupplier.create(ProfessionTextureSupplier.create(FORMATTER)))), PlayerTextureSupplier.create(ProfessionTextureSupplier.create(FORMATTER)))),

View file

@ -5,8 +5,6 @@ import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.Util; import net.minecraft.util.Util;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.pony.Pony; import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.SkinsProxy; import com.minelittlepony.client.SkinsProxy;
@ -15,31 +13,20 @@ import java.util.function.Function;
public class PlayerTextureSupplier { public class PlayerTextureSupplier {
public static <T extends LivingEntity> TextureSupplier<T> create(TextureSupplier<T> fallback) { public static <T extends LivingEntity> TextureSupplier<T> create(TextureSupplier<T> fallback) {
Function<String, Entry> customNameCache = Util.memoize(Entry::new); Function<String, CompletableFuture<Identifier>> customNameCache = Util.memoize(name -> {
return SkullBlockEntity.fetchProfile(name).thenApply(profile -> {
return profile
.map(p -> SkinsProxy.instance.getSkinTexture(p))
.filter(skin -> !Pony.getManager().getPony(skin).race().isHuman())
.orElse(null);
});
});
return entity -> { return entity -> {
Identifier override = entity.hasCustomName() ? customNameCache.apply(entity.getCustomName().getString()).getTexture() : null; Identifier override = entity.hasCustomName() ? customNameCache.apply(entity.getCustomName().getString()).getNow(null) : null;
if (override != null) { if (override != null) {
return override; return override;
} }
return fallback.apply(entity); return fallback.apply(entity);
}; };
} }
static final class Entry {
private final CompletableFuture<Identifier> profile;
Entry(String name) {
profile = SkullBlockEntity.fetchProfile(name).thenApply(profile -> {
return profile
.map(p -> SkinsProxy.instance.getSkinTexture(p))
.filter(skin -> !Pony.getManager().getPony(skin).race().isHuman())
.orElse(null);
});
}
@Nullable
public Identifier getTexture() {
return profile.getNow(null);
}
}
} }

View file

@ -4,22 +4,11 @@ import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.village.VillagerDataContainer; import net.minecraft.village.VillagerDataContainer;
public class SillyPonyTextureSupplier<T extends LivingEntity & VillagerDataContainer> implements TextureSupplier<T> { public class SillyPonyTextureSupplier {
public static <T extends LivingEntity & VillagerDataContainer> TextureSupplier<T> create(TextureSupplier<T> fallback, TextureSupplier<String> formatter) {
private final TextureSupplier<T> fallback; Identifier egg = formatter.apply("silly_pony");
Identifier egg2 = formatter.apply("tiny_silly_pony");
private final Identifier egg; return entity -> isBestPony(entity) ? (entity.isBaby() ? egg2 : egg) : fallback.apply(entity);
private final Identifier egg2;
public SillyPonyTextureSupplier(TextureSupplier<T> fallback, TextureSupplier<String> formatter) {
this.fallback = fallback;
this.egg = formatter.apply("silly_pony");
this.egg2 = formatter.apply("tiny_silly_pony");
}
@Override
public Identifier apply(T entity) {
return isBestPony(entity) ? (entity.isBaby() ? egg2 : egg) : fallback.apply(entity);
} }
public static boolean isBestPony(LivingEntity entity) { public static boolean isBestPony(LivingEntity entity) {

View file

@ -6,7 +6,7 @@ import net.minecraft.util.math.Vec3d;
import com.minelittlepony.api.model.BodyPart; import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.PonyModel; import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.pony.meta.Size; import com.minelittlepony.api.pony.meta.Size;
import com.minelittlepony.api.pony.meta.Sizes; import com.minelittlepony.api.pony.meta.SizePreset;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
@ -15,7 +15,7 @@ import java.util.stream.Collectors;
public enum PonyTransformation { public enum PonyTransformation {
NORMAL(Sizes.NORMAL, 0, 3F, 0.75F) { NORMAL(SizePreset.NORMAL, 0, 3F, 0.75F) {
@Override @Override
public void transform(PonyModel<?> model, BodyPart part, MatrixStack stack) { public void transform(PonyModel<?> model, BodyPart part, MatrixStack stack) {
if (model.getAttributes().isSwimming) stack.translate(0, -0.3F, 0); if (model.getAttributes().isSwimming) stack.translate(0, -0.3F, 0);
@ -37,7 +37,7 @@ public enum PonyTransformation {
} }
} }
}, },
LANKY(Sizes.LANKY, 0, 2.6F, 0.75F) { LANKY(SizePreset.LANKY, 0, 2.6F, 0.75F) {
@Override @Override
public void transform(PonyModel<?> model, BodyPart part, MatrixStack stack) { public void transform(PonyModel<?> model, BodyPart part, MatrixStack stack) {
if (model.getAttributes().isSwimming) stack.translate(0, -0.2F, 0); if (model.getAttributes().isSwimming) stack.translate(0, -0.2F, 0);
@ -73,7 +73,7 @@ public enum PonyTransformation {
} }
} }
}, },
BULKY(Sizes.BULKY, 0, 2.3F, 0.75F) { BULKY(SizePreset.BULKY, 0, 2.3F, 0.75F) {
@Override @Override
public void transform(PonyModel<?> model, BodyPart part, MatrixStack stack) { public void transform(PonyModel<?> model, BodyPart part, MatrixStack stack) {
if (model.getAttributes().isCrouching) stack.translate(0, -0.15F, 0); if (model.getAttributes().isCrouching) stack.translate(0, -0.15F, 0);
@ -108,7 +108,7 @@ public enum PonyTransformation {
} }
} }
}, },
FOAL(Sizes.FOAL, 0, 3.8F, 0.75F) { FOAL(SizePreset.FOAL, 0, 3.8F, 0.75F) {
@Override @Override
public void transform(PonyModel<?> model, BodyPart part, MatrixStack stack) { public void transform(PonyModel<?> model, BodyPart part, MatrixStack stack) {
if (model.getAttributes().isSwimming) stack.translate(0, -0.9F, 0); if (model.getAttributes().isSwimming) stack.translate(0, -0.9F, 0);
@ -138,7 +138,7 @@ public enum PonyTransformation {
} }
} }
}, },
TALL(Sizes.TALL, 0, 2.2F, 0.75F) { TALL(SizePreset.TALL, 0, 2.2F, 0.75F) {
@Override @Override
public void transform(PonyModel<?> model, BodyPart part, MatrixStack stack) { public void transform(PonyModel<?> model, BodyPart part, MatrixStack stack) {
if (model.getAttributes().isCrouching) stack.translate(0, -0.15F, 0); if (model.getAttributes().isCrouching) stack.translate(0, -0.15F, 0);
@ -170,7 +170,7 @@ public enum PonyTransformation {
} }
} }
}, },
YEARLING(Sizes.YEARLING, 0, 3.8F, 0.75F) { YEARLING(SizePreset.YEARLING, 0, 3.8F, 0.75F) {
@Override @Override
public void transform(PonyModel<?> model, BodyPart part, MatrixStack stack) { public void transform(PonyModel<?> model, BodyPart part, MatrixStack stack) {
if (model.getAttributes().isSwimming) stack.translate(0, -0.6F, 0); if (model.getAttributes().isSwimming) stack.translate(0, -0.6F, 0);
@ -205,12 +205,12 @@ public enum PonyTransformation {
} }
}; };
private static final Map<Sizes, PonyTransformation> REGISTRY = Arrays.stream(values()).collect(Collectors.toMap(i -> i.size, Function.identity())); private static final Map<Size, PonyTransformation> REGISTRY = Arrays.stream(values()).collect(Collectors.toMap(i -> i.size, Function.identity()));
private final Sizes size; private final Size size;
private final Vec3d riderOffset; private final Vec3d riderOffset;
PonyTransformation(Sizes size, float rX, float rY, float rZ) { PonyTransformation(Size size, float rX, float rY, float rZ) {
this.size = size; this.size = size;
riderOffset = new Vec3d(rX, rY, rZ); riderOffset = new Vec3d(rX, rY, rZ);
} }

View file

@ -5,6 +5,7 @@ import net.minecraft.client.texture.*;
import net.minecraft.resource.Resource; import net.minecraft.resource.Resource;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import com.minelittlepony.api.pony.meta.TriggerPixel;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import java.io.InputStream; import java.io.InputStream;
@ -86,11 +87,11 @@ public class NativeUtil {
} }
} }
public static void parseImage(Identifier resource, Consumer<NativeImage> consumer, Consumer<Exception> fail) { public static void parseImage(Identifier resource, Consumer<TriggerPixel.Mat> consumer, Consumer<Exception> fail) {
parseImage(resource, consumer, fail, 0); parseImage(resource, consumer, fail, 0);
} }
private static void parseImage(Identifier resource, Consumer<NativeImage> consumer, Consumer<Exception> fail, int attempt) { private static void parseImage(Identifier resource, Consumer<TriggerPixel.Mat> consumer, Consumer<Exception> fail, int attempt) {
try { try {
if (!RenderSystem.isOnRenderThread()) { if (!RenderSystem.isOnRenderThread()) {
RenderSystem.recordRenderCall(() -> parseImage(resource, consumer, fail, attempt)); RenderSystem.recordRenderCall(() -> parseImage(resource, consumer, fail, attempt));
@ -105,7 +106,7 @@ public class NativeUtil {
if (loadedTexture instanceof NativeImageBackedTexture nibt) { if (loadedTexture instanceof NativeImageBackedTexture nibt) {
NativeImage image = nibt.getImage(); NativeImage image = nibt.getImage();
if (image != null) { if (image != null) {
consumer.accept(image); consumer.accept(image::getColor);
return; return;
} }
} }
@ -113,7 +114,7 @@ public class NativeUtil {
Resource res = mc.getResourceManager().getResource(resource).orElse(null); Resource res = mc.getResourceManager().getResource(resource).orElse(null);
if (res != null) { if (res != null) {
try (InputStream inputStream = res.getInputStream()){ try (InputStream inputStream = res.getInputStream()){
consumer.accept(NativeImage.read(inputStream)); consumer.accept(NativeImage.read(inputStream)::getColor);
return; return;
} }
} }
@ -124,7 +125,7 @@ public class NativeUtil {
} }
} }
private static void __reconstructNativeImage(Identifier resource, Consumer<NativeImage> consumer, Consumer<Exception> fail, int attempt) { private static void __reconstructNativeImage(Identifier resource, Consumer<TriggerPixel.Mat> consumer, Consumer<Exception> fail, int attempt) {
MinecraftClient mc = MinecraftClient.getInstance(); MinecraftClient mc = MinecraftClient.getInstance();
TextureManager textures = mc.getTextureManager(); TextureManager textures = mc.getTextureManager();
@ -156,7 +157,7 @@ public class NativeUtil {
// This allocates a new array to store the image every time. // This allocates a new array to store the image every time.
// Don't do this every time. Keep a cache and store it so we don't destroy memory. // Don't do this every time. Keep a cache and store it so we don't destroy memory.
image.loadFromTextureImage(0, false); image.loadFromTextureImage(0, false);
consumer.accept(image); consumer.accept(image::getColor);
} }
} }
} }