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.
This commit is contained in:
WinDanesz
2022-04-17 20:43:59 +02:00
parent ea27b1a081
commit 3155aa6815
3 changed files with 42 additions and 1 deletions
@@ -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
@@ -189,7 +189,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> 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<Spell> 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<Spell> 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;
@@ -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<Spell> 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++);
}
}
}