Convert PonyData classes into records

This commit is contained in:
Sollace 2023-09-25 02:55:43 +01:00
parent ff800006f7
commit 8eca1796e1
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
37 changed files with 189 additions and 440 deletions

View file

@ -53,7 +53,7 @@ public interface IModel {
} }
default Race getRace() { default Race getRace() {
return PonyConfig.getEffectiveRace(getMetadata().getRace()); return PonyConfig.getEffectiveRace(getMetadata().race());
} }
/** /**

View file

@ -25,6 +25,6 @@ public interface IUnicorn extends IModel {
* Gets the preferred magic color for this mode. * Gets the preferred magic color for this mode.
*/ */
default int getMagicColor() { default int getMagicColor() {
return getMetadata().getGlowColor(); return getMetadata().glowColor();
} }
} }

View file

@ -42,14 +42,14 @@ public interface IPony extends Comparable<IPony> {
* Gets the race associated with this pony. * Gets the race associated with this pony.
*/ */
default Race race() { default Race race() {
return PonyConfig.getEffectiveRace(metadata().getRace()); return PonyConfig.getEffectiveRace(metadata().race());
} }
/** /**
* Returns true if and only if this metadata represents a pony that can cast magic. * Returns true if and only if this metadata represents a pony that can cast magic.
*/ */
default boolean hasMagic() { default boolean hasMagic() {
return race().hasHorn() && metadata().getGlowColor() != 0; return race().hasHorn() && metadata().glowColor() != 0;
} }
/** /**

View file

@ -19,37 +19,37 @@ public interface IPonyData extends Comparable<IPonyData> {
* *
* This is the actual race value. For the effective race, prefer going through {@link IPony#race} * This is the actual race value. For the effective race, prefer going through {@link IPony#race}
*/ */
Race getRace(); Race race();
/** /**
* Gets the length of the pony's tail. * Gets the length of the pony's tail.
*/ */
TailLength getTailLength(); TailLength tailLength();
/** /**
* Gets the shape of the pony's tail. * Gets the shape of the pony's tail.
*/ */
TailShape getTailShape(); TailShape tailShape();
/** /**
* Get the pony's gender (usually female). * Get the pony's gender (usually female).
*/ */
Gender getGender(); Gender gender();
/** /**
* Gets the current pony size. * Gets the current pony size.
*/ */
Size getSize(); Size size();
/** /**
* Gets the magical glow colour for magic-casting races. Returns 0 otherwise. * Gets the magical glow colour for magic-casting races. Returns 0 otherwise.
*/ */
int getGlowColor(); int glowColor();
/** /**
* Returns an array of wearables that this pony is carrying. * Returns an array of wearables that this pony is carrying.
*/ */
Wearable[] getGear(); Wearable[] gear();
/** /**
* Checks it this pony is wearing the given accessory. * Checks it this pony is wearing the given accessory.
@ -59,22 +59,24 @@ public interface IPonyData extends Comparable<IPonyData> {
/** /**
* Gets an interpolator for interpolating values. * Gets an interpolator for interpolating values.
*/ */
Interpolator getInterpolator(UUID interpolatorId); default Interpolator getInterpolator(UUID interpolatorId) {
return Interpolator.linear(interpolatorId);
}
/** /**
* 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<?>> getTriggerPixels(); Map<String, TriggerPixelType<?>> attributes();
@Override @Override
default int compareTo(@Nullable IPonyData o) { default int compareTo(@Nullable IPonyData o) {
return o == this ? 0 : o == null ? 1 : ComparisonChain.start() return o == this ? 0 : o == null ? 1 : ComparisonChain.start()
.compare(getRace(), o.getRace()) .compare(race(), o.race())
.compare(getTailLength(), o.getTailLength()) .compare(tailLength(), o.tailLength())
.compare(getGender(), o.getGender()) .compare(gender(), o.gender())
.compare(getSize().ordinal(), o.getSize().ordinal()) .compare(size().ordinal(), o.size().ordinal())
.compare(getGlowColor(), o.getGlowColor()) .compare(glowColor(), o.glowColor())
.compare(0, Arrays.compare(getGear(), o.getGear())) .compare(0, Arrays.compare(gear(), o.gear()))
.result(); .result();
} }
} }

View file

@ -1,24 +0,0 @@
package com.minelittlepony.api.pony;
import java.util.List;
@SuppressWarnings("unchecked")
public class TriggerPixelSet<T extends Enum<T> & TriggerPixelType<T>> extends TriggerPixelValue<boolean[]> {
private final T def;
public TriggerPixelSet(int color, T def, boolean[] value) {
super(color, value);
this.def = def;
}
@Override
public List<TriggerPixelType<T>> getOptions() {
return def.getOptions();
}
@Override
public boolean matches(Object o) {
return o.getClass() == def.getClass() && getValue()[((Enum<?>)o).ordinal()];
}
}

View file

@ -1,5 +1,6 @@
package com.minelittlepony.api.pony; package com.minelittlepony.api.pony;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
@ -9,13 +10,13 @@ public interface TriggerPixelType<T> {
/** /**
* Gets the pixel colour matching this enum value. * Gets the pixel colour matching this enum value.
*/ */
int getColorCode(); int colorCode();
/** /**
* Gets the pixel colour matching this enum value, adjusted to fill all three channels. * Gets the pixel colour matching this enum value, adjusted to fill all three channels.
*/ */
default int getChannelAdjustedColorCode() { default int getChannelAdjustedColorCode() {
return getColorCode(); return colorCode();
} }
/** /**
@ -26,7 +27,7 @@ public interface TriggerPixelType<T> {
} }
default String getHexValue() { default String getHexValue() {
return toHex(getColorCode()); return toHex(colorCode());
} }
/** /**
@ -55,7 +56,7 @@ public interface TriggerPixelType<T> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static <T extends TriggerPixelType<T>> T getByTriggerPixel(T type, int pixelValue) { static <T extends TriggerPixelType<T>> T getByTriggerPixel(T type, int pixelValue) {
return (T)type.getOptions().stream() return (T)type.getOptions().stream()
.filter(i -> i.getColorCode() == pixelValue) .filter(i -> i.colorCode() == pixelValue)
.findFirst() .findFirst()
.orElse(type); .orElse(type);
} }
@ -71,4 +72,43 @@ public interface TriggerPixelType<T> {
} }
return "#" + v; return "#" + v;
} }
public record Flags<T extends Enum<T> & TriggerPixelType<T>> (
int colorCode,
T def,
boolean[] value
) implements TriggerPixelType<boolean[]> {
@Override
public String name() {
return "[Flags " + Arrays.toString(value) + "]";
}
@SuppressWarnings("unchecked")
@Override
public List<TriggerPixelType<T>> getOptions() {
return def.getOptions();
}
@Override
public boolean matches(Object o) {
return o.getClass() == def.getClass() && value()[((Enum<?>)o).ordinal()];
}
}
public record Value<T> (
int colorCode,
T value
) implements TriggerPixelType<T> {
@Override
public String name() {
return value instanceof TriggerPixelType t ? t.name() : TriggerPixelType.super.name();
}
@SuppressWarnings("unchecked")
@Override
public <Option extends TriggerPixelType<T>> List<Option> getOptions() {
return value instanceof TriggerPixelType t ? t.getOptions() : TriggerPixelType.super.getOptions();
}
}
} }

View file

@ -1,43 +0,0 @@
package com.minelittlepony.api.pony;
import java.util.List;
import java.util.Objects;
public class TriggerPixelValue<T> implements TriggerPixelType<T> {
private final int color;
private final T value;
public TriggerPixelValue(int color, T value) {
this.color = color;
this.value = value;
}
@SuppressWarnings("unchecked")
@Override
public String name() {
return value instanceof TriggerPixelType ? ((TriggerPixelType<T>)value).name() : TriggerPixelType.super.name();
}
@SuppressWarnings("unchecked")
@Override
public <Option extends TriggerPixelType<T>> List<Option> getOptions() {
return value instanceof TriggerPixelType ? ((TriggerPixelType<T>)value).getOptions() : TriggerPixelType.super.getOptions();
}
public T getValue() {
return value;
}
@Override
public int getColorCode() {
return color;
}
@Override
public boolean equals(Object o) {
return super.equals(o)
|| (o instanceof TriggerPixelValue && Objects.equals(((TriggerPixelValue<?>)o).getValue(), getValue()))
|| Objects.equals(o, getValue());
}
}

View file

@ -14,7 +14,7 @@ public enum Gender implements TriggerPixelType<Gender> {
} }
@Override @Override
public int getColorCode() { public int colorCode() {
return triggerValue; return triggerValue;
} }

View file

@ -69,7 +69,7 @@ public enum Race implements TriggerPixelType<Race> {
} }
@Override @Override
public int getColorCode() { public int colorCode() {
return triggerPixel; return triggerPixel;
} }
} }

View file

@ -27,20 +27,20 @@ public interface Size extends TriggerPixelType<Size> {
/** /**
* A scale factor that controls the size of the shadow that appears under the entity. * A scale factor that controls the size of the shadow that appears under the entity.
*/ */
float getShadowSize(); float shadowSize();
/** /**
* The global scale factor applied to all physical dimensions. * The global scale factor applied to all physical dimensions.
*/ */
float getScaleFactor(); float scaleFactor();
/** /**
* A scale factor used to alter the vertical eye position. * A scale factor used to alter the vertical eye position.
*/ */
float getEyeHeightFactor(); float eyeHeightFactor();
/** /**
* A scale factor used to alter the camera's distance. * A scale factor used to alter the camera's distance.
*/ */
float getEyeDistanceFactor(); float eyeDistanceFactor();
} }

View file

@ -34,17 +34,17 @@ public enum Sizes implements Size {
} }
@Override @Override
public float getShadowSize() { public float shadowSize() {
return shadowSize * PonyConfig.getInstance().getGlobalScaleFactor(); return shadowSize * PonyConfig.getInstance().getGlobalScaleFactor();
} }
@Override @Override
public float getScaleFactor() { public float scaleFactor() {
return scale * PonyConfig.getInstance().getGlobalScaleFactor(); return scale * PonyConfig.getInstance().getGlobalScaleFactor();
} }
@Override @Override
public float getEyeHeightFactor() { public float eyeHeightFactor() {
if (!PonyConfig.getInstance().fillycam.get()) { if (!PonyConfig.getInstance().fillycam.get()) {
return 1; return 1;
} }
@ -52,7 +52,7 @@ public enum Sizes implements Size {
} }
@Override @Override
public float getEyeDistanceFactor() { public float eyeDistanceFactor() {
if (!PonyConfig.getInstance().fillycam.get()) { if (!PonyConfig.getInstance().fillycam.get()) {
return 1; return 1;
} }
@ -60,7 +60,7 @@ public enum Sizes implements Size {
} }
@Override @Override
public int getColorCode() { public int colorCode() {
return triggerValue; return triggerValue;
} }

View file

@ -16,7 +16,7 @@ public enum TailLength implements TriggerPixelType<TailLength> {
} }
@Override @Override
public int getColorCode() { public int colorCode() {
return triggerValue; return triggerValue;
} }
} }

View file

@ -15,7 +15,7 @@ public enum TailShape implements TriggerPixelType<TailShape> {
} }
@Override @Override
public int getColorCode() { public int colorCode() {
return triggerValue; return triggerValue;
} }
} }

View file

@ -2,9 +2,7 @@ package com.minelittlepony.api.pony.meta;
import net.minecraft.client.texture.NativeImage; import net.minecraft.client.texture.NativeImage;
import com.minelittlepony.api.pony.TriggerPixelSet;
import com.minelittlepony.api.pony.TriggerPixelType; import com.minelittlepony.api.pony.TriggerPixelType;
import com.minelittlepony.api.pony.TriggerPixelValue;
import com.minelittlepony.common.util.Color; import com.minelittlepony.common.util.Color;
import java.util.Arrays; import java.util.Arrays;
@ -55,20 +53,20 @@ public enum TriggerPixel {
* *
* @param image Image to read * @param image Image to read
*/ */
public <T extends TriggerPixelType<T>> TriggerPixelValue<T> readValue(NativeImage image) { public <T extends TriggerPixelType<T>> TriggerPixelType.Value<T> readValue(NativeImage image) {
int color = readColor(image); int color = readColor(image);
if (Channel.ALPHA.readValue(x, y, image) < 255) { if (Channel.ALPHA.readValue(x, y, image) < 255) {
return new TriggerPixelValue<>(color, (T)def); return new TriggerPixelType.Value<>(color, (T)def);
} }
return new TriggerPixelValue<>(color, TriggerPixelType.getByTriggerPixel((T)def, color)); return new TriggerPixelType.Value<>(color, TriggerPixelType.getByTriggerPixel((T)def, color));
} }
public <T extends Enum<T> & TriggerPixelType<T>> TriggerPixelSet<T> readFlags(NativeImage image) { public <T extends Enum<T> & TriggerPixelType<T>> TriggerPixelType.Flags<T> readFlags(NativeImage image) {
boolean[] out = new boolean[def.getClass().getEnumConstants().length]; boolean[] out = new boolean[def.getClass().getEnumConstants().length];
readFlags(out, image); readFlags(out, image);
return new TriggerPixelSet<>(readColor(image), (T)def, out); return new TriggerPixelType.Flags<>(readColor(image), (T)def, out);
} }
public <T extends Enum<T> & TriggerPixelType<T>> void readFlags(boolean[] out, NativeImage image) { public <T extends Enum<T> & TriggerPixelType<T>> void readFlags(boolean[] out, NativeImage image) {

View file

@ -45,7 +45,7 @@ public enum Wearable implements TriggerPixelType<Wearable> {
} }
@Override @Override
public int getColorCode() { public int colorCode() {
return triggerValue; return triggerValue;
} }

View file

@ -74,14 +74,14 @@ public class MsgPonyData implements IPonyData {
} }
public MsgPonyData(IPonyData data, boolean noSkin) { public MsgPonyData(IPonyData data, boolean noSkin) {
race = data.getRace(); race = data.race();
tailLength = data.getTailLength(); tailLength = data.tailLength();
tailShape = data.getTailShape(); tailShape = data.tailShape();
gender = data.getGender(); gender = data.gender();
size = data.getSize(); size = data.size();
glowColor = data.getGlowColor(); glowColor = data.glowColor();
wearables = Wearable.flags(data.getGear()); wearables = Wearable.flags(data.gear());
wearableColor = data.getTriggerPixels().get("gear").getColorCode(); wearableColor = data.attributes().get("gear").colorCode();
this.noSkin = noSkin; this.noSkin = noSkin;
} }
@ -96,7 +96,7 @@ public class MsgPonyData implements IPonyData {
buffer.writeInt(glowColor); buffer.writeInt(glowColor);
buffer.writeBoolean(noSkin); buffer.writeBoolean(noSkin);
Wearable[] gear = getGear(); Wearable[] gear = gear();
buffer.writeInt(gear.length); buffer.writeInt(gear.length);
for (int i = 0; i < gear.length; i++) { for (int i = 0; i < gear.length; i++) {
buffer.writeInt(gear[i].ordinal()); buffer.writeInt(gear[i].ordinal());
@ -110,37 +110,37 @@ public class MsgPonyData implements IPonyData {
} }
@Override @Override
public Race getRace() { public Race race() {
return race; return race;
} }
@Override @Override
public TailLength getTailLength() { public TailLength tailLength() {
return tailLength; return tailLength;
} }
@Override @Override
public TailShape getTailShape() { public TailShape tailShape() {
return tailShape; return tailShape;
} }
@Override @Override
public Gender getGender() { public Gender gender() {
return gender; return gender;
} }
@Override @Override
public Size getSize() { public Size size() {
return size; return size;
} }
@Override @Override
public int getGlowColor() { public int glowColor() {
return glowColor; return glowColor;
} }
@Override @Override
public Wearable[] getGear() { public Wearable[] gear() {
return Wearable.flags(wearables); return Wearable.flags(wearables);
} }
@ -155,7 +155,7 @@ public class MsgPonyData implements IPonyData {
} }
@Override @Override
public Map<String, TriggerPixelType<?>> getTriggerPixels() { public Map<String, TriggerPixelType<?>> attributes() {
return triggerPixels.get(); return triggerPixels.get();
} }
@ -167,88 +167,45 @@ public class MsgPonyData implements IPonyData {
.add("tailShape", tailShape) .add("tailShape", tailShape)
.add("gender", gender) .add("gender", gender)
.add("size", size) .add("size", size)
.add("wearables", getGear()) .add("wearables", gear())
.add("glowColor", TriggerPixelType.toHex(glowColor)) .add("glowColor", TriggerPixelType.toHex(glowColor))
.toString(); .toString();
} }
private static final class MsgSize implements Size { private record MsgSize (
int ordinal,
private final int ordinal; String name,
private final String name; float shadowSize,
private final float shadow; float scaleFactor,
private final float scale; float eyeHeightFactor,
private final float eyeHeight; float eyeDistanceFactor,
private final float eyeDistance; int triggerPixel) implements Size {
private final int triggerPixel;
MsgSize(Size size) { MsgSize(Size size) {
ordinal = size.ordinal(); this(size.ordinal(), size.name(), size.shadowSize(), size.scaleFactor(), size.eyeHeightFactor(), size.eyeDistanceFactor(), size.colorCode());
name = size.name();
shadow = size.getShadowSize();
scale = size.getScaleFactor();
eyeHeight = size.getEyeHeightFactor();
eyeDistance = size.getEyeDistanceFactor();
triggerPixel = size.getColorCode();
} }
MsgSize(PacketByteBuf buffer) { MsgSize(PacketByteBuf buffer) {
ordinal = buffer.readInt(); this(buffer.readInt(), buffer.readString(32767), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readInt());
name = buffer.readString(32767);
shadow = buffer.readFloat();
scale = buffer.readFloat();
eyeHeight = buffer.readFloat();
eyeDistance = buffer.readFloat();
triggerPixel = buffer.readInt();
} }
public void toBuffer(PacketByteBuf buffer) { public void toBuffer(PacketByteBuf buffer) {
buffer.writeInt(ordinal); buffer.writeInt(ordinal);
buffer.writeString(name); buffer.writeString(name);
buffer.writeFloat(shadow); buffer.writeFloat(shadowSize);
buffer.writeFloat(scale); buffer.writeFloat(scaleFactor);
buffer.writeFloat(eyeHeight); buffer.writeFloat(eyeHeightFactor);
buffer.writeFloat(eyeDistance); buffer.writeFloat(eyeDistanceFactor);
buffer.writeFloat(triggerPixel); buffer.writeFloat(triggerPixel);
} }
@Override
public int ordinal() {
return ordinal;
}
@Override
public String name() {
return name;
}
@Override
public float getShadowSize() {
return shadow;
}
@Override
public float getScaleFactor() {
return scale;
}
@Override
public float getEyeHeightFactor() {
return eyeHeight;
}
@Override
public float getEyeDistanceFactor() {
return eyeDistance;
}
@Override @Override
public String toString() { public String toString() {
return name; return name;
} }
@Override @Override
public int getColorCode() { public int colorCode() {
return triggerPixel; return triggerPixel;
} }
} }

View file

@ -16,8 +16,8 @@ public class PonyBounds {
return PonyPosture.getMountPony(entity).map(ridingPony -> { return PonyPosture.getMountPony(entity).map(ridingPony -> {
LivingEntity vehicle = (LivingEntity)entity.getVehicle(); LivingEntity vehicle = (LivingEntity)entity.getVehicle();
Vec3d offset = PonyTransformation.forSize(ridingPony.metadata().getSize()).getRiderOffset(); Vec3d offset = PonyTransformation.forSize(ridingPony.metadata().size()).getRiderOffset();
float scale = ridingPony.metadata().getSize().getScaleFactor(); float scale = ridingPony.metadata().size().scaleFactor();
return getAbsoluteRidingOffset(vehicle).add( return getAbsoluteRidingOffset(vehicle).add(
0, 0,
@ -41,7 +41,7 @@ public class PonyBounds {
} }
public static Box getBoundingBox(IPony pony, LivingEntity entity) { public static Box getBoundingBox(IPony pony, LivingEntity entity) {
final float scale = pony.metadata().getSize().getScaleFactor() + 0.1F; final float scale = pony.metadata().size().scaleFactor() + 0.1F;
final float width = entity.getWidth() * scale; final float width = entity.getWidth() * scale;
final float height = entity.getHeight() * scale; final float height = entity.getHeight() * scale;

View file

@ -25,7 +25,7 @@ class LegendOverlayWidget implements Carousel.Element, ITextContext {
public void render(DummyPlayer player, DrawContext context, int mouseX, int mouseY) { public void render(DummyPlayer player, DrawContext context, int mouseX, int mouseY) {
IPonyData data = IPony.getManager().getPony(player).metadata(); IPonyData data = IPony.getManager().getPony(player).metadata();
int[] index = new int[1]; int[] index = new int[1];
data.getTriggerPixels().forEach((key, value) -> { data.attributes().forEach((key, value) -> {
context.getMatrices().push(); context.getMatrices().push();
int i = index[0]++; int i = index[0]++;
int x = frame.left; int x = frame.left;
@ -38,7 +38,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, TriggerPixelType<?> 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.getColorCode() | 0xFF000000); context.fill(1, 1, LEGEND_BLOCK_BOUNDS.width - 1, LEGEND_BLOCK_BOUNDS.height - 1, value.colorCode() | 0xFF000000);
char symbol = value.name().charAt(0); char symbol = value.name().charAt(0);
if (symbol == '[') { if (symbol == '[') {
@ -60,7 +60,7 @@ class LegendOverlayWidget implements Carousel.Element, ITextContext {
if (lines.size() == 1) { if (lines.size() == 1) {
lines.add(Text.literal(value.name()).styled(s -> { lines.add(Text.literal(value.name()).styled(s -> {
int color = value.getChannelAdjustedColorCode(); int color = value.getChannelAdjustedColorCode();
return color == 0 ? s : s.withColor(value.getColorCode()); return color == 0 ? s : s.withColor(value.colorCode());
})); }));
} }
context.drawTooltip(getFont(), lines, 2, 10); context.drawTooltip(getFont(), lines, 2, 10);

View file

@ -105,7 +105,7 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
IPonyData metadata = IPony.getManager().getPony(main.getId()).metadata(); IPonyData metadata = IPony.getManager().getPony(main.getId()).metadata();
if (wearable != Wearable.NONE && metadata.isWearing(wearable)) { if (wearable != Wearable.NONE && metadata.isWearing(wearable)) {
if (wearable.isSaddlebags() && metadata.getRace().supportsLegacySaddlebags()) { if (wearable.isSaddlebags() && metadata.race().supportsLegacySaddlebags()) {
return Optional.of(main.getId()); return Optional.of(main.getId());
} }

View file

@ -21,7 +21,7 @@ abstract class MixinCamera {
IPony pony = IPony.getManager().getPony(MinecraftClient.getInstance().player); IPony pony = IPony.getManager().getPony(MinecraftClient.getInstance().player);
if (!pony.race().isHuman()) { if (!pony.race().isHuman()) {
value *= pony.metadata().getSize().getEyeDistanceFactor(); value *= pony.metadata().size().eyeDistanceFactor();
} }
info.setReturnValue(value); info.setReturnValue(value);

View file

@ -50,7 +50,7 @@ abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity implem
IPony pony = IPony.getManager().getPony(this); IPony pony = IPony.getManager().getPony(this);
if (!pony.race().isHuman()) { if (!pony.race().isHuman()) {
float factor = pony.metadata().getSize().getEyeHeightFactor(); float factor = pony.metadata().size().eyeHeightFactor();
if (factor != 1) { if (factor != 1) {
value *= factor; value *= factor;

View file

@ -67,7 +67,7 @@ public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer
@Override @Override
public Size getSize() { public Size getSize() {
return child ? Sizes.FOAL : getMetadata().getSize(); return child ? Sizes.FOAL : getMetadata().size();
} }
@Override @Override

View file

@ -57,7 +57,7 @@ public class ChristmasHat extends AbstractWearableGear {
bodySwing += 0.1F; bodySwing += 0.1F;
tint = model.getMetadata().getGlowColor(); tint = model.getMetadata().glowColor();
left.roll = bodySwing; left.roll = bodySwing;
right.roll = -bodySwing; right.roll = -bodySwing;
} }

View file

@ -56,8 +56,8 @@ public class PonyEars implements IPart, MsonModel {
@Override @Override
public void setVisible(boolean visible, ModelAttributes attributes) { public void setVisible(boolean visible, ModelAttributes attributes) {
right.visible = visible && !attributes.metadata.getRace().isHuman(); right.visible = visible && !attributes.metadata.race().isHuman();
left.visible = visible && !attributes.metadata.getRace().isHuman(); left.visible = visible && !attributes.metadata.race().isHuman();
if (attributes.isHorsey) { if (attributes.isHorsey) {
left.pivotX = -1; left.pivotX = -1;

View file

@ -40,9 +40,9 @@ public class PonySnout implements IPart, MsonModel {
@Override @Override
public void setVisible(boolean visible, ModelAttributes attributes) { public void setVisible(boolean visible, ModelAttributes attributes) {
visible &= !attributes.isHorsey visible &= !attributes.isHorsey
&& !attributes.metadata.getRace().isHuman() && !attributes.metadata.race().isHuman()
&& MineLittlePony.getInstance().getConfig().snuzzles.get(); && MineLittlePony.getInstance().getConfig().snuzzles.get();
Gender gender = attributes.metadata.getGender(); Gender gender = attributes.metadata.gender();
mare.visible = (visible && gender.isMare()); mare.visible = (visible && gender.isMare());
stallion.visible = (visible && gender.isStallion()); stallion.visible = (visible && gender.isStallion());

View file

@ -81,8 +81,8 @@ public class PonyTail implements IPart, MsonModel {
@Override @Override
public void setVisible(boolean visible, ModelAttributes attributes) { public void setVisible(boolean visible, ModelAttributes attributes) {
tail.visible = visible; tail.visible = visible;
tailStop = attributes.metadata.getTailLength().ordinal(); tailStop = attributes.metadata.tailLength().ordinal();
shape = attributes.metadata.getTailShape(); shape = attributes.metadata.tailShape();
} }
@Override @Override

View file

@ -119,14 +119,14 @@ public class PonyWings<T extends Model & IPegasus> implements IPart, MsonModel {
public void rotateWalking(float swing) { public void rotateWalking(float swing) {
folded.yaw = swing * walkingRotationSpeed; folded.yaw = swing * walkingRotationSpeed;
if (pegasus.getMetadata().getRace().hasBugWings()) { if (pegasus.getMetadata().race().hasBugWings()) {
extended.yaw = folded.yaw; extended.yaw = folded.yaw;
} }
} }
public void rotateFlying(float roll) { public void rotateFlying(float roll) {
extended.roll = roll; extended.roll = roll;
if (pegasus.getMetadata().getRace().hasBugWings()) { if (pegasus.getMetadata().race().hasBugWings()) {
folded.roll = roll; folded.roll = roll;
} }
} }

View file

@ -1,126 +0,0 @@
package com.minelittlepony.client.pony;
import net.minecraft.client.texture.NativeImage;
import com.google.common.base.MoreObjects;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.TriggerPixelSet;
import com.minelittlepony.api.pony.TriggerPixelType;
import com.minelittlepony.api.pony.TriggerPixelValue;
import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.common.util.animation.Interpolator;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import org.jetbrains.annotations.Unmodifiable;
/**
* Implementation for IPonyData.
*/
@Unmodifiable
class NativePonyData implements IPonyData {
private final TriggerPixelValue<Race> race;
private final TriggerPixelValue<TailLength> tailLength;
private final TriggerPixelValue<TailShape> tailShape;
private final TriggerPixelValue<Gender> gender;
private final TriggerPixelValue<Size> size;
private final int glowColor;
private final TriggerPixelSet<Wearable> wearables;
private final Map<String, TriggerPixelType<?>> attributes = new TreeMap<>();
NativePonyData(NativeImage image) {
race = TriggerPixel.RACE.readValue(image);
tailLength = TriggerPixel.TAIL.readValue(image);
tailShape = TriggerPixel.TAIL_SHAPE.readValue(image);
size = TriggerPixel.SIZE.readValue(image);
gender = TriggerPixel.GENDER.readValue(image);
glowColor = TriggerPixel.GLOW.readColor(image);
wearables = TriggerPixel.WEARABLES.readFlags(image);
attributes.put("race", race);
attributes.put("tailLength", tailLength);
attributes.put("tailShape", tailShape);
attributes.put("gender", gender);
attributes.put("size", size);
attributes.put("magic", TriggerPixelType.of(glowColor));
attributes.put("gear", wearables);
}
@Override
public Race getRace() {
return race.getValue();
}
@Override
public TailLength getTailLength() {
return tailLength.getValue();
}
@Override
public TailShape getTailShape() {
return tailShape.getValue();
}
@Override
public Gender getGender() {
return gender.getValue();
}
@Override
public Sizes getSize() {
Sizes sz = MineLittlePony.getInstance().getConfig().sizeOverride.get();
if (sz != Sizes.UNSET) {
return sz;
}
if (size.getValue() == Sizes.UNSET || !MineLittlePony.getInstance().getConfig().sizes.get()) {
return Sizes.NORMAL;
}
return (Sizes)size.getValue();
}
@Override
public int getGlowColor() {
return glowColor;
}
@Override
public Wearable[] getGear() {
return Wearable.flags(wearables.getValue());
}
@Override
public boolean isWearing(Wearable wearable) {
return wearables.matches(wearable);
}
@Override
public Interpolator getInterpolator(UUID interpolatorId) {
return Interpolator.linear(interpolatorId);
}
@Override
public Map<String, TriggerPixelType<?>> getTriggerPixels() {
return attributes;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("race", race.getValue())
.add("tailLength", tailLength.getValue())
.add("tailShape", tailShape.getValue())
.add("gender", gender.getValue())
.add("size", size.getValue())
.add("wearables", getGear())
.add("glowColor", TriggerPixelType.toHex(glowColor))
.toString();
}
}

View file

@ -2,26 +2,30 @@ package com.minelittlepony.client.pony;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import com.google.common.base.MoreObjects;
import com.google.gson.annotations.Expose;
import com.minelittlepony.api.pony.IPonyData; import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.TriggerPixelType; import com.minelittlepony.api.pony.TriggerPixelType;
import com.minelittlepony.api.pony.meta.*; import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.client.MineLittlePony; import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.util.render.NativeUtil; import com.minelittlepony.client.util.render.NativeUtil;
import com.minelittlepony.common.util.animation.Interpolator;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
/** /**
* Implementation for IPonyData. * Implementation for IPonyData.
*/ */
@Unmodifiable public record PonyData (
public class PonyData implements IPonyData { Race race,
TailLength tailLength,
TailShape tailShape,
Gender gender,
Size size,
int glowColor,
boolean[] wearables,
Map<String, TriggerPixelType<?>> attributes
) implements IPonyData {
private static final PonyDataSerialiser SERIALISER = new PonyDataSerialiser(); private static final PonyDataSerialiser SERIALISER = new PonyDataSerialiser();
@ -46,8 +50,16 @@ public class PonyData implements IPonyData {
return null; return null;
}).map(Memoize::of).orElseGet(() -> { }).map(Memoize::of).orElseGet(() -> {
return Memoize.load(callback -> { return Memoize.load(callback -> {
NativeUtil.parseImage(identifier, img -> { NativeUtil.parseImage(identifier, image -> {
callback.accept(new NativePonyData(img)); callback.accept(new PonyData(
TriggerPixel.RACE.<Race>readValue(image),
TriggerPixel.TAIL.<TailLength>readValue(image),
TriggerPixel.TAIL_SHAPE.<TailShape>readValue(image),
TriggerPixel.GENDER.<Gender>readValue(image),
TriggerPixel.SIZE.<Size>readValue(image),
TriggerPixel.GLOW.readColor(image),
TriggerPixel.WEARABLES.readFlags(image)
));
}, e -> { }, e -> {
MineLittlePony.logger.fatal("Unable to read {} metadata", identifier, e); MineLittlePony.logger.fatal("Unable to read {} metadata", identifier, e);
callback.accept(NULL); callback.accept(NULL);
@ -56,31 +68,8 @@ public class PonyData implements IPonyData {
}); });
} }
@Expose
private final Race race;
@Expose
private final TailLength tailLength = TailLength.FULL;
@Expose
private final TailShape tailShape = TailShape.STRAIGHT;
@Expose
private final Gender gender = Gender.MARE;
@Expose
private final Sizes size = Sizes.NORMAL;
@Expose
private final int glowColor = 0x4444aa;
@Expose
private final boolean[] wearables = new boolean[Wearable.values().length];
private final Map<String, TriggerPixelType<?>> attributes = new TreeMap<>();
public PonyData(Race race) { public PonyData(Race race) {
this.race = race; this(race, TailLength.FULL, TailShape.STRAIGHT, Gender.MARE, Sizes.NORMAL, 0x4444aa, new boolean[Wearable.values().length], new TreeMap<>());
attributes.put("race", race); attributes.put("race", race);
attributes.put("tailLength", tailLength); attributes.put("tailLength", tailLength);
attributes.put("tailShape", tailShape); attributes.put("tailShape", tailShape);
@ -90,28 +79,20 @@ public class PonyData implements IPonyData {
attributes.put("gear", TriggerPixelType.of(0)); attributes.put("gear", TriggerPixelType.of(0));
} }
@Override PonyData(TriggerPixelType.Value<Race> race, TriggerPixelType.Value<TailLength> tailLength, TriggerPixelType.Value<TailShape> tailShape,
public Race getRace() { TriggerPixelType.Value<Gender> gender, TriggerPixelType.Value<Size> size, int glowColor, TriggerPixelType.Flags<Wearable> wearables) {
return race; this(race.value(), tailLength.value(), tailShape.value(), gender.value(), size.value(), glowColor, wearables.value(), new TreeMap<>());
attributes.put("race", race);
attributes.put("tailLength", tailLength);
attributes.put("tailShape", tailShape);
attributes.put("gender", gender);
attributes.put("size", size);
attributes.put("magic", TriggerPixelType.of(glowColor));
attributes.put("gear", wearables);
} }
@Override @Override
public TailLength getTailLength() { public Size size() {
return tailLength;
}
@Override
public TailShape getTailShape() {
return tailShape;
}
@Override
public Gender getGender() {
return gender;
}
@Override
public Sizes getSize() {
Sizes sz = MineLittlePony.getInstance().getConfig().sizeOverride.get(); Sizes sz = MineLittlePony.getInstance().getConfig().sizeOverride.get();
if (sz != Sizes.UNSET) { if (sz != Sizes.UNSET) {
@ -126,12 +107,7 @@ public class PonyData implements IPonyData {
} }
@Override @Override
public int getGlowColor() { public Wearable[] gear() {
return glowColor;
}
@Override
public Wearable[] getGear() {
return Wearable.flags(wearables); return Wearable.flags(wearables);
} }
@ -139,26 +115,4 @@ public class PonyData implements IPonyData {
public boolean isWearing(Wearable wearable) { public boolean isWearing(Wearable wearable) {
return wearables[wearable.ordinal()]; return wearables[wearable.ordinal()];
} }
@Override
public Interpolator getInterpolator(UUID interpolatorId) {
return Interpolator.linear(interpolatorId);
}
public Map<String, TriggerPixelType<?>> getTriggerPixels() {
return attributes;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("race", race)
.add("tailLength", tailLength)
.add("tailShape", tailShape)
.add("gender", gender)
.add("size", size)
.add("wearables", getGear())
.add("glowColor", TriggerPixelType.toHex(glowColor))
.toString();
}
} }

View file

@ -94,7 +94,7 @@ public class PonyManager implements IPonyManager, SimpleSynchronousResourceReloa
public IPony getPony(Identifier resource, UUID uuid) { public IPony getPony(Identifier resource, UUID uuid) {
IPony pony = getPony(resource); IPony pony = getPony(resource);
if (config.ponyLevel.get() == PonyLevel.PONIES && pony.metadata().getRace().isHuman()) { if (config.ponyLevel.get() == PonyLevel.PONIES && pony.metadata().race().isHuman()) {
return getBackgroundPony(uuid); return getBackgroundPony(uuid);
} }

View file

@ -141,7 +141,7 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
} }
public float getScaleFactor() { public float getScaleFactor() {
return getModel().getSize().getScaleFactor(); return getModel().getSize().scaleFactor();
} }
public double getNamePlateYOffset(T entity) { public double getNamePlateYOffset(T entity) {

View file

@ -22,7 +22,7 @@ import net.minecraft.world.World;
public class LevitatingItemRenderer { public class LevitatingItemRenderer {
private VertexConsumerProvider getProvider(IPony pony, VertexConsumerProvider renderContext) { private VertexConsumerProvider getProvider(IPony pony, VertexConsumerProvider renderContext) {
final int color = pony.metadata().getGlowColor(); final int color = pony.metadata().glowColor();
return layer -> { return layer -> {
Identifier texture = RenderLayerUtil.getTexture(layer).orElse(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE); Identifier texture = RenderLayerUtil.getTexture(layer).orElse(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE);
if (texture == ItemRenderer.ENTITY_ENCHANTMENT_GLINT || texture == ItemRenderer.ITEM_ENCHANTMENT_GLINT) { if (texture == ItemRenderer.ENTITY_ENCHANTMENT_GLINT || texture == ItemRenderer.ITEM_ENCHANTMENT_GLINT) {

View file

@ -90,7 +90,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().getShadowSize(); shadowRadius = manager.getModel().getSize().shadowSize();
if (entity.isBaby()) { if (entity.isBaby()) {
shadowRadius *= 3; // undo vanilla shadow scaling shadowRadius *= 3; // undo vanilla shadow scaling

View file

@ -80,7 +80,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
IPony pony = getEntityPony(entity); IPony 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().getShadowSize(); shadowRadius = manager.getModel().getSize().shadowSize();
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);
@ -88,7 +88,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.metadata().getSize().getScaleFactor(); float l = entity.getWidth() / 2 * pony.metadata().size().scaleFactor();
stack.multiply(RotationAxis.NEGATIVE_Y.rotationDegrees(yaw)); stack.multiply(RotationAxis.NEGATIVE_Y.rotationDegrees(yaw));
stack.translate(0, 0, -l); stack.translate(0, 0, -l);
@ -191,7 +191,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
@Override @Override
public Identifier getDefaultTexture(AbstractClientPlayerEntity entity, Wearable wearable) { public Identifier getDefaultTexture(AbstractClientPlayerEntity entity, Wearable wearable) {
return SkinsProxy.instance.getSkin(wearable.getId(), entity).orElseGet(() -> { return SkinsProxy.instance.getSkin(wearable.getId(), entity).orElseGet(() -> {
if (wearable.isSaddlebags() && getInternalRenderer().getModel().getMetadata().getRace().supportsLegacySaddlebags()) { if (wearable.isSaddlebags() && getInternalRenderer().getModel().getMetadata().race().supportsLegacySaddlebags()) {
return getTexture(entity); return getTexture(entity);
} }

View file

@ -3,20 +3,21 @@ package com.minelittlepony.client.render.entity.npc.textures;
import net.minecraft.block.entity.SkullBlockEntity; import net.minecraft.block.entity.SkullBlockEntity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.pony.IPony; import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.client.SkinsProxy; import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.util.FunctionUtil;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Function; 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<T, Entry> customNameCache = FunctionUtil.memoize(Entry::new, entity -> entity.getCustomName().getString() + "_" + entity.getUuidAsString()); Function<String, Entry> customNameCache = Util.memoize(Entry::new);
return entity -> { return entity -> {
Identifier override = entity.hasCustomName() ? customNameCache.apply(entity).getTexture() : null; Identifier override = entity.hasCustomName() ? customNameCache.apply(entity.getCustomName().getString()).getTexture() : null;
if (override != null) { if (override != null) {
return override; return override;
} }
@ -27,8 +28,8 @@ public class PlayerTextureSupplier {
static final class Entry { static final class Entry {
private final CompletableFuture<Identifier> profile; private final CompletableFuture<Identifier> profile;
Entry(LivingEntity entity) { Entry(String name) {
profile = SkullBlockEntity.fetchProfile(entity.getCustomName().getString()).thenApply(profile -> { profile = SkullBlockEntity.fetchProfile(name).thenApply(profile -> {
return profile return profile
.map(p -> SkinsProxy.instance.getSkinTexture(p)) .map(p -> SkinsProxy.instance.getSkinTexture(p))
.filter(skin -> !IPony.getManager().getPony(skin).race().isHuman()) .filter(skin -> !IPony.getManager().getPony(skin).race().isHuman())

View file

@ -2,12 +2,14 @@ package com.minelittlepony.client.render.entity.npc.textures;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import com.minelittlepony.client.MineLittlePony; import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.util.FunctionUtil;
import java.util.Map; import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
/** /**
@ -32,14 +34,14 @@ public interface TextureSupplier<T> extends Function<T, Identifier> {
} }
static <T extends LivingEntity> TextureSupplier<T> ofPool(Identifier poolId, TextureSupplier<T> fallback) { static <T extends LivingEntity> TextureSupplier<T> ofPool(Identifier poolId, TextureSupplier<T> fallback) {
final Function<T, Identifier> cache = FunctionUtil.memoize(entity -> { final BiFunction<String, UUID, Identifier> cache = Util.memoize((name, uuid) -> {
return MineLittlePony.getInstance().getVariatedTextures() return MineLittlePony.getInstance().getVariatedTextures()
.get(poolId) .get(poolId)
.getByName(entity.getCustomName().getString(), entity.getUuid()) .getByName(name, uuid)
.orElse(null); .orElse(null);
}, entity -> entity.getCustomName().getString() + "_" + entity.getUuidAsString()); });
return entity -> { return entity -> {
Identifier override = entity.hasCustomName() ? cache.apply(entity) : null; Identifier override = entity.hasCustomName() ? cache.apply(entity.getCustomName().getString(), entity.getUuid()) : null;
if (override != null) { if (override != null) {
return override; return override;
} }

View file

@ -1,12 +0,0 @@
package com.minelittlepony.util;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
public interface FunctionUtil {
static <A, B> Function<A, B> memoize(Function<A, B> func, Function<A, String> keyFunc) {
final Map<String, B> cache = new ConcurrentHashMap<>();
return a -> cache.computeIfAbsent(keyFunc.apply(a), k -> func.apply(a));
}
}