Change mixed humans skins option to a dual skin mode and add a priority trigger pixel to facilitate skin sorting

This commit is contained in:
Sollace 2023-09-27 02:00:18 +01:00
parent 6013fa2ad5
commit 24a8afc508
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
6 changed files with 44 additions and 25 deletions

View file

@ -54,10 +54,11 @@ public class PonyConfig extends Config {
.addComment("Helps to prevent entities from vanishing when they're in long stacks"); .addComment("Helps to prevent entities from vanishing when they're in long stacks");
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<Boolean> mixedHumanSkins = value("settings", "mixedHumanSkins", false) public final Setting<Boolean> mixedHumanSkins = value("settings", "dualSkinMode", false)
.addComment("(Experimental) When displaying humans, use mojang's skin server instead.") .addComment("(Experimental) Use priority to decide between displaying the HDSkins' texture, or vanilla mojang server skin")
.addComment("(Experimental) Only takes effect on pony level = HUMANS") .addComment("(Experimental) eg. On pony level = HUMANS")
.addComment("(Experimental) Will cause the vanilla skin to show if the hd skin is a pony skin"); .addComment("(Experimental) Any time both skins resolve to the same race (eg. on pony-level HUMANS, or if both are ponies)")
.addComment("(Experimental) the skin with the highest priority will be chosen.");;
public final Setting<SizePreset> sizeOverride = value("debug", "sizeOverride", SizePreset.UNSET) public final Setting<SizePreset> sizeOverride = value("debug", "sizeOverride", SizePreset.UNSET)
.addComment("Overrides pony sizes") .addComment("Overrides pony sizes")

View file

@ -23,6 +23,7 @@ public class MsgPonyData {
new MsgSize(buffer), new MsgSize(buffer),
buffer.readInt(), buffer.readInt(),
buffer.readBoolean(), buffer.readBoolean(),
buffer.readVarInt(),
Flags.read(Wearable.NONE, buffer) Flags.read(Wearable.NONE, buffer)
); );
} }
@ -34,6 +35,7 @@ public class MsgPonyData {
buffer.writeEnumConstant(data.tailLength()); buffer.writeEnumConstant(data.tailLength());
buffer.writeEnumConstant(data.tailShape()); buffer.writeEnumConstant(data.tailShape());
buffer.writeEnumConstant(data.gender()); buffer.writeEnumConstant(data.gender());
buffer.writeVarInt(data.priority());
new MsgSize(data.size()).toBuffer(buffer); new MsgSize(data.size()).toBuffer(buffer);
buffer.writeInt(data.glowColor()); buffer.writeInt(data.glowColor());
buffer.writeBoolean(data.noSkin()); buffer.writeBoolean(data.noSkin());

View file

@ -49,13 +49,25 @@ public record PonyData (
* rather than a user-uploaded one. * rather than a user-uploaded one.
*/ */
boolean noSkin, boolean noSkin,
/**
* (Experimental) Priority.
* Used to decide which skin to use when dual skin mode is active.
* Provides an optional tie-breaker when the client has to decide between displaying
* either the HDSkins texture or vanilla texture given both are otherwise acceptable.
*
* Any time both skins resolve to the same race (eg. on pony-level HUMANS, or if both are ponies)
* the skin with the highest priority will be chosen.
*
* If both have the same priority, HD Skins' texture will always be used (old default).
*/
int priority,
/** /**
* 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, TValue<?>> attributes Map<String, TValue<?>> attributes
) implements Comparable<PonyData> { ) implements Comparable<PonyData> {
public static final int DEFAULT_MAGIC_COLOR = 0x4444aa; public static final int DEFAULT_MAGIC_COLOR = 0x4444aa;
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)); 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, 0, Wearable.EMPTY_FLAGS));
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) {
@ -71,18 +83,20 @@ public record PonyData (
TriggerPixel.SIZE.read(image), TriggerPixel.SIZE.read(image),
TriggerPixel.GLOW.read(image), TriggerPixel.GLOW.read(image),
noSkin, noSkin,
TriggerPixel.PRIORITY.read(image),
TriggerPixel.WEARABLES.read(image) TriggerPixel.WEARABLES.read(image)
); );
} }
public PonyData(Race race, TailLength tailLength, TailShape tailShape, Gender gender, Size size, int glowColor, boolean noSkin, Flags<Wearable> wearables) { public PonyData(Race race, TailLength tailLength, TailShape tailShape, Gender gender, Size size, int glowColor, boolean noSkin, int priority, Flags<Wearable> wearables) {
this(race, tailLength, tailShape, gender, size, glowColor, wearables, noSkin, Util.make(new TreeMap<>(), map -> { this(race, tailLength, tailShape, gender, size, glowColor, wearables, noSkin, priority, Util.make(new TreeMap<>(), map -> {
map.put("race", race); map.put("race", race);
map.put("tailLength", tailLength); map.put("tailLength", tailLength);
map.put("tailShape", tailShape); map.put("tailShape", tailShape);
map.put("gender", gender); map.put("gender", gender);
map.put("size", size); map.put("size", size);
map.put("magic", new TValue.Numeric(glowColor)); map.put("magic", new TValue.Numeric(glowColor));
map.put("priority", new TValue.Numeric(priority));
map.put("gear", wearables); map.put("gear", wearables);
}) })
); );

View file

@ -22,6 +22,7 @@ public interface TriggerPixel<T> {
TriggerPixel<Size> SIZE = ofOptions(3, 0, SizePreset.NORMAL, SizePreset.values()); TriggerPixel<Size> SIZE = ofOptions(3, 0, SizePreset.NORMAL, SizePreset.values());
TriggerPixel<Integer> GLOW = ofColor(0, 1); TriggerPixel<Integer> GLOW = ofColor(0, 1);
TriggerPixel<Flags<Wearable>> WEARABLES = ofFlags(1, 1, Wearable.EMPTY_FLAGS, Wearable.values()); TriggerPixel<Flags<Wearable>> WEARABLES = ofFlags(1, 1, Wearable.EMPTY_FLAGS, Wearable.values());
TriggerPixel<Integer> PRIORITY = ofColor(2, 2);
static <T extends TValue<T>> TriggerPixel<T> ofOptions(int x, int y, T def, T[] options) { 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.x = Math.max(MAX_COORDS.x, x);

View file

@ -61,9 +61,12 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
HDSkins.getInstance().getSkinPrioritySorter().addSelector((skinType, playerSkins) -> { HDSkins.getInstance().getSkinPrioritySorter().addSelector((skinType, playerSkins) -> {
if (skinType == SkinType.SKIN && PonyConfig.getInstance().mixedHumanSkins.get()) { if (skinType == SkinType.SKIN && PonyConfig.getInstance().mixedHumanSkins.get()) {
PonyLevel level = PonyConfig.getInstance().ponyLevel.get(); Optional<Pony> hdPony = getPony(playerSkins.hd());
Optional<Pony> vanillaPony = getPony(playerSkins.vanilla());
if (level == PonyLevel.HUMANS && isPony(playerSkins.hd()) && !isPony(playerSkins.vanilla())) { if (hdPony.isPresent() && vanillaPony.isPresent()
&& vanillaPony.get().metadata().priority() > hdPony.get().metadata().priority()
&& (PonyConfig.getInstance().ponyLevel.get() == PonyLevel.HUMANS || vanillaPony.get().metadata().race().isHuman() == hdPony.get().metadata().race().isHuman())) {
return playerSkins.vanilla(); return playerSkins.vanilla();
} }
} }
@ -71,12 +74,10 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
}); });
} }
static boolean isPony(PlayerSkins.Layer layer) { static Optional<Pony> getPony(PlayerSkins.Layer layer) {
return layer return layer
.getSkin(SkinType.SKIN) .getSkin(SkinType.SKIN)
.map(Pony.getManager()::getPony) .map(Pony.getManager()::getPony);
.filter(pony -> !pony.metadata().race().isHuman())
.isPresent();
} }
@Override @Override

View file

@ -23,7 +23,7 @@
"minelp.options.flappyelytras": "Flap Wings whilst Gliding", "minelp.options.flappyelytras": "Flap Wings whilst Gliding",
"minelp.options.horsiemode": "Horsey Horse Mode", "minelp.options.horsiemode": "Horsey Horse Mode",
"minelp.options.nofun": "Boring Mode", "minelp.options.nofun": "Boring Mode",
"minelp.options.mixedhumanskins": "(Experimental) Vanilla Humans", "minelp.options.dualskinmode": "(Experimental) Dual Skin Mode",
"minelp.options.button": "Display On Title Screen", "minelp.options.button": "Display On Title Screen",
"minelp.options.button.on": "Always Display\n\nBoth the pony button and HD Skins button are visible (if installed)", "minelp.options.button.on": "Always Display\n\nBoth the pony button and HD Skins button are visible (if installed)",
"minelp.options.button.auto": "Display only when HD Skins is not installed", "minelp.options.button.auto": "Display only when HD Skins is not installed",