diff --git a/src/main/java/net/minecraftforge/fml/common/FMLContainer.java b/src/main/java/net/minecraftforge/fml/common/FMLContainer.java index 92c2258302..c1a77d183c 100644 --- a/src/main/java/net/minecraftforge/fml/common/FMLContainer.java +++ b/src/main/java/net/minecraftforge/fml/common/FMLContainer.java @@ -154,6 +154,14 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai blocked[idx++] = i; } data.setIntArray("blocked", blocked); + NBTTagList dummied = new NBTTagList(); + for (ResourceLocation entry : e.getValue().dummied) + { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString("K", entry.toString()); + dummied.appendTag(tag); + } + data.setTag("dummied", dummied); } return fmlData; } @@ -297,6 +305,14 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai { entry.blocked.add(i); } + // save doesn't have dummied list + if (!regs.getCompoundTag(key).hasKey("dummied")) return; + list = regs.getCompoundTag(key).getTagList("dummied",10); + for (int x = 0; x < list.tagCount(); x++) + { + NBTTagCompound e = list.getCompoundTagAt(x); + entry.dummied.add(new ResourceLocation(e.getString("K"))); + } } failedElements = PersistentRegistryManager.injectSnapshot(snapshot, true, true); } diff --git a/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeClientState.java b/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeClientState.java index aa09692949..d17393c418 100644 --- a/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeClientState.java +++ b/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeClientState.java @@ -105,11 +105,12 @@ enum FMLHandshakeClientState implements IHandshakeState PersistentRegistryManager.GameDataSnapshot.Entry entry = new PersistentRegistryManager.GameDataSnapshot.Entry(); entry.ids.putAll(pkt.getIdMap()); entry.substitutions.addAll(pkt.getSubstitutions()); + entry.dummied.addAll(pkt.getDummied()); snap.entries.put(pkt.getName(), entry); if (pkt.hasMore()) { - FMLLog.fine("Received Mod Registry mapping for %s: %d IDs %d subs", pkt.getName(), entry.ids.size(), entry.substitutions.size()); + FMLLog.fine("Received Mod Registry mapping for %s: %d IDs %d subs %d dummied", pkt.getName(), entry.ids.size(), entry.substitutions.size(), entry.dummied.size()); return WAITINGSERVERCOMPLETE; } diff --git a/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeMessage.java b/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeMessage.java index b6f797a4ab..e24ed76ef1 100644 --- a/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeMessage.java +++ b/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeMessage.java @@ -165,12 +165,14 @@ public abstract class FMLHandshakeMessage { this.name = name; this.ids = entry.ids; this.substitutions = entry.substitutions; + this.dummied = entry.dummied; } private boolean hasMore; private ResourceLocation name; private Map ids; private Set substitutions; + private Set dummied; @Override public void fromBytes(ByteBuf buffer) @@ -193,6 +195,15 @@ public abstract class FMLHandshakeMessage { { substitutions.add(new ResourceLocation(ByteBufUtils.readUTF8String(buffer))); } + dummied = Sets.newHashSet(); + // if the dummied list isn't present - probably an older server + if (!buffer.isReadable()) return; + length = ByteBufUtils.readVarInt(buffer, 3); + + for (int i = 0; i < length; i++) + { + dummied.add(new ResourceLocation(ByteBufUtils.readUTF8String(buffer))); + } //if (!buffer.isReadable()) return; // In case we expand } @@ -214,6 +225,11 @@ public abstract class FMLHandshakeMessage { { ByteBufUtils.writeUTF8String(buffer, entry.toString()); } + ByteBufUtils.writeVarInt(buffer, dummied.size(), 3); + for (ResourceLocation entry: dummied) + { + ByteBufUtils.writeUTF8String(buffer, entry.toString()); + } } public Map getIdMap() @@ -224,6 +240,7 @@ public abstract class FMLHandshakeMessage { { return substitutions; } + public Set getDummied() { return dummied; } public ResourceLocation getName() { return this.name; diff --git a/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java b/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java index b4a5670856..3e2a5c669f 100644 --- a/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java +++ b/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java @@ -54,6 +54,8 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul */ private final Set blockedIds = Sets.newHashSet(); + private final Set dummiedLocations = Sets.newHashSet(); + private final BitSet availabilityMap; private final AddCallback addCallback; @@ -164,6 +166,8 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul this.persistentSubstitutions.clear(); this.persistentSubstitutions.putAll(otherRegistry.getPersistentSubstitutions()); this.activeSubstitutions.clear(); + this.dummiedLocations.clear(); + this.dummiedLocations.addAll(otherRegistry.dummiedLocations); underlyingIntegerMap = new ObjectIntIdentityMap(); registryObjects.clear(); @@ -384,6 +388,9 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul set.addAll(activeSubstitutions.keySet()); } + public void serializeDummied(Set set) { set.addAll(this.dummiedLocations); } + + /** * Add the specified object to the registry. * @@ -456,6 +463,8 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul { getExistingDelegate(thing).setResourceName(name); } + this.dummiedLocations.remove(name); + if (DEBUG) { FMLLog.finer("Registry add: %s %d %s (req. id %d)", name, idToUse, thing, id); @@ -463,6 +472,12 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul return idToUse; } + void markDummy(ResourceLocation rl, Integer id, I thing) + { + this.dummiedLocations.add(rl); + this.addObjectRaw(id, rl, thing); + } + void addAlias(ResourceLocation from, ResourceLocation to) { aliases.put(from, to); @@ -688,6 +703,11 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul } } + public void loadDummied(Set dummied) + { + this.dummiedLocations.addAll(dummied); + } + public void loadIds(Map ids, Map missingIds, Map remappedIds, FMLControlledNamespacedRegistry currentRegistry, ResourceLocation registryName) { for (Map.Entry entry : ids.entrySet()) diff --git a/src/main/java/net/minecraftforge/fml/common/registry/PersistentRegistryManager.java b/src/main/java/net/minecraftforge/fml/common/registry/PersistentRegistryManager.java index 6071989645..8bc999c8b5 100644 --- a/src/main/java/net/minecraftforge/fml/common/registry/PersistentRegistryManager.java +++ b/src/main/java/net/minecraftforge/fml/common/registry/PersistentRegistryManager.java @@ -161,6 +161,30 @@ public class PersistentRegistryManager loadPersistentDataToStagingRegistry(injectFrozenData, remaps, missing, snapshotEntry, PersistentRegistry.ACTIVE.registrySuperTypes.inverse().get(snapshotEntry.getKey())); } + // Handle dummied blocks + for (ResourceLocation dummy : snapshot.entries.get(BLOCKS).dummied) + { + // Currently missing locally, we just inject and carry on + if (missing.get(BLOCKS).containsKey(dummy)) + { + Integer id = missing.get(BLOCKS).remove(dummy); + // Mark this entry as a dummy + PersistentRegistry.STAGING.getRegistry(BLOCKS, Block.class).markDummy(dummy, id, new BlockDummyAir()); + } + else if (isLocalWorld) + { + // Carry on, we resuscitated the block + } + else + { + Integer id = PersistentRegistry.STAGING.getRegistry(BLOCKS, Block.class).getId(dummy); + // The server believes this is a dummy block identity, but we seem to have one locally. This is likely a conflict + // in mod setup - Mark this entry as a dummy + FMLLog.log(Level.WARN, "The ID %d is currently locally mapped - it will be replaced with air for this session", id); + PersistentRegistry.STAGING.getRegistry(BLOCKS, Block.class).markDummy(dummy, id, new BlockDummyAir()); + } + } + // If we have missed data, fire the missing mapping event List missedMappings = Loader.instance().fireMissingMappingEvent(missing.get(BLOCKS), missing.get(ITEMS), isLocalWorld, remaps.get(BLOCKS), remaps.get(ITEMS)); // If there's still missed mappings, we return, because that's an error @@ -178,7 +202,8 @@ public class PersistentRegistryManager ResourceLocation rl = missingBlock.getKey(); Integer id = missingBlock.getValue(); FMLLog.log(Level.DEBUG, "Replacing id %s named as %s with air block. If the mod becomes available again later, it can reload here", id, rl); - PersistentRegistry.STAGING.getRegistry(BLOCKS, Block.class).add(id, rl, new BlockDummyAir()); + // Mark this entry as a dummy + PersistentRegistry.STAGING.getRegistry(BLOCKS, Block.class).markDummy(rl, id, new BlockDummyAir()); } } // If we're loading up the world from disk, we want to add in the new data that might have been provisioned by mods @@ -301,6 +326,8 @@ public class PersistentRegistryManager missing.put(registryName, Maps.newLinkedHashMap()); remaps.put(registryName, Maps.newHashMap()); newRegistry.loadIds(snapshotEntry.ids, missing.get(registryName), remaps.get(registryName), currentRegistry, registryName); + // Load current dummies AFTER the snapshot is loaded + newRegistry.loadDummied(snapshotEntry.dummied); } public static boolean isFrozen(FMLControlledNamespacedRegistry registry) @@ -510,18 +537,20 @@ public class PersistentRegistryManager public final Set substitutions; public final Map aliases; public final Set blocked; + public final Set dummied; public Entry() { - this(new HashMap(), new HashSet(), new HashMap(), new HashSet()); + this(new HashMap(), new HashSet(), new HashMap(), new HashSet(), new HashSet()); } - public Entry(Map ids, Set substitutions, Map aliases, Set blocked) + public Entry(Map ids, Set substitutions, Map aliases, Set blocked, Set dummies) { this.ids = ids; this.substitutions = substitutions; this.aliases = aliases; this.blocked = blocked; + this.dummied = dummies; } public Entry(FMLControlledNamespacedRegistry registry) @@ -530,11 +559,13 @@ public class PersistentRegistryManager this.substitutions = Sets.newHashSet(); this.aliases = Maps.newHashMap(); this.blocked = Sets.newHashSet(); + this.dummied = Sets.newHashSet(); registry.serializeIds(this.ids); registry.serializeSubstitutions(this.substitutions); registry.serializeAliases(this.aliases); registry.serializeBlockList(this.blocked); + registry.serializeDummied(this.dummied); } }