From 95ffe5b0b5836bc4c343ffe43c837d5b3f951b0d Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 18 May 2024 14:29:47 +0100 Subject: [PATCH] Serialize spell type and traits together, and make affinity names translatable --- .../com/minelittlepony/unicopia/Affinity.java | 11 +- .../ability/UnicornCastingAbility.java | 4 +- .../magic/spell/AbstractDelegatingSpell.java | 19 +-- .../ability/magic/spell/PlaceableSpell.java | 4 +- .../unicopia/ability/magic/spell/Spell.java | 32 ++--- .../ability/magic/spell/SpellReference.java | 2 +- .../magic/spell/effect/AbstractSpell.java | 18 +-- .../spell/effect/CustomisedSpellType.java | 33 +++-- .../ability/magic/spell/effect/SpellType.java | 136 +++++++++++++----- .../client/gui/DismissSpellScreen.java | 17 +-- .../client/render/HornFeatureRenderer.java | 2 +- .../entity/MagicBeamEntityRenderer.java | 2 +- .../render/spell/PlacedSpellRenderer.java | 2 +- .../render/spell/ShieldSpellRenderer.java | 2 +- .../spell/SpellEffectsRenderDispatcher.java | 6 +- .../client/render/spell/SpellRenderer.java | 2 +- .../entity/player/PlayerCharmTracker.java | 2 +- .../unicopia/entity/player/Pony.java | 2 +- .../unicopia/item/EnchantedStaffItem.java | 6 +- .../unicopia/server/world/Ether.java | 12 +- .../resources/assets/unicopia/lang/en_us.json | 4 + 21 files changed, 188 insertions(+), 130 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/Affinity.java b/src/main/java/com/minelittlepony/unicopia/Affinity.java index e1c4e3a9..724cbdc4 100644 --- a/src/main/java/com/minelittlepony/unicopia/Affinity.java +++ b/src/main/java/com/minelittlepony/unicopia/Affinity.java @@ -2,8 +2,10 @@ package com.minelittlepony.unicopia; import java.util.Locale; +import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.StringIdentifiable; +import net.minecraft.util.Util; public enum Affinity implements StringIdentifiable { GOOD(Formatting.BLUE, -1, 0), @@ -20,10 +22,13 @@ public enum Affinity implements StringIdentifiable { public static final Affinity[] VALUES = values(); + private final String translationKey; + Affinity(Formatting color, int corruption, float alignment) { this.color = color; this.corruption = corruption; this.alignment = alignment; + this.translationKey = Util.createTranslationKey("affinity", Unicopia.id(name().toLowerCase(Locale.ROOT))); } @Override @@ -36,7 +41,11 @@ public enum Affinity implements StringIdentifiable { } public String getTranslationKey() { - return this == BAD ? "curse" : "spell"; + return translationKey; + } + + public Text getDisplayName() { + return Text.translatable(getTranslationKey()); } public int getCorruption() { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java index fae2d49c..d47f098d 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java @@ -108,9 +108,7 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility { } boolean hasExact = player.getSpellSlot().contains(spell); - boolean removed = player.getSpellSlot().removeWhere(s -> { - return s.findMatches(spell.type()).findAny().isPresent() && (spell.isEmpty() || !SpellType.PLACED_SPELL.test(s)); - }, true); + boolean removed = !spell.isStackable() && player.getSpellSlot().removeWhere(s -> s.findMatches(spell.type()).findAny().isPresent(), true); player.subtractEnergyCost(removed ? 2 : 4); if (!hasExact && !spell.isEmpty()) { Spell s = spell.apply(player, CastingMethod.DIRECT); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java index 68a006ed..c27fb13c 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java @@ -5,11 +5,8 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; -import com.minelittlepony.unicopia.Affinity; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; -import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; -import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.ProjectileDelegate; @@ -26,10 +23,10 @@ public abstract class AbstractDelegatingSpell implements Spell, private UUID uuid = UUID.randomUUID(); - private final SpellType type; + private final CustomisedSpellType type; public AbstractDelegatingSpell(CustomisedSpellType type) { - this.type = type.type(); + this.type = type; } public abstract Collection getDelegates(); @@ -45,20 +42,10 @@ public abstract class AbstractDelegatingSpell implements Spell, } @Override - public Affinity getAffinity() { - return Affinity.NEUTRAL; - } - - @Override - public SpellType getType() { + public CustomisedSpellType getTypeAndTraits() { return type; } - @Override - public SpellTraits getTraits() { - return getDelegates().stream().map(Spell::getTraits).reduce(SpellTraits.EMPTY, SpellTraits::union); - } - @Override public final UUID getUuid() { return uuid; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java index 1eb59540..ab724eaa 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java @@ -154,7 +154,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS } private void checkDetachment(Caster source, EntityValues target) { - if (getWorld(source).map(Ether::get).map(ether -> ether.get(getType(), target, placedSpellId)).isEmpty()) { + if (getWorld(source).map(Ether::get).map(ether -> ether.get(getTypeAndTraits().type(), target, placedSpellId)).isEmpty()) { setDead(); } } @@ -202,7 +202,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS if (!source.isClient()) { castEntity.getTarget().ifPresent(target -> { getWorld(source).map(Ether::get) - .ifPresent(ether -> ether.remove(getType(), target.uuid())); + .ifPresent(ether -> ether.remove(getTypeAndTraits().type(), target.uuid())); }); castEntity.set(null); getSpellEntity(source).ifPresent(e -> { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java index 0c504041..30a93dd2 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java @@ -7,11 +7,12 @@ import java.util.stream.Stream; import org.jetbrains.annotations.Nullable; import org.spongepowered.include.com.google.common.base.Objects; +import com.minelittlepony.unicopia.Affinity; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.ability.magic.Affine; import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; -import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.util.NbtSerialisable; import net.minecraft.nbt.NbtCompound; @@ -24,14 +25,18 @@ public interface Spell extends NbtSerialisable, Affine { Serializer SERIALIZER = Serializer.of(Spell::readNbt, Spell::writeNbt); /** - * Returns the registered type of this spell. + * Returns the full type that describes this spell. */ - SpellType getType(); + CustomisedSpellType getTypeAndTraits(); - /** - * Gets the traits of this spell. - */ - SpellTraits getTraits(); + default boolean isOf(SpellType type) { + return getTypeAndTraits().type() == type; + } + + @Override + default Affinity getAffinity() { + return getTypeAndTraits().type().getAffinity(); + } /** * The unique id of this particular spell instance. @@ -132,15 +137,8 @@ public interface Spell extends NbtSerialisable, Affine { @Nullable static T readNbt(@Nullable NbtCompound compound) { try { - if (compound != null && compound.contains("effect_id")) { - @SuppressWarnings("unchecked") - T effect = (T)SpellType.getKey(compound).withTraits().create(); - - if (effect != null) { - effect.fromNBT(compound); - } - - return effect; + if (compound != null) { + return CustomisedSpellType.fromNBT(compound).create(compound); } } catch (Exception e) { Unicopia.LOGGER.fatal("Invalid spell nbt {}", e); @@ -155,7 +153,7 @@ public interface Spell extends NbtSerialisable, Affine { static NbtCompound writeNbt(Spell effect) { NbtCompound compound = effect.toNBT(); - effect.getType().toNbt(compound); + effect.getTypeAndTraits().toNbt(compound); return compound; } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellReference.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellReference.java index cca32178..97152693 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellReference.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellReference.java @@ -44,7 +44,7 @@ public final class SpellReference implements NbtSerialisable { public void toNBT(NbtCompound compound) { if (spell != null && !spell.isDead()) { spell.toNBT(compound); - spell.getType().toNbt(compound); + spell.getTypeAndTraits().type().toNbt(compound); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java index 1660c01e..ada82e85 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java @@ -2,7 +2,6 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; import java.util.UUID; -import com.minelittlepony.unicopia.Affinity; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; @@ -17,7 +16,7 @@ public abstract class AbstractSpell implements Spell { private boolean hidden; private boolean destroyed; - private CustomisedSpellType type; + private final CustomisedSpellType type; private UUID uuid = UUID.randomUUID(); @@ -30,17 +29,16 @@ public abstract class AbstractSpell implements Spell { return uuid; } - @Override - public final SpellType getType() { + protected final SpellType getType() { return type.type(); } + @Override public final CustomisedSpellType getTypeAndTraits() { return type; } - @Override - public final SpellTraits getTraits() { + protected final SpellTraits getTraits() { return type.traits(); } @@ -80,11 +78,6 @@ public abstract class AbstractSpell implements Spell { this.hidden = hidden; } - @Override - public Affinity getAffinity() { - return getType().getAffinity(); - } - protected void onDestroyed(Caster caster) { } @@ -121,9 +114,6 @@ public abstract class AbstractSpell implements Spell { dying = compound.getBoolean("dying"); dead = compound.getBoolean("dead"); hidden = compound.getBoolean("hidden"); - if (compound.contains("traits")) { - type = type.type().withTraits(SpellTraits.fromNbt(compound.getCompound("traits")).orElse(SpellTraits.EMPTY)); - } } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java index 4c346401..bd0e73e8 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java @@ -21,6 +21,10 @@ public record CustomisedSpellType ( return type.isEmpty(); } + public boolean isStackable() { + return type().isStackable(); + } + public T create() { try { return type.getFactory().create(this); @@ -31,6 +35,14 @@ public record CustomisedSpellType ( return null; } + @Nullable + public T create(NbtCompound compound) { + T spell = create(); + if (spell != null) { + spell.fromNBT(compound); + } + return spell; + } @Nullable public T apply(Caster caster, CastingMethod method) { @@ -50,8 +62,8 @@ public record CustomisedSpellType ( } @Override - public boolean test(Spell spell) { - return type.test(spell) && spell.getTraits().equals(traits); + public boolean test(@Nullable Spell spell) { + return spell != null && spell.getTypeAndTraits().equals(this); } public ItemStack getDefaultStack() { @@ -62,17 +74,14 @@ public record CustomisedSpellType ( return isEmpty() ? TypedActionResult.fail(this) : TypedActionResult.pass(this); } - public NbtCompound toNBT() { - NbtCompound tag = new NbtCompound(); - type.toNbt(tag); - tag.put("traits", traits.toNbt()); - return tag; + public NbtCompound toNbt(NbtCompound compound) { + type.toNbt(compound); + compound.put("traits", traits.toNbt()); + return compound; } - public static CustomisedSpellType fromNBT(NbtCompound compound) { - SpellType type = SpellType.getKey(compound); - SpellTraits traits = SpellTraits.fromNbt(compound.getCompound("traits")).orElse(type.getTraits()); - - return type.withTraits(traits); + public static CustomisedSpellType fromNBT(NbtCompound compound) { + SpellType type = SpellType.getKey(compound); + return type.withTraits(SpellTraits.fromNbt(compound.getCompound("traits")).orElse(type.getTraits())); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java index e963c0e7..c73def7c 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java @@ -34,47 +34,47 @@ import net.minecraft.server.command.ServerCommandSource; public final class SpellType implements Affine, SpellPredicate { public static final Identifier EMPTY_ID = Unicopia.id("none"); - public static final SpellType EMPTY_KEY = new SpellType<>(EMPTY_ID, Affinity.NEUTRAL, 0xFFFFFF, false, GemstoneItem.Shape.ROUND, SpellTraits.EMPTY, t -> null); + public static final SpellType EMPTY_KEY = new SpellType<>(EMPTY_ID, Affinity.NEUTRAL, 0xFFFFFF, false, false, GemstoneItem.Shape.ROUND, SpellTraits.EMPTY, t -> null); public static final Registry> REGISTRY = RegistryUtils.createSimple(Unicopia.id("spells")); public static final RegistryKey>> REGISTRY_KEY = REGISTRY.getKey(); private static final DynamicCommandExceptionType UNKNOWN_SPELL_TYPE_EXCEPTION = new DynamicCommandExceptionType(id -> Text.translatable("spell_type.unknown", id)); - public static final SpellType PLACED_SPELL = register("placed", Affinity.NEUTRAL, 0, false, GemstoneItem.Shape.DONUT, SpellTraits.EMPTY, PlaceableSpell::new); - public static final SpellType THROWN_SPELL = register("thrown", Affinity.NEUTRAL, 0, false, GemstoneItem.Shape.DONUT, SpellTraits.EMPTY, ThrowableSpell::new); + public static final SpellType PLACED_SPELL = register("placed", builder(PlaceableSpell::new).affinity(Affinity.NEUTRAL).unobtainable().stackable().shape(GemstoneItem.Shape.DONUT)); + public static final SpellType THROWN_SPELL = register("thrown", builder(ThrowableSpell::new).affinity(Affinity.NEUTRAL).unobtainable().shape(GemstoneItem.Shape.DONUT)); - public static final SpellType CHANGELING_DISGUISE = register("disguise", Affinity.BAD, 0x19E48E, false, GemstoneItem.Shape.ARROW, SpellTraits.EMPTY, DispersableDisguiseSpell::new); - public static final SpellType FEED = register("feed", Affinity.BAD, 0xBDBDF9, false, GemstoneItem.Shape.ARROW, SpellTraits.EMPTY, ChangelingFeedingSpell::new); - public static final SpellType RAINBOOM = register("rainboom", Affinity.GOOD, 0xBDBDF9, false, GemstoneItem.Shape.ROCKET, SpellTraits.EMPTY, RainboomAbilitySpell::new); - public static final SpellType RAGE = register("rage", Affinity.GOOD, 0xBDBDF9, false, GemstoneItem.Shape.FLAME, SpellTraits.EMPTY, RageAbilitySpell::new); - public static final SpellType TIME_CONTROL = register("time_control", Affinity.GOOD, 0xBDBDF9, false, GemstoneItem.Shape.STAR, SpellTraits.EMPTY, TimeControlAbilitySpell::new); + public static final SpellType CHANGELING_DISGUISE = register("disguise", builder(DispersableDisguiseSpell::new).affinity(Affinity.BAD).color(0x19E48E).unobtainable().shape(GemstoneItem.Shape.ARROW)); + public static final SpellType FEED = register("feed", SpellType.builder(ChangelingFeedingSpell::new).affinity(Affinity.BAD).color(0xBDBDF9).unobtainable().shape(GemstoneItem.Shape.ARROW)); + public static final SpellType RAINBOOM = register("rainboom", builder(RainboomAbilitySpell::new).color(0xBDBDF9).unobtainable().shape(GemstoneItem.Shape.ROCKET)); + public static final SpellType RAGE = register("rage", builder(RageAbilitySpell::new).color(0xBDBDF9).unobtainable().shape(GemstoneItem.Shape.FLAME)); + public static final SpellType TIME_CONTROL = register("time_control", builder(TimeControlAbilitySpell::new).color(0xBDBDF9).unobtainable().shape(GemstoneItem.Shape.STAR)); - public static final SpellType FROST = register("frost", Affinity.GOOD, 0xEABBFF, true, GemstoneItem.Shape.TRIANGLE, IceSpell.DEFAULT_TRAITS, IceSpell::new); - public static final SpellType CHILLING_BREATH = register("chilling_breath", Affinity.NEUTRAL, 0xFFEAFF, true, GemstoneItem.Shape.TRIANGLE, ChillingBreathSpell.DEFAULT_TRAITS, ChillingBreathSpell::new); - public static final SpellType SCORCH = register("scorch", Affinity.BAD, 0xF8EC1F, true, GemstoneItem.Shape.FLAME, ScorchSpell.DEFAULT_TRAITS, ScorchSpell::new); - public static final SpellType FLAME = register("flame", Affinity.GOOD, 0xFFBB99, true, GemstoneItem.Shape.FLAME, FireSpell.DEFAULT_TRAITS, FireSpell::new); - public static final SpellType INFERNAL = register("infernal", Affinity.BAD, 0xFFAA00, true, GemstoneItem.Shape.FLAME, InfernoSpell.DEFAULT_TRAITS, InfernoSpell::new); - public static final SpellType SHIELD = register("shield", Affinity.NEUTRAL, 0x66CDAA, true, GemstoneItem.Shape.SHIELD, ShieldSpell.DEFAULT_TRAITS, ShieldSpell::new); - public static final SpellType ARCANE_PROTECTION = register("arcane_protection", Affinity.BAD, 0x99CDAA, true, GemstoneItem.Shape.SHIELD, AreaProtectionSpell.DEFAULT_TRAITS, AreaProtectionSpell::new); - public static final SpellType VORTEX = register("vortex", Affinity.NEUTRAL, 0xFFEA88, true, GemstoneItem.Shape.VORTEX, AttractiveSpell.DEFAULT_TRAITS, AttractiveSpell::new); - public static final SpellType DARK_VORTEX = register("dark_vortex", Affinity.BAD, 0xA33333, true, GemstoneItem.Shape.VORTEX, DarkVortexSpell.DEFAULT_TRAITS, DarkVortexSpell::new); - public static final SpellType NECROMANCY = register("necromancy", Affinity.BAD, 0xFA3A3A, true, GemstoneItem.Shape.SKULL, SpellTraits.EMPTY, NecromancySpell::new); - public static final SpellType SIPHONING = register("siphoning", Affinity.NEUTRAL, 0xFFA3AA, true, GemstoneItem.Shape.LAMBDA, SpellTraits.EMPTY, SiphoningSpell::new); - public static final SpellType REVEALING = register("reveal", Affinity.GOOD, 0xFFFFAF, true, GemstoneItem.Shape.CROSS, SpellTraits.EMPTY, DisperseIllusionSpell::new); - public static final SpellType AWKWARD = register("awkward", Affinity.GOOD, 0x3A59FF, true, GemstoneItem.Shape.ICE, SpellTraits.EMPTY, AwkwardSpell::new); - public static final SpellType TRANSFORMATION = register("transformation", Affinity.GOOD, 0x19E48E, true, GemstoneItem.Shape.BRUSH, SpellTraits.EMPTY, TransformationSpell::new); - public static final SpellType FEATHER_FALL = register("feather_fall", Affinity.GOOD, 0x00EEFF, true, GemstoneItem.Shape.LAMBDA, FeatherFallSpell.DEFAULT_TRAITS, FeatherFallSpell::new); - public static final SpellType CATAPULT = register("catapult", Affinity.GOOD, 0x22FF00, true, GemstoneItem.Shape.ROCKET, CatapultSpell.DEFAULT_TRAITS, CatapultSpell::new); - public static final SpellType FIRE_BOLT = register("fire_bolt", Affinity.GOOD, 0xFF8811, true, GemstoneItem.Shape.FLAME, FireBoltSpell.DEFAULT_TRAITS, FireBoltSpell::new); - public static final SpellType LIGHT = register("light", Affinity.GOOD, 0xEEFFAA, true, GemstoneItem.Shape.STAR, LightSpell.DEFAULT_TRAITS, LightSpell::new); - public static final SpellType DISPLACEMENT = register("displacement", Affinity.NEUTRAL, 0x9900FF, true, GemstoneItem.Shape.BRUSH, PortalSpell.DEFAULT_TRAITS, DisplacementSpell::new); - public static final SpellType PORTAL = register("portal", Affinity.GOOD, 0x99FFFF, true, GemstoneItem.Shape.RING, PortalSpell.DEFAULT_TRAITS, PortalSpell::new); - public static final SpellType MIMIC = register("mimic", Affinity.GOOD, 0xFFFF00, true, GemstoneItem.Shape.ARROW, SpellTraits.EMPTY, MimicSpell::new); - public static final SpellType MIND_SWAP = register("mind_swap", Affinity.BAD, 0xF9FF99, true, GemstoneItem.Shape.WAVE, SpellTraits.EMPTY, MindSwapSpell::new); - public static final SpellType HYDROPHOBIC = register("hydrophobic", Affinity.NEUTRAL, 0xF999FF, true, GemstoneItem.Shape.ROCKET, SpellTraits.EMPTY, s -> new HydrophobicSpell(s, FluidTags.WATER)); - public static final SpellType BUBBLE = register("bubble", Affinity.NEUTRAL, 0xF999FF, true, GemstoneItem.Shape.DONUT, BubbleSpell.DEFAULT_TRAITS, BubbleSpell::new); - public static final SpellType DISPEL_EVIL = register("dispel_evil", Affinity.GOOD, 0x00FF00, true, GemstoneItem.Shape.CROSS, DispellEvilSpell.DEFAULT_TRAITS, DispellEvilSpell::new); + public static final SpellType FROST = register("frost", builder(IceSpell::new).color(0xEABBFF).shape(GemstoneItem.Shape.TRIANGLE).traits(IceSpell.DEFAULT_TRAITS)); + public static final SpellType CHILLING_BREATH = register("chilling_breath", builder(ChillingBreathSpell::new).affinity(Affinity.NEUTRAL).color(0xFFEAFF).shape(GemstoneItem.Shape.TRIANGLE).traits(ChillingBreathSpell.DEFAULT_TRAITS)); + public static final SpellType SCORCH = register("scorch", builder(ScorchSpell::new).affinity(Affinity.BAD).color(0xF8EC1F).shape(GemstoneItem.Shape.FLAME).traits(ScorchSpell.DEFAULT_TRAITS)); + public static final SpellType FLAME = register("flame", builder(FireSpell::new).color(0xFFBB99).shape(GemstoneItem.Shape.FLAME).traits(FireSpell.DEFAULT_TRAITS)); + public static final SpellType INFERNAL = register("infernal", builder(InfernoSpell::new).affinity(Affinity.BAD).color(0xFFAA00).shape(GemstoneItem.Shape.FLAME).traits(InfernoSpell.DEFAULT_TRAITS)); + public static final SpellType SHIELD = register("shield", builder(ShieldSpell::new).affinity(Affinity.NEUTRAL).color(0x66CDAA).shape(GemstoneItem.Shape.SHIELD).traits(ShieldSpell.DEFAULT_TRAITS)); + public static final SpellType ARCANE_PROTECTION = register("arcane_protection", builder(AreaProtectionSpell::new).affinity(Affinity.BAD).color(0x99CDAA).shape(GemstoneItem.Shape.SHIELD).traits(AreaProtectionSpell.DEFAULT_TRAITS)); + public static final SpellType VORTEX = register("vortex", builder(AttractiveSpell::new).affinity(Affinity.NEUTRAL).color(0xFFEA88).shape(GemstoneItem.Shape.VORTEX).traits(AttractiveSpell.DEFAULT_TRAITS)); + public static final SpellType DARK_VORTEX = register("dark_vortex", builder(DarkVortexSpell::new).affinity(Affinity.BAD).color(0xA33333).shape(GemstoneItem.Shape.VORTEX).traits(DarkVortexSpell.DEFAULT_TRAITS)); + public static final SpellType NECROMANCY = register("necromancy", builder(NecromancySpell::new).affinity(Affinity.BAD).color(0xFA3A3A).shape(GemstoneItem.Shape.SKULL)); + public static final SpellType SIPHONING = register("siphoning", builder(SiphoningSpell::new).affinity(Affinity.NEUTRAL).color(0xFFA3AA).shape(GemstoneItem.Shape.LAMBDA)); + public static final SpellType REVEALING = register("reveal", builder(DisperseIllusionSpell::new).color(0xFFFFAF).shape(GemstoneItem.Shape.CROSS)); + public static final SpellType AWKWARD = register("awkward", builder(AwkwardSpell::new).affinity(Affinity.NEUTRAL).color(0x3A59FF).shape(GemstoneItem.Shape.ICE)); + public static final SpellType TRANSFORMATION = register("transformation", builder(TransformationSpell::new).color(0x19E48E).shape(GemstoneItem.Shape.BRUSH)); + public static final SpellType FEATHER_FALL = register("feather_fall", builder(FeatherFallSpell::new).color(0x00EEFF).shape(GemstoneItem.Shape.LAMBDA).traits(FeatherFallSpell.DEFAULT_TRAITS)); + public static final SpellType CATAPULT = register("catapult", builder(CatapultSpell::new).color(0x22FF00).shape(GemstoneItem.Shape.ROCKET).traits(CatapultSpell.DEFAULT_TRAITS)); + public static final SpellType FIRE_BOLT = register("fire_bolt", builder(FireBoltSpell::new).color(0xFF8811).shape(GemstoneItem.Shape.FLAME).traits(FireBoltSpell.DEFAULT_TRAITS)); + public static final SpellType LIGHT = register("light", builder(LightSpell::new).color(0xEEFFAA).shape(GemstoneItem.Shape.STAR).traits(LightSpell.DEFAULT_TRAITS)); + public static final SpellType DISPLACEMENT = register("displacement", builder(DisplacementSpell::new).affinity(Affinity.NEUTRAL).color(0x9900FF).shape(GemstoneItem.Shape.BRUSH).traits(PortalSpell.DEFAULT_TRAITS)); + public static final SpellType PORTAL = register("portal", builder(PortalSpell::new).color(0x99FFFF).shape(GemstoneItem.Shape.RING).traits(PortalSpell.DEFAULT_TRAITS)); + public static final SpellType MIMIC = register("mimic", builder(MimicSpell::new).color(0xFFFF00).shape(GemstoneItem.Shape.ARROW)); + public static final SpellType MIND_SWAP = register("mind_swap", builder(MindSwapSpell::new).affinity(Affinity.BAD).color(0xF9FF99).shape(GemstoneItem.Shape.WAVE)); + public static final SpellType HYDROPHOBIC = register("hydrophobic", SpellType.builder(s -> new HydrophobicSpell(s, FluidTags.WATER)).affinity(Affinity.NEUTRAL).color(0xF999FF).shape(GemstoneItem.Shape.ROCKET)); + public static final SpellType BUBBLE = register("bubble", builder(BubbleSpell::new).affinity(Affinity.NEUTRAL).color(0xF999FF).shape(GemstoneItem.Shape.DONUT).traits(BubbleSpell.DEFAULT_TRAITS)); + public static final SpellType DISPEL_EVIL = register("dispel_evil", builder(DispellEvilSpell::new).color(0x00FF00).shape(GemstoneItem.Shape.CROSS).traits(DispellEvilSpell.DEFAULT_TRAITS)); public static void bootstrap() {} @@ -82,6 +82,7 @@ public final class SpellType implements Affine, SpellPredicate< private final Affinity affinity; private final int color; private final boolean obtainable; + private final boolean stackable; private final GemstoneItem.Shape shape; private final Factory factory; @@ -94,7 +95,7 @@ public final class SpellType implements Affine, SpellPredicate< private final ItemStack defaultStack; - private SpellType(Identifier id, Affinity affinity, int color, boolean obtainable, GemstoneItem.Shape shape, SpellTraits traits, Factory factory) { + private SpellType(Identifier id, Affinity affinity, int color, boolean obtainable, boolean stackable, GemstoneItem.Shape shape, SpellTraits traits, Factory factory) { this.id = id; this.affinity = affinity; this.color = color; @@ -102,6 +103,7 @@ public final class SpellType implements Affine, SpellPredicate< this.shape = shape; this.factory = factory; this.traits = traits; + this.stackable = stackable; traited = new CustomisedSpellType<>(this, traits); defaultStack = UItems.GEMSTONE.getDefaultStack(this); } @@ -110,6 +112,10 @@ public final class SpellType implements Affine, SpellPredicate< return obtainable; } + public boolean isStackable() { + return stackable; + } + public Identifier getId() { return id; } @@ -163,7 +169,7 @@ public final class SpellType implements Affine, SpellPredicate< @Override public boolean test(@Nullable Spell spell) { - return spell != null && spell.getType() == this; + return spell != null && spell.getTypeAndTraits().type() == this; } public void toNbt(NbtCompound tag) { @@ -179,12 +185,12 @@ public final class SpellType implements Affine, SpellPredicate< return "SpellType[" + getTranslationKey() + "]"; } - public static SpellType register(String name, Affinity affinity, int color, boolean obtainable, GemstoneItem.Shape shape, SpellTraits traits, Factory factory) { - return register(Unicopia.id(name), affinity, color, obtainable, shape, traits, factory); + public static SpellType register(String name, Builder builder) { + return register(Unicopia.id(name), builder); } - public static SpellType register(Identifier id, Affinity affinity, int color, boolean obtainable, GemstoneItem.Shape shape, SpellTraits traits, Factory factory) { - return Registry.register(REGISTRY, id, new SpellType<>(id, affinity, color, obtainable, shape, traits, factory)); + public static SpellType register(Identifier id, Builder builder) { + return Registry.register(REGISTRY, id, builder.build(id)); } @SuppressWarnings("unchecked") @@ -209,4 +215,56 @@ public final class SpellType implements Affine, SpellPredicate< public interface Factory { T create(CustomisedSpellType type); } + + public static Builder builder(Factory factory) { + return new Builder<>(factory); + } + + static class Builder { + private final Factory factory; + private Affinity affinity = Affinity.GOOD; + private int color; + private boolean obtainable = true; + private boolean stackable = false; + private GemstoneItem.Shape shape = GemstoneItem.Shape.ROUND; + private SpellTraits traits = SpellTraits.EMPTY; + + Builder(Factory factory) { + this.factory = factory; + } + + public Builder affinity(Affinity affinity) { + this.affinity = affinity; + return this; + } + + public Builder color(int color) { + this.color = color; + return this; + } + + public Builder unobtainable() { + obtainable = false; + return this; + } + + public Builder stackable() { + stackable = true; + return this; + } + + public Builder shape(GemstoneItem.Shape shape) { + this.shape = shape; + return this; + } + + public Builder traits(SpellTraits traits) { + this.traits = traits; + return this; + } + + public SpellType build(Identifier id) { + return new SpellType<>(id, affinity, color, obtainable, stackable, shape, traits, factory); + } + } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java index 8361a045..17182cef 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java @@ -164,18 +164,19 @@ public class DismissSpellScreen extends GameGui { public void render(DrawContext context, int mouseX, int mouseY, float tickDelta) { MatrixStack matrices = context.getMatrices(); - var type = actualSpell.getType().withTraits(actualSpell.getTraits()); + var type = actualSpell.getTypeAndTraits(); + var affinity = actualSpell.getAffinity(); copy.set(mouseX - width * 0.5F - x * 0.5F, mouseY - height * 0.5F - y * 0.5F, 0, 0); - DrawableUtil.drawLine(matrices, 0, 0, (int)x, (int)y, actualSpell.getAffinity().getColor().getColorValue()); + DrawableUtil.drawLine(matrices, 0, 0, (int)x, (int)y, affinity.getColor().getColorValue()); DrawableUtil.renderItemIcon(context, actualSpell.isDead() ? UItems.BOTCHED_GEM.getDefaultStack() : type.getDefaultStack(), x - 8 - copy.x * 0.2F, y - 8 - copy.y * 0.2F, 1 ); - int color = actualSpell.getType().getColor() << 2; + int color = type.type().getColor() << 2; matrices.push(); matrices.translate(x, y, 0); @@ -187,15 +188,15 @@ public class DismissSpellScreen extends GameGui { List tooltip = new ArrayList<>(); - MutableText name = actualSpell.getType().getName().copy(); - color = actualSpell.getType().getColor(); + MutableText name = type.type().getName().copy(); + color = type.type().getColor(); name.setStyle(name.getStyle().withColor(color == 0 ? 0xFFAAAAAA : color)); tooltip.add(Text.translatable("gui.unicopia.dispell_screen.spell_type", name)); - actualSpell.getType().getTraits().appendTooltip(tooltip); + type.traits().appendTooltip(tooltip); tooltip.add(ScreenTexts.EMPTY); - tooltip.add(Text.translatable("gui.unicopia.dispell_screen.affinity", actualSpell.getAffinity().name()).formatted(actualSpell.getAffinity().getColor())); + tooltip.add(Text.translatable("gui.unicopia.dispell_screen.affinity", affinity.getDisplayName()).formatted(affinity.getColor())); tooltip.add(ScreenTexts.EMPTY); - tooltip.addAll(TextHelper.wrap(Text.translatable(actualSpell.getType().getTranslationKey() + ".lore").formatted(actualSpell.getAffinity().getColor()), 180).toList()); + tooltip.addAll(TextHelper.wrap(Text.translatable(type.type().getTranslationKey() + ".lore").formatted(affinity.getColor()), 180).toList()); if (spell instanceof TimedSpell timed) { tooltip.add(ScreenTexts.EMPTY); tooltip.add(Text.translatable("gui.unicopia.dispell_screen.time_left", StringHelper.formatTicks(timed.getTimer().getTicksRemaining()))); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/HornFeatureRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/HornFeatureRenderer.java index 068263e5..786dee41 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/HornFeatureRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/HornFeatureRenderer.java @@ -55,7 +55,7 @@ public class HornFeatureRenderer implements AccessoryFea return pony.getAbilities().getActiveStat() .flatMap(Stat::getActiveAbility) .map(ability -> ability.getColor(pony)) - .filter(i -> i != -1).or(() -> pony.getSpellSlot().get(SpellPredicate.IS_NOT_PLACED, false).map(spell -> spell.getType().getColor())); + .filter(i -> i != -1).or(() -> pony.getSpellSlot().get(SpellPredicate.IS_NOT_PLACED, false).map(spell -> spell.getTypeAndTraits().type().getColor())); }).ifPresent(color -> { model.setState(true); model.render(stack, ItemRenderer.getArmorGlintConsumer(renderContext, RenderLayers.getMagicColored((0x99 << 24) | color), false, false), lightUv, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/entity/MagicBeamEntityRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/entity/MagicBeamEntityRenderer.java index 26e2297a..24d4a042 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/entity/MagicBeamEntityRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/entity/MagicBeamEntityRenderer.java @@ -57,7 +57,7 @@ public class MagicBeamEntityRenderer extends EntityRenderer { ); RenderLayer layer = entity.getSpellSlot().get(true) - .map(spell -> (0x99 << 24) | spell.getType().getColor()) + .map(spell -> (0x99 << 24) | spell.getTypeAndTraits().type().getColor()) .map(RenderLayers::getMagicColored) .orElseGet(RenderLayers::getMagicColored); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/PlacedSpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PlacedSpellRenderer.java index fbdfce47..ee08654d 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/PlacedSpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PlacedSpellRenderer.java @@ -66,7 +66,7 @@ public class PlacedSpellRenderer extends SpellRenderer { float angle = (animationProgress / 9F) % 360; - int color = delegate.getType().getColor(); + int color = delegate.getTypeAndTraits().type().getColor(); float red = Color.r(color); float green = Color.g(color); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/ShieldSpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/ShieldSpellRenderer.java index 1fc202ad..70fd70f3 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/ShieldSpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/ShieldSpellRenderer.java @@ -27,7 +27,7 @@ public class ShieldSpellRenderer extends SpellRenderer { double height = caster.asEntity().getEyeY() - caster.getOriginVector().y; matrices.translate(0, height, 0); - int typeColor = spell.getType().getColor(); + int typeColor = spell.getTypeAndTraits().type().getColor(); int ponyColor = MineLPDelegate.getInstance().getMagicColor(caster.getOriginatingCaster().asEntity()); int color = ColorHelper.lerp(caster.getCorruption().getScaled(1) * (tickDelta / (1 + caster.asWorld().random.nextFloat())), diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellEffectsRenderDispatcher.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellEffectsRenderDispatcher.java index c87430da..90bfbbb2 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellEffectsRenderDispatcher.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellEffectsRenderDispatcher.java @@ -68,7 +68,7 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader @SuppressWarnings("unchecked") public SpellRenderer getRenderer(S spell) { - return (SpellRenderer)renderers.getOrDefault(spell.getType(), SpellRenderer.DEFAULT); + return (SpellRenderer)renderers.getOrDefault(spell.getTypeAndTraits().type(), SpellRenderer.DEFAULT); } public void render(MatrixStack matrices, VertexConsumerProvider vertices, Spell spell, Caster caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { @@ -127,8 +127,8 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader caster.getSpellSlot().stream(AllSpells.INSTANCE, false).flatMap(spell -> Stream.of( Text.literal("UUID: " + spell.getUuid()), - Text.literal("|>Type: ").append(Text.literal(spell.getType().getId().toString()).styled(s -> s.withColor(spell.getType().getColor()))), - Text.of("|>Traits: " + spell.getTraits()), + Text.literal("|>Type: ").append(Text.literal(spell.getTypeAndTraits().type().getId().toString()).styled(s -> s.withColor(spell.getTypeAndTraits().type().getColor()))), + Text.of("|>Traits: " + spell.getTypeAndTraits().traits()), Text.literal("|>HasRenderer: ").append(Text.literal((getRenderer(spell) != null) + "").formatted(getRenderer(spell) != null ? Formatting.GREEN : Formatting.RED)) ) ) diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java index cdaf9f79..74e72212 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java @@ -42,7 +42,7 @@ public class SpellRenderer { matrices.push(); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(animationProgress)); - client.getItemRenderer().renderItem(spell.getType().withTraits(spell.getTraits()).getDefaultStack(), ModelTransformationMode.FIXED, light, 0, matrices, vertices, caster.asWorld(), 0); + client.getItemRenderer().renderItem(spell.getTypeAndTraits().getDefaultStack(), ModelTransformationMode.FIXED, light, 0, matrices, vertices, caster.asWorld(), 0); matrices.pop(); if (spell instanceof TimedSpell timed) { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerCharmTracker.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerCharmTracker.java index aeaf4d73..2721ec83 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerCharmTracker.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerCharmTracker.java @@ -66,7 +66,7 @@ public class PlayerCharmTracker implements NbtSerialisable { public void toNBT(NbtCompound compound) { NbtList equippedSpells = new NbtList(); for (CustomisedSpellType spell : handSpells) { - equippedSpells.add(spell.toNBT()); + equippedSpells.add(spell.toNbt(new NbtCompound())); } compound.put("handSpells", equippedSpells); } 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 b8f30cd5..5502920a 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -955,7 +955,7 @@ public class Pony extends Living implements Copyable, Update if (spell.getAffinity() == Affinity.BAD && entity.getWorld().random.nextInt(20) == 0) { getCorruption().add(entity.getRandom().nextBetween(1, 10)); } - getCorruption().add((int)spell.getTraits().getCorruption() * 10); + getCorruption().add((int)spell.getTypeAndTraits().traits().getCorruption() * 10); setDirty(); } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/EnchantedStaffItem.java b/src/main/java/com/minelittlepony/unicopia/item/EnchantedStaffItem.java index 08798972..6d08b1f7 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/EnchantedStaffItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/EnchantedStaffItem.java @@ -12,6 +12,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.Spell; +import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation; import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; @@ -46,7 +47,10 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch public static SpellType getSpellType(Entity entity, boolean remove) { if (entity instanceof CastSpellEntity cast) { - return cast.getSpellSlot().get(c -> !SpellPredicate.IS_PLACED.test(c), true).map(Spell::getType).orElse(SpellType.empty()); + return cast.getSpellSlot().get(c -> !SpellPredicate.IS_PLACED.test(c), true) + .map(Spell::getTypeAndTraits) + .map(CustomisedSpellType::type) + .orElse(SpellType.empty()); } if (entity instanceof PlayerEntity player) { if (remove) { diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java b/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java index d60b7607..1dd46a92 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java @@ -25,7 +25,7 @@ public class Ether extends PersistentState { return WorldOverlay.getPersistableStorage(world, ID, Ether::new, Ether::new); } - private final Map>>> endpoints; + private final Map, Map>>> endpoints; private final Object locker = new Object(); @@ -33,7 +33,7 @@ public class Ether extends PersistentState { Ether(World world, NbtCompound compound) { this.world = world; - this.endpoints = NbtSerialisable.readMap(compound.getCompound("endpoints"), Identifier::tryParse, typeNbt -> { + this.endpoints = NbtSerialisable.readMap(compound.getCompound("endpoints"), id -> SpellType.getKey(Identifier.tryParse(id)), typeNbt -> { return NbtSerialisable.readMap((NbtCompound)typeNbt, UUID::fromString, entityNbt -> { return NbtSerialisable.readMap((NbtCompound)entityNbt, UUID::fromString, Entry::new); }); @@ -49,7 +49,7 @@ public class Ether extends PersistentState { public NbtCompound writeNbt(NbtCompound compound) { synchronized (locker) { pruneNodes(); - compound.put("endpoints", NbtSerialisable.writeMap(endpoints, Identifier::toString, entities -> { + compound.put("endpoints", NbtSerialisable.writeMap(endpoints, type -> type.getId().toString(), entities -> { return NbtSerialisable.writeMap(entities, UUID::toString, spells -> { return NbtSerialisable.writeMap(spells, UUID::toString, Entry::toNBT); }); @@ -62,7 +62,7 @@ public class Ether extends PersistentState { public Entry getOrCreate(T spell, Caster caster) { synchronized (locker) { Entry entry = (Entry)endpoints - .computeIfAbsent(spell.getType().getId(), typeId -> new HashMap<>()) + .computeIfAbsent(spell.getTypeAndTraits().type(), typeId -> new HashMap<>()) .computeIfAbsent(caster.asEntity().getUuid(), entityId -> new HashMap<>()) .computeIfAbsent(spell.getUuid(), spellid -> { markDirty(); @@ -82,7 +82,7 @@ public class Ether extends PersistentState { public void remove(SpellType spellType, UUID entityId) { synchronized (locker) { - endpoints.computeIfPresent(spellType.getId(), (typeId, entries) -> { + endpoints.computeIfPresent(spellType, (typeId, entries) -> { if (entries.remove(entityId) != null) { markDirty(); } @@ -104,7 +104,7 @@ public class Ether extends PersistentState { @SuppressWarnings("unchecked") public Entry get(T spell, Caster caster) { - return get((SpellType)spell.getType(), caster.asEntity().getUuid(), spell.getUuid()); + return get((SpellType)spell.getTypeAndTraits().type(), caster.asEntity().getUuid(), spell.getUuid()); } public Entry get(SpellType spell, EntityReference.EntityValues entityId, @Nullable UUID spellId) { diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index dcacc971..717632bd 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -725,6 +725,10 @@ "ability.unicopia.dash": "Flying Dash", "ability.unicopia.change_form": "Change Form", "ability.unicopia.sonar_pulse": "Sonar Pulse", + + "affinity.unicopia.good": "Good", + "affinity.unicopia.bad": "Bad", + "affinity.unicopia.neutral": "Neutral", "gui.unicopia.trait.label": "Element of %s", "gui.unicopia.trait.group": "\n %s",