From 3155aa6815b2219d4ca80fed811624776f71f626 Mon Sep 17 00:00:00 2001 From: WinDanesz <31292708+WinDanesz@users.noreply.github.com> Date: Sun, 17 Apr 2022 20:43:59 +0200 Subject: [PATCH] fix: Should fix the disconnect issue when pretty much all existing spell packs are present in the game Mods were registering spells on the client and server side in a different order (perhaps related to the OS), causing a mismatch in spell networkIDs. This will ensure that spells are sorted alphabetically and redistributes a new ID. --- .../java/electroblob/wizardry/Wizardry.java | 3 ++ .../electroblob/wizardry/spell/Spell.java | 8 ++++- .../wizardry/util/SpellNetworkIDSorter.java | 32 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/main/java/electroblob/wizardry/util/SpellNetworkIDSorter.java diff --git a/src/main/java/electroblob/wizardry/Wizardry.java b/src/main/java/electroblob/wizardry/Wizardry.java index 9e6daef6..56a7f5cc 100644 --- a/src/main/java/electroblob/wizardry/Wizardry.java +++ b/src/main/java/electroblob/wizardry/Wizardry.java @@ -20,6 +20,7 @@ import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryLoot; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.util.SpellNetworkIDSorter; import electroblob.wizardry.util.SpellProperties; import electroblob.wizardry.util.WandHelper; import electroblob.wizardry.worldgen.WorldGenCrystalFlower; @@ -202,6 +203,8 @@ public class Wizardry { public void postInit(FMLPostInitializationEvent event){ proxy.initialiseLayers(); proxy.initialiseAnimations(); + + SpellNetworkIDSorter.init(); } @EventHandler diff --git a/src/main/java/electroblob/wizardry/spell/Spell.java b/src/main/java/electroblob/wizardry/spell/Spell.java index 386a3d64..609dc4cf 100644 --- a/src/main/java/electroblob/wizardry/spell/Spell.java +++ b/src/main/java/electroblob/wizardry/spell/Spell.java @@ -189,7 +189,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C private static int nextSpellId = 0; /** The spell's integer ID, mainly used for networking. */ // This was added after I learnt the hard way why you can't assume Forge's registry IDs are sequential... - private final int id; + private int id; /** * This constructor should be called from any subclasses, either feeding in the constants directly or through their @@ -225,6 +225,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C this.icon = new ResourceLocation(modID, "textures/spells/" + name + ".png"); this.sounds = createSounds(); this.id = nextSpellId++; + Wizardry.logger.debug("Registering spell " + this.unlocalisedName +" with networkID " + id); this.items(WizardryItems.spell_book, WizardryItems.scroll); this.npcSelector((e, o) -> false); } @@ -560,6 +561,11 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C return id; } + /** Sets the networkID of this spell. Do not call this or it will cause all packets to fail. */ + public void setId(int id) { + this.id = id; + } + /** Returns the {@code ResourceLocation} for this spell's icon. */ public final ResourceLocation getIcon(){ return icon; diff --git a/src/main/java/electroblob/wizardry/util/SpellNetworkIDSorter.java b/src/main/java/electroblob/wizardry/util/SpellNetworkIDSorter.java new file mode 100644 index 00000000..2d06931d --- /dev/null +++ b/src/main/java/electroblob/wizardry/util/SpellNetworkIDSorter.java @@ -0,0 +1,32 @@ +package electroblob.wizardry.util; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.spell.Spell; + +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Helper class which ensures that all spellpack spell networkIDs are distributed in alphabetical order. Introducing this was necessary as mods (especially with + * (load-after) dependencies were not always registering their spells in the exact same order. This is definitely + */ +public class SpellNetworkIDSorter { + + public static void init() { + + //reorder network IDs based on addon modids. This is necessary as modloading order doesn't seem to be guaranteed to match between various servers and clients + Wizardry.logger.debug("Reordering all spell NetworkIDs based on addon modid alphabetical order"); + + // the first available ID after all default spells + int nextSpellId = (int) Spell.getAllSpells().stream().filter(spell -> spell.getRegistryName().getNamespace().equals(Wizardry.MODID)).count() + 1; + List addonSpells = Spell.getAllSpells().stream().filter(spell -> !spell.getRegistryName().getNamespace().equals(Wizardry.MODID)).collect(Collectors.toList()); + + // sorting spells + addonSpells.sort(Comparator.comparing((Spell o) -> o.getRegistryName().toString())); + for (Spell spell : addonSpells) { + Wizardry.logger.debug("Updating networkID of spell " + spell.getRegistryName().toString() + " from " + spell.networkID() + " to " + nextSpellId); + spell.setId(nextSpellId++); + } + } +}