diff --git a/src/main/java/com/minelittlepony/unicopia/Race.java b/src/main/java/com/minelittlepony/unicopia/Race.java index 6647951f..67c17dd2 100644 --- a/src/main/java/com/minelittlepony/unicopia/Race.java +++ b/src/main/java/com/minelittlepony/unicopia/Race.java @@ -2,12 +2,14 @@ package com.minelittlepony.unicopia; import java.util.*; import java.util.function.Predicate; +import java.util.function.Supplier; import java.util.stream.Collectors; import org.jetbrains.annotations.Nullable; import org.spongepowered.include.com.google.common.base.Objects; import com.google.common.base.Strings; +import com.google.common.base.Suppliers; import com.minelittlepony.unicopia.ability.magic.Affine; import com.minelittlepony.unicopia.util.RegistryUtils; import com.mojang.brigadier.context.CommandContext; @@ -22,7 +24,7 @@ import net.minecraft.util.Identifier; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKey; -public record Race (boolean canCast, FlightType flightType, boolean canUseEarth, boolean isNocturnal, boolean canHang) implements Affine { +public record Race (Supplier compositeSupplier, boolean canCast, FlightType flightType, boolean canUseEarth, boolean isNocturnal, boolean canHang) implements Affine { public static final String DEFAULT_ID = "unicopia:unset"; public static final Registry REGISTRY = RegistryUtils.createDefaulted(Unicopia.id("race"), DEFAULT_ID); public static final RegistryKey> REGISTRY_KEY = REGISTRY.getKey(); @@ -33,7 +35,7 @@ public record Race (boolean canCast, FlightType flightType, boolean canUseEarth, } public static Race register(Identifier id, boolean magic, FlightType flight, boolean earth, boolean nocturnal, boolean canHang) { - return Registry.register(REGISTRY, id, new Race(magic, flight, earth, nocturnal, canHang)); + return Registry.register(REGISTRY, id, new Race(Suppliers.memoize(() -> new Composite(REGISTRY.get(id), null)), magic, flight, earth, nocturnal, canHang)); } public static RegistryKeyArgumentType argument() { @@ -55,6 +57,14 @@ public record Race (boolean canCast, FlightType flightType, boolean canUseEarth, public static void bootstrap() {} + public Composite composite() { + return compositeSupplier.get(); + } + + public Composite composite(@Nullable Race pseudo) { + return pseudo == null ? composite() : new Composite(this, pseudo); + } + @Override public Affinity getAffinity() { return this == CHANGELING ? Affinity.BAD : Affinity.NEUTRAL; @@ -187,8 +197,6 @@ public record Race (boolean canCast, FlightType flightType, boolean canUseEarth, } public record Composite (Race physical, @Nullable Race pseudo) { - public static Composite DEFAULT = new Composite(Race.HUMAN, null); - public Race collapsed() { return pseudo == null ? physical : pseudo; } diff --git a/src/main/java/com/minelittlepony/unicopia/Unicopia.java b/src/main/java/com/minelittlepony/unicopia/Unicopia.java index 899ee06b..a714e97a 100644 --- a/src/main/java/com/minelittlepony/unicopia/Unicopia.java +++ b/src/main/java/com/minelittlepony/unicopia/Unicopia.java @@ -104,7 +104,7 @@ public class Unicopia implements ModInitializer { Optional getPony(); default Race.Composite getPlayerSpecies() { - return getPony().map(Pony::getCompositeRace).orElse(Race.Composite.DEFAULT); + return getPony().map(Pony::getCompositeRace).orElse(Race.HUMAN.composite()); } } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Equine.java b/src/main/java/com/minelittlepony/unicopia/entity/Equine.java index dbfd9295..b7219517 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Equine.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Equine.java @@ -21,7 +21,7 @@ public interface Equine extends NbtSerialisable, Tickable, Pro void setSpecies(Race race); default Race.Composite getCompositeRace() { - return new Race.Composite(getSpecies(), null); + return getSpecies().composite(); } /** diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index 2510770b..5cbc7617 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -94,6 +94,8 @@ public class Pony extends Living implements Copyable, Update private final Interpolator interpolator = new LinearInterpolator(); + @Nullable + private Race.Composite compositeRace; private Race respawnRace = Race.UNSET; private boolean dirty; @@ -203,13 +205,7 @@ public class Pony extends Living implements Copyable, Update * This includes illusions and shape-shifting but excludes items that grant abilities without changing their race. */ public Race getObservedSpecies() { - return getSpellSlot() - .get(SpellPredicate.IS_MIMIC, true) - .map(AbstractDisguiseSpell::getDisguise) - .map(EntityAppearance::getAppearance) - .flatMap(Pony::of) - .map(Pony::getSpecies) - .orElseGet(this::getSpecies); + return getCompositeRace().physical(); } /** @@ -218,11 +214,20 @@ public class Pony extends Living implements Copyable, Update */ @Override public Race.Composite getCompositeRace() { - return new Race.Composite(getObservedSpecies(), - AmuletSelectors.UNICORN_AMULET.test(entity) ? Race.UNICORN - : AmuletSelectors.ALICORN_AMULET.test(entity) ? Race.ALICORN - : null - ); + if (compositeRace == null || entity.age % 2 == 0) { + compositeRace = getSpellSlot() + .get(SpellPredicate.IS_MIMIC, true) + .map(AbstractDisguiseSpell::getDisguise) + .map(EntityAppearance::getAppearance) + .flatMap(Pony::of) + .map(Pony::getSpecies) + .orElseGet(this::getSpecies).composite( + AmuletSelectors.UNICORN_AMULET.test(entity) ? Race.UNICORN + : AmuletSelectors.ALICORN_AMULET.test(entity) ? Race.ALICORN + : null + ); + } + return compositeRace; } @Override