diff --git a/fml/build.gradle b/fml/build.gradle index 5dc4b65b5..b2af25bf7 100644 --- a/fml/build.gradle +++ b/fml/build.gradle @@ -38,7 +38,7 @@ minecraft { installerVersion = "1.4" } -group = 'net.minecraftforge.fml' +group = 'net.minecraftforge' version = getVersionFromGit(getProject()) jenkins { diff --git a/fml/src/main/java/net/minecraftforge/fml/client/FMLClientHandler.java b/fml/src/main/java/net/minecraftforge/fml/client/FMLClientHandler.java index bf88f22c8..a4cc51347 100644 --- a/fml/src/main/java/net/minecraftforge/fml/client/FMLClientHandler.java +++ b/fml/src/main/java/net/minecraftforge/fml/client/FMLClientHandler.java @@ -126,10 +126,8 @@ public class FMLClientHandler implements IFMLSidedHandler private DummyModContainer optifineContainer; - @SuppressWarnings("unused") private boolean guiLoaded; - @SuppressWarnings("unused") private boolean serverIsRunning; private MissingModsException modsMissing; @@ -148,7 +146,6 @@ public class FMLClientHandler implements IFMLSidedHandler private List resourcePackList; - @SuppressWarnings("unused") private IReloadableResourceManager resourceManager; private Map resourcePackMap; diff --git a/fml/src/main/java/net/minecraftforge/fml/client/GuiModList.java b/fml/src/main/java/net/minecraftforge/fml/client/GuiModList.java index fa20c721d..f587c9e3c 100644 --- a/fml/src/main/java/net/minecraftforge/fml/client/GuiModList.java +++ b/fml/src/main/java/net/minecraftforge/fml/client/GuiModList.java @@ -168,7 +168,6 @@ public class GuiModList extends GuiScreen } else { - @SuppressWarnings("resource") InputStream logoResource = getClass().getResourceAsStream(logoFile); if (logoResource != null) { diff --git a/fml/src/main/java/net/minecraftforge/fml/common/FMLContainer.java b/fml/src/main/java/net/minecraftforge/fml/common/FMLContainer.java index f1351d1df..023604633 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/FMLContainer.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/FMLContainer.java @@ -24,6 +24,7 @@ import java.util.Set; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagIntArray; import net.minecraft.nbt.NBTTagList; import net.minecraft.world.storage.SaveHandler; import net.minecraft.world.storage.WorldInfo; @@ -92,66 +93,63 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai public NBTTagCompound getDataForWriting(SaveHandler handler, WorldInfo info) { NBTTagCompound fmlData = new NBTTagCompound(); - NBTTagList list = new NBTTagList(); + NBTTagList modList = new NBTTagList(); for (ModContainer mc : Loader.instance().getActiveModList()) { NBTTagCompound mod = new NBTTagCompound(); mod.setString("ModId", mc.getModId()); mod.setString("ModVersion", mc.getVersion()); - list.appendTag(mod); + modList.appendTag(mod); } - fmlData.setTag("ModList", list); - // name <-> id mappings - NBTTagList dataList = new NBTTagList(); - FMLLog.fine("Gathering id map for writing to world save %s", info.getWorldName()); - GameData.GameDataSnapshot dataSnapshot = GameData.buildItemDataList(); - for (Entry item : dataSnapshot.idMap.entrySet()) - { - NBTTagCompound tag = new NBTTagCompound(); - tag.setString("K",item.getKey()); - tag.setInteger("V",item.getValue()); - dataList.appendTag(tag); - } - fmlData.setTag("ItemData", dataList); - // blocked ids - fmlData.setIntArray("BlockedItemIds", GameData.getBlockedIds()); - // block aliases - NBTTagList blockAliasList = new NBTTagList(); - for (Entry entry : GameData.getBlockRegistry().getAliases().entrySet()) - { - NBTTagCompound tag = new NBTTagCompound(); - tag.setString("K", entry.getKey()); - tag.setString("V", entry.getValue()); - blockAliasList.appendTag(tag); - } - fmlData.setTag("BlockAliases", blockAliasList); - NBTTagList blockSubstitutionsList = new NBTTagList(); - for (String entry : dataSnapshot.blockSubstitutions) - { - NBTTagCompound tag = new NBTTagCompound(); - tag.setString("K", entry); - blockSubstitutionsList.appendTag(tag); - } - fmlData.setTag("BlockSubstitutions", blockSubstitutionsList); - // item aliases - NBTTagList itemAliasList = new NBTTagList(); - for (Entry entry : GameData.getItemRegistry().getAliases().entrySet()) - { - NBTTagCompound tag = new NBTTagCompound(); - tag.setString("K", entry.getKey()); - tag.setString("V", entry.getValue()); - itemAliasList.appendTag(tag); - } - fmlData.setTag("ItemAliases", itemAliasList); + fmlData.setTag("ModList", modList); - NBTTagList itemSubstitutionsList = new NBTTagList(); - for (String entry : dataSnapshot.itemSubstitutions) + NBTTagCompound registries = new NBTTagCompound(); + fmlData.setTag("Registries", registries); + FMLLog.fine("Gathering id map for writing to world save %s", info.getWorldName()); + GameData.GameDataSnapshot dataSnapshot = GameData.takeSnapshot(); + + for (Map.Entry e : dataSnapshot.entries.entrySet()) { - NBTTagCompound tag = new NBTTagCompound(); - tag.setString("K", entry); - itemSubstitutionsList.appendTag(tag); + NBTTagCompound data = new NBTTagCompound(); + registries.setTag(e.getKey(), data); + + NBTTagList ids = new NBTTagList(); + for (Entry item : e.getValue().ids.entrySet()) + { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString("K", item.getKey()); + tag.setInteger("V", item.getValue()); + ids.appendTag(tag); + } + data.setTag("ids", ids); + + NBTTagList aliases = new NBTTagList(); + for (Entry entry : e.getValue().aliases.entrySet()) + { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString("K", entry.getKey()); + tag.setString("V", entry.getValue()); + aliases.appendTag(tag); + } + data.setTag("aliases", aliases); + + NBTTagList subs = new NBTTagList(); + for (String entry : e.getValue().substitutions) + { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString("K", entry); + subs.appendTag(tag); + } + data.setTag("substitutions", subs); + + int[] blocked = new int[e.getValue().blocked.size()]; + int idx = 0; + for (Integer i : e.getValue().blocked) + { + blocked[idx++] = i; + } + data.setIntArray("blocked", blocked); } - fmlData.setTag("ItemSubstitutions", itemSubstitutionsList); return fmlData; } @@ -181,97 +179,143 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai List failedElements = null; - if (tag.hasKey("ModItemData")) + if (tag.hasKey("ModItemData")) // Pre 1.7 { + GameData.GameDataSnapshot snapshot = new GameData.GameDataSnapshot(); + GameData.GameDataSnapshot.Entry items = new GameData.GameDataSnapshot.Entry(); + snapshot.entries.put("fml:blocks", new GameData.GameDataSnapshot.Entry()); + snapshot.entries.put("fml:items", items); + FMLLog.info("Attempting to convert old world data to new system. This may be trouble!"); NBTTagList modList = tag.getTagList("ModItemData", (byte)10); - Map dataList = Maps.newLinkedHashMap(); for (int i = 0; i < modList.tagCount(); i++) { - NBTTagCompound itemTag = modList.getCompoundTagAt(i); - String modId = itemTag.getString("ModId"); - String itemType = itemTag.getString("ItemType"); - int itemId = itemTag.getInteger("ItemId"); - int ordinal = itemTag.getInteger("ordinal"); - String forcedModId = itemTag.hasKey("ForcedModId") ? itemTag.getString("ForcedModId") : null; - String forcedName = itemTag.hasKey("ForcedName") ? itemTag.getString("ForcedName") : null; + NBTTagCompound data = modList.getCompoundTagAt(i); + String forcedModId = data.hasKey("ForcedModId") ? data.getString("ForcedModId") : null; + String forcedName = data.hasKey("ForcedName") ? data.getString("ForcedName") : null; if (forcedName == null) { - FMLLog.warning("Found unlabelled item in world save, this may cause problems. The item type %s:%d will not be present", itemType, ordinal); + FMLLog.warning("Found unlabelled item in world save, this may cause problems. The item type %s:%d will not be present", data.getString("ItemType"), data.getInteger("ordinal")); } else { // all entries are Items, blocks were only saved through their ItemBlock - String itemLabel = String.format("%c%s:%s", '\u0002', forcedModId != null ? forcedModId : modId, forcedName); - dataList.put(itemLabel, itemId); + String itemLabel = String.format("%s:%s", forcedModId != null ? forcedModId : data.getString("ModId"), forcedName); + items.ids.put(itemLabel, data.getInteger("ItemId")); } } - failedElements = GameData.injectWorldIDMap(dataList, ImmutableSet.of(), ImmutableSet.of(), true, true); + failedElements = GameData.injectSnapshot(snapshot, true, true); } - else if (tag.hasKey("ItemData")) + else if (tag.hasKey("ItemData")) // 1.7 { - // name <-> id mappings + GameData.GameDataSnapshot snapshot = new GameData.GameDataSnapshot(); + GameData.GameDataSnapshot.Entry blocks = new GameData.GameDataSnapshot.Entry(); + GameData.GameDataSnapshot.Entry items = new GameData.GameDataSnapshot.Entry(); + snapshot.entries.put("fml:blocks", blocks); + snapshot.entries.put("fml:items", items); + NBTTagList list = tag.getTagList("ItemData", 10); - Map dataList = Maps.newLinkedHashMap(); for (int i = 0; i < list.tagCount(); i++) { - NBTTagCompound dataTag = list.getCompoundTagAt(i); - dataList.put(dataTag.getString("K"), dataTag.getInteger("V")); + NBTTagCompound e = list.getCompoundTagAt(i); + String name = e.getString("K"); + + if (name.charAt(0) == '\u0001') + blocks.ids.put(name.substring(1), e.getInteger("V")); + else if (name.charAt(0) == '\u0002') + items.ids.put(name.substring(1), e.getInteger("V")); } Set blockedIds = new HashSet(); - if (!tag.hasKey("BlockedItemIds")) // no blocked id info -> old 1.7 save { // old early 1.7 save potentially affected by the registry mapping bug // fix the ids the best we can... - GameData.fixBrokenIds(dataList, blockedIds); + GameData.fixBrokenIds(blocks, items, blockedIds); } - - // blocked ids - for (int id : tag.getIntArray("BlockedItemIds")) + else { - blockedIds.add(id); + for (int id : tag.getIntArray("BlockedItemIds")) + { + blockedIds.add(id); + } } - // block aliases - Map blockAliases = new HashMap(); + blocks.blocked.addAll(blockedIds); + items.blocked.addAll(blockedIds); + list = tag.getTagList("BlockAliases", 10); for (int i = 0; i < list.tagCount(); i++) { NBTTagCompound dataTag = list.getCompoundTagAt(i); - blockAliases.put(dataTag.getString("K"), dataTag.getString("V")); + blocks.aliases.put(dataTag.getString("K"), dataTag.getString("V")); } - Set blockSubstitutions = Sets.newHashSet(); + if (tag.hasKey("BlockSubstitutions", 9)) { list = tag.getTagList("BlockSubstitutions", 10); for (int i = 0; i < list.tagCount(); i++) { NBTTagCompound dataTag = list.getCompoundTagAt(i); - blockSubstitutions.add(dataTag.getString("K")); + blocks.substitutions.add(dataTag.getString("K")); } } - // item aliases - Map itemAliases = new HashMap(); + list = tag.getTagList("ItemAliases", 10); for (int i = 0; i < list.tagCount(); i++) { NBTTagCompound dataTag = list.getCompoundTagAt(i); - itemAliases.put(dataTag.getString("K"), dataTag.getString("V")); + items.aliases.put(dataTag.getString("K"), dataTag.getString("V")); } - Set itemSubstitutions = Sets.newHashSet(); if (tag.hasKey("ItemSubstitutions", 9)) { list = tag.getTagList("ItemSubstitutions", 10); for (int i = 0; i < list.tagCount(); i++) { NBTTagCompound dataTag = list.getCompoundTagAt(i); - itemSubstitutions.add(dataTag.getString("K")); + items.substitutions.add(dataTag.getString("K")); } } - failedElements = GameData.injectWorldIDMap(dataList, blockedIds, blockAliases, itemAliases, blockSubstitutions, itemSubstitutions, true, true); + failedElements = GameData.injectSnapshot(snapshot, true, true); + } + else if (tag.hasKey("Registries")) // 1.8, genericed out the 'registries' list + { + GameData.GameDataSnapshot snapshot = new GameData.GameDataSnapshot(); + NBTTagCompound regs = tag.getCompoundTag("Registries"); + for (String key : (Set)regs.getKeySet()) + { + GameData.GameDataSnapshot.Entry entry = new GameData.GameDataSnapshot.Entry(); + snapshot.entries.put(key, entry); + + NBTTagList list = regs.getCompoundTag(key).getTagList("ids", 10); + for (int x = 0; x < list.tagCount(); x++) + { + NBTTagCompound e = list.getCompoundTagAt(x); + entry.ids.put(e.getString("K"), e.getInteger("V")); + } + + list = regs.getCompoundTag(key).getTagList("aliases", 10); + for (int x = 0; x < list.tagCount(); x++) + { + NBTTagCompound e = list.getCompoundTagAt(x); + entry.aliases.put(e.getString("K"), e.getString("V")); + } + + list = regs.getCompoundTag(key).getTagList("substitutions", 10); + for (int x = 0; x < list.tagCount(); x++) + { + NBTTagCompound e = list.getCompoundTagAt(x); + entry.substitutions.add(e.getString("K")); + } + + int[] blocked = regs.getCompoundTag(key).getIntArray("blocked"); + for (int i : blocked) + { + entry.blocked.add(i); + } + } + failedElements = GameData.injectSnapshot(snapshot, true, true); } if (failedElements != null && !failedElements.isEmpty()) diff --git a/fml/src/main/java/net/minecraftforge/fml/common/Loader.java b/fml/src/main/java/net/minecraftforge/fml/common/Loader.java index 9d2a78fb9..9ecc0a3fb 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/Loader.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/Loader.java @@ -695,8 +695,6 @@ public class Loader modController.transition(LoaderState.AVAILABLE, false); modController.distributeStateMessage(LoaderState.AVAILABLE); GameData.freezeData(); - // Dump the custom registry data map, if necessary - GameData.dumpRegistry(minecraftDir); FMLLog.info("Forge Mod Loader has successfully loaded %d mod%s", mods.size(), mods.size() == 1 ? "" : "s"); } diff --git a/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeClientState.java b/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeClientState.java index 98f11f351..d28a6d5b8 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeClientState.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeClientState.java @@ -1,5 +1,6 @@ package net.minecraftforge.fml.common.network.handshake; +import java.util.HashSet; import java.util.List; import net.minecraftforge.fml.common.FMLLog; @@ -85,8 +86,28 @@ enum FMLHandshakeClientState implements IHandshakeState @Override public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg) { - FMLHandshakeMessage.ModIdData modIds = (FMLHandshakeMessage.ModIdData)msg; - List locallyMissing = GameData.injectWorldIDMap(modIds.dataList(), modIds.blockSubstitutions(), modIds.itemSubstitutions(), false, false); + FMLHandshakeMessage.RegistryData pkt = (FMLHandshakeMessage.RegistryData)msg; + GameData.GameDataSnapshot snap = ctx.channel().attr(NetworkDispatcher.FML_GAMEDATA_SNAPSHOT).get(); + if (snap == null) + { + snap = new GameData.GameDataSnapshot(); + ctx.channel().attr(NetworkDispatcher.FML_GAMEDATA_SNAPSHOT).set(snap); + } + + GameData.GameDataSnapshot.Entry entry = new GameData.GameDataSnapshot.Entry(); + entry.ids.putAll(pkt.getIdMap()); + entry.substitutions.addAll(pkt.getSubstitutions()); + 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()); + return WAITINGSERVERCOMPLETE; + } + + ctx.channel().attr(NetworkDispatcher.FML_GAMEDATA_SNAPSHOT).remove(); + + List locallyMissing = GameData.injectSnapshot(snap, false, false); if (!locallyMissing.isEmpty()) { NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get(); diff --git a/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeCodec.java b/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeCodec.java index 806e7b583..da6ed3fb5 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeCodec.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeCodec.java @@ -10,7 +10,7 @@ public class FMLHandshakeCodec extends FMLIndexedMessageToMessageCodec modIds; - private Set blockSubstitutions; - private Set itemSubstitutions; + private boolean hasMore; + private String name; + private Map ids; + private Set substitutions; + @Override public void fromBytes(ByteBuf buffer) { + this.hasMore = buffer.readBoolean(); + this.name = ByteBufUtils.readUTF8String(buffer); + int length = ByteBufUtils.readVarInt(buffer, 3); - modIds = Maps.newHashMap(); - blockSubstitutions = Sets.newHashSet(); - itemSubstitutions = Sets.newHashSet(); + ids = Maps.newHashMap(); for (int i = 0; i < length; i++) { - modIds.put(ByteBufUtils.readUTF8String(buffer),ByteBufUtils.readVarInt(buffer, 3)); - } - // we don't have any more data to read - if (!buffer.isReadable()) - { - return; + ids.put(ByteBufUtils.readUTF8String(buffer), ByteBufUtils.readVarInt(buffer, 3)); } + length = ByteBufUtils.readVarInt(buffer, 3); + substitutions = Sets.newHashSet(); + for (int i = 0; i < length; i++) { - blockSubstitutions.add(ByteBufUtils.readUTF8String(buffer)); - } - length = ByteBufUtils.readVarInt(buffer, 3); - for (int i = 0; i < length; i++) - { - itemSubstitutions.add(ByteBufUtils.readUTF8String(buffer)); + substitutions.add(ByteBufUtils.readUTF8String(buffer)); } + //if (!buffer.isReadable()) return; // In case we expand } @Override public void toBytes(ByteBuf buffer) { - ByteBufUtils.writeVarInt(buffer, modIds.size(), 3); - for (Entry entry: modIds.entrySet()) + buffer.writeBoolean(this.hasMore); + ByteBufUtils.writeUTF8String(buffer, this.name); + + ByteBufUtils.writeVarInt(buffer, ids.size(), 3); + for (Entry entry: ids.entrySet()) { ByteBufUtils.writeUTF8String(buffer, entry.getKey()); ByteBufUtils.writeVarInt(buffer, entry.getValue(), 3); } - ByteBufUtils.writeVarInt(buffer, blockSubstitutions.size(), 3); - for (String entry: blockSubstitutions) - { - ByteBufUtils.writeUTF8String(buffer, entry); - } - ByteBufUtils.writeVarInt(buffer, blockSubstitutions.size(), 3); - - for (String entry: itemSubstitutions) + ByteBufUtils.writeVarInt(buffer, substitutions.size(), 3); + for (String entry: substitutions) { ByteBufUtils.writeUTF8String(buffer, entry); } } - public Map dataList() + public Map getIdMap() { - return modIds; + return ids; } - public Set blockSubstitutions() + public Set getSubstitutions() { - return blockSubstitutions; + return substitutions; } - public Set itemSubstitutions() + public String getName() { - return itemSubstitutions; + return this.name; + } + public boolean hasMore() + { + return this.hasMore; } @Override public String toString(Class> side) { - return super.toString(side) + ":"+modIds.size()+" mappings"; + return super.toString(side) + ":"+ids.size()+" mappings"; } } public static class HandshakeAck extends FMLHandshakeMessage { diff --git a/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeServerState.java b/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeServerState.java index f5a9eee37..e7586cda3 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeServerState.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/FMLHandshakeServerState.java @@ -1,5 +1,9 @@ package net.minecraftforge.fml.common.network.handshake; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + import net.minecraftforge.fml.common.FMLLog; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.network.NetworkRegistry; @@ -56,7 +60,13 @@ enum FMLHandshakeServerState implements IHandshakeState { if (!ctx.channel().attr(NetworkDispatcher.IS_LOCAL).get()) { - ctx.writeAndFlush(new FMLHandshakeMessage.ModIdData(GameData.buildItemDataList())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); + GameData.GameDataSnapshot snapshot = GameData.takeSnapshot(); + Iterator> itr = snapshot.entries.entrySet().iterator(); + while (itr.hasNext()) + { + Entry e = itr.next(); + ctx.writeAndFlush(new FMLHandshakeMessage.RegistryData(itr.hasNext(), e.getKey(), e.getValue())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); + } } ctx.writeAndFlush(new FMLHandshakeMessage.HandshakeAck(ordinal())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); NetworkRegistry.INSTANCE.fireNetworkHandshake(ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get(), Side.SERVER); diff --git a/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/NetworkDispatcher.java b/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/NetworkDispatcher.java index a6d69da6e..9f6a2e410 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/NetworkDispatcher.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/network/handshake/NetworkDispatcher.java @@ -41,6 +41,7 @@ import net.minecraftforge.fml.common.network.PacketLoggingHandler; import net.minecraftforge.fml.common.network.internal.FMLMessage; import net.minecraftforge.fml.common.network.internal.FMLNetworkHandler; import net.minecraftforge.fml.common.network.internal.FMLProxyPacket; +import net.minecraftforge.fml.common.registry.GameData; import net.minecraftforge.fml.relauncher.Side; public class NetworkDispatcher extends SimpleChannelInboundHandler implements ChannelOutboundHandler { @@ -74,6 +75,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler imple public static final AttributeKey FML_DISPATCHER = AttributeKey.valueOf("fml:dispatcher"); public static final AttributeKey IS_LOCAL = AttributeKey.valueOf("fml:isLocal"); + public static final AttributeKey FML_GAMEDATA_SNAPSHOT = AttributeKey.valueOf("fml:gameDataSnapshot"); public final NetworkManager manager; private final ServerConfigurationManager scm; private EntityPlayerMP player; diff --git a/fml/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java b/fml/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java index 0c93d000e..4921c8969 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java @@ -29,18 +29,16 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul private I optionalDefaultObject; private int maxId; private int minId; - private char discriminator; // aliases redirecting legacy names to the actual name, may need recursive application to find the final name. // these need to be registry specific, it's possible to only have a loosely linked item for a block which may get renamed by itself. private final Map aliases = new HashMap(); private BiMap persistentSubstitutions; private BiMap activeSubstitutions = HashBiMap.create(); - FMLControlledNamespacedRegistry(Object defaultKey, int maxIdValue, int minIdValue, Class type, char discriminator) + FMLControlledNamespacedRegistry(Object defaultKey, int maxIdValue, int minIdValue, Class type) { super(defaultKey); this.superType = type; - this.discriminator = discriminator; this.optionalDefaultKey = defaultKey; this.maxId = maxIdValue; this.minId = minIdValue; @@ -98,7 +96,6 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul { if (this.superType != registry.superType) throw new IllegalArgumentException("incompatible registry"); - this.discriminator = registry.discriminator; this.optionalDefaultKey = registry.optionalDefaultKey; this.maxId = registry.maxId; this.minId = registry.minId; @@ -333,13 +330,16 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul { for (I thing : this.typeSafeIterable()) { - idMapping.put(discriminator+getNameForObject(thing).toString(), getId(thing)); + idMapping.put(getNameForObject(thing).toString(), getId(thing)); } } - - public Map getAliases() // for saving + public void serializeAliases(Map map) { - return ImmutableMap.copyOf(aliases); + map.putAll(this.aliases); + } + public void serializeSubstitutions(Set set) + { + set.addAll(activeSubstitutions.keySet()); } /** @@ -504,11 +504,6 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul getPersistentSubstitutions().put(nameToReplace, replacement); } - public void serializeSubstitutions(Set blockSubs) - { - blockSubs.addAll(activeSubstitutions.keySet()); - } - private BiMap getPersistentSubstitutions() { if (persistentSubstitutions == null) diff --git a/fml/src/main/java/net/minecraftforge/fml/common/registry/GameData.java b/fml/src/main/java/net/minecraftforge/fml/common/registry/GameData.java index f597adb85..3007fbc2e 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/registry/GameData.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/registry/GameData.java @@ -14,6 +14,7 @@ package net.minecraftforge.fml.common.registry; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.BitSet; import java.util.HashMap; import java.util.HashSet; @@ -63,11 +64,6 @@ public class GameData { static final int MAX_ITEM_ID = 31999; private static final GameData mainData = new GameData(); - - private static final FMLControlledNamespacedRegistry blockRegistry = getBlockRegistry(); - private static final FMLControlledNamespacedRegistry itemRegistry = getItemRegistry(); - - private static Table customItemStacks = HashBasedTable.create(); private static Map customOwners = Maps.newHashMap(); private static GameData frozen; @@ -91,43 +87,59 @@ public class GameData { return getMain().iItemRegistry; } - /** - * @deprecated no replacement planned - */ - @Deprecated - public static ModContainer findModOwner(String string) + /*************************************************** + * INTERNAL CODE FROM HERE ON DO NOT USE! + ***************************************************/ + + public static class GameDataSnapshot { - UniqueIdentifier ui = new UniqueIdentifier(string); - if (customOwners.containsKey(ui)) + public static class Entry { - return customOwners.get(ui); + public final Map ids; + public final Set substitutions; + public final Map aliases; + public final Set blocked; + + public Entry() + { + this(new HashMap(), new HashSet(), new HashMap(), new HashSet()); + } + + public Entry(Map ids, Set substitions, Map aliases, Set blocked) + { + this.ids = ids; + this.substitutions = substitions; + this.aliases = aliases; + this.blocked = blocked; + } + + public Entry(FMLControlledNamespacedRegistry registry) + { + this.ids = Maps.newHashMap(); + this.substitutions = Sets.newHashSet(); + this.aliases = Maps.newHashMap(); + this.blocked = Sets.newHashSet(); + + registry.serializeInto(this.ids); + registry.serializeSubstitutions(this.substitutions); + registry.serializeAliases(this.aliases); + + if (GameData.getBlockRegistry() == registry || + GameData.getItemRegistry() == registry) + { + this.blocked.addAll(GameData.getMain().blockedIds); + } + } } - return Loader.instance().getIndexedModList().get(ui.modId); + public final Map entries = Maps.newHashMap(); } - // internal from here - - public static class GameDataSnapshot { - public final Map idMap; - public final Set blockSubstitutions; - public final Set itemSubstitutions; - public GameDataSnapshot(Map idMap, Set blockSubstitutions, Set itemSubstitutions) - { - this.idMap = idMap; - this.blockSubstitutions = blockSubstitutions; - this.itemSubstitutions = itemSubstitutions; - } - } - public static GameDataSnapshot buildItemDataList() + public static GameDataSnapshot takeSnapshot() { - Map idMapping = Maps.newHashMap(); - getMain().iBlockRegistry.serializeInto(idMapping); - getMain().iItemRegistry.serializeInto(idMapping); - Set blockSubs = Sets.newHashSet(); - getMain().iBlockRegistry.serializeSubstitutions(blockSubs); - Set itemSubs = Sets.newHashSet(); - getMain().iItemRegistry.serializeSubstitutions(itemSubs); - return new GameDataSnapshot(idMapping, blockSubs, itemSubs); + GameDataSnapshot snap = new GameDataSnapshot(); + snap.entries.put("fml:blocks", new GameDataSnapshot.Entry(getMain().getBlockRegistry())); + snap.entries.put("fml:items", new GameDataSnapshot.Entry(getMain().getItemRegistry())); + return snap; } public static int[] getBlockedIds() @@ -144,34 +156,6 @@ public class GameData { return ret; } - public static void dumpRegistry(File minecraftDir) - { - if (customItemStacks == null) - { - return; - } - if (Boolean.valueOf(System.getProperty("fml.dumpRegistry", "false")).booleanValue()) - { - ImmutableListMultimap.Builder builder = ImmutableListMultimap.builder(); - for (String modId : customItemStacks.rowKeySet()) - { - builder.putAll(modId, customItemStacks.row(modId).keySet()); - } - - File f = new File(minecraftDir, "itemStackRegistry.csv"); - MapJoiner mapJoiner = Joiner.on("\n").withKeyValueSeparator(","); - try - { - Files.write(mapJoiner.join(builder.build().entries()), f, Charsets.UTF_8); - FMLLog.log(Level.INFO, "Dumped item registry data to %s", f.getAbsolutePath()); - } - catch (IOException e) - { - FMLLog.log(Level.ERROR, e, "Failed to write registry data to %s", f.getAbsolutePath()); - } - } - } - static Item findItem(String modId, String name) { return (Item) getMain().iItemRegistry.getObject(modId + ":" + name); @@ -183,57 +167,18 @@ public class GameData { return getMain().iBlockRegistry.containsKey(key) ? getMain().iBlockRegistry.getObject(key) : null; } - static ItemStack findItemStack(String modId, String name) - { - ItemStack is = customItemStacks.get(modId, name); - if (is == null) - { - Item i = findItem(modId, name); - if (i != null) - { - is = new ItemStack(i, 0 ,0); - } - } - if (is == null) - { - Block b = findBlock(modId, name); - if (b != null) - { - is = new ItemStack(b, 0, Short.MAX_VALUE); - } - } - return is; - } - - static void registerCustomItemStack(String name, ItemStack itemStack) - { - customItemStacks.put(Loader.instance().activeModContainer().getModId(), name, itemStack); - } - static UniqueIdentifier getUniqueName(Block block) { if (block == null) return null; Object name = getMain().iBlockRegistry.getNameForObject(block); - UniqueIdentifier ui = new UniqueIdentifier(name); - if (customItemStacks.contains(ui.modId, ui.name)) - { - return null; - } - - return ui; + return new UniqueIdentifier(name); } static UniqueIdentifier getUniqueName(Item item) { if (item == null) return null; Object name = getMain().iItemRegistry.getNameForObject(item); - UniqueIdentifier ui = new UniqueIdentifier(name); - if (customItemStacks.contains(ui.modId, ui.name)) - { - return null; - } - - return ui; + return new UniqueIdentifier(name); } /** @@ -244,20 +189,14 @@ public class GameData { * * @param dataList List containing the IDs to fix */ - public static void fixBrokenIds(Map dataList, Set blockedIds) + public static void fixBrokenIds(GameDataSnapshot.Entry blocks, GameDataSnapshot.Entry items, Set blockedIds) { BitSet availabilityMap = new BitSet(MAX_ITEM_ID + 1); // reserve all ids occupied by blocks - for (Entry entry : dataList.entrySet()) + for (Entry entry : blocks.ids.entrySet()) { - String itemName = entry.getKey(); - String realName = itemName.substring(1); - - if (itemName.charAt(0) == '\u0001') // is a block - { - availabilityMap.set(entry.getValue()); - } + availabilityMap.set(entry.getValue()); } Set newBlockedIds = new HashSet(); @@ -265,71 +204,65 @@ public class GameData { Map itemsToRelocate = new HashMap(); // check all ids occupied by items - for (Entry entry : dataList.entrySet()) + for (Entry entry : items.ids.entrySet()) { - String itemName = entry.getKey(); + int oldId = entry.getValue(); + String name = entry.getKey(); + Item item = getMain().iItemRegistry.getRaw(name); + boolean blockThisId = false; // block oldId unless it's used by a block - if (itemName.charAt(0) != '\u0001') // is an item + if (item == null) // item no longer available { - int oldId = entry.getValue(); - String realName = itemName.substring(1); - String blockName = '\u0001' + realName; - Item item = getMain().iItemRegistry.getRaw(realName); - boolean blockThisId = false; // block oldId unless it's used by a block - - if (item == null) // item no longer available + // can't fix items without reliably checking if they are ItemBlocks + FMLLog.warning("Item %s (old id %d) is no longer available and thus can't be fixed.", name, oldId); + itemsToRemove.add(name); + blockThisId = true; + } + else if (item instanceof ItemBlock) + { + if (blocks.ids.containsKey(name)) // the item was an ItemBlock before { - // can't fix items without reliably checking if they are ItemBlocks - FMLLog.warning("Item %s (old id %d) is no longer available and thus can't be fixed.", realName, oldId); - itemsToRemove.add(itemName); - blockThisId = true; - } - else if (item instanceof ItemBlock) - { - if (dataList.containsKey(blockName)) // the item was an ItemBlock before - { - int blockId = dataList.get(blockName); + int blockId = blocks.ids.get(name); - if (blockId != oldId) // mis-located ItemBlock - { - // relocate to the matching block - FMLLog.warning("ItemBlock %s (old id %d) doesn't have the same id as its block (%d).", realName, oldId, blockId); - itemsToRelocate.put(entry.getKey(), blockId); - blockThisId = true; - } - else // intact ItemBlock - { - availabilityMap.set(oldId); // occupy id - } - } - else // the item hasn't been an ItemBlock before, but it's now + if (blockId != oldId) // mis-located ItemBlock { - // can't fix these, drop them - FMLLog.warning("Item %s (old id %d) has been migrated to an ItemBlock and can't be fixed.", realName, oldId); - itemsToRemove.add(itemName); + // relocate to the matching block + FMLLog.warning("ItemBlock %s (old id %d) doesn't have the same id as its block (%d).", name, oldId, blockId); + itemsToRelocate.put(name, blockId); blockThisId = true; } + else // intact ItemBlock + { + availabilityMap.set(oldId); // occupy id + } } - else if (availabilityMap.get(oldId)) // normal item, id is already occupied + else // the item hasn't been an ItemBlock before, but it's now { - // remove the item mapping - FMLLog.warning("Item %s (old id %d) is conflicting with another block/item and can't be fixed.", realName, oldId); - itemsToRemove.add(itemName); - } - else // intact Item - { - availabilityMap.set(oldId); // occupy id + // can't fix these, drop them + FMLLog.warning("Item %s (old id %d) has been migrated to an ItemBlock and can't be fixed.", name, oldId); + itemsToRemove.add(name); + blockThisId = true; } + } + else if (availabilityMap.get(oldId)) // normal item, id is already occupied + { + // remove the item mapping + FMLLog.warning("Item %s (old id %d) is conflicting with another block/item and can't be fixed.", name, oldId); + itemsToRemove.add(name); + } + else // intact Item + { + availabilityMap.set(oldId); // occupy id + } - // handle blocking the id from future use if possible (i.e. not used by a conflicting block) - // blockThisId requests don't modify availabilityMap, it could only be set by a block (or another item, which isn't being handled) - if (blockThisId && !availabilityMap.get(oldId)) - { - // there's no block occupying this id, thus block the id from future use - // as there may still be ItemStacks in the world referencing it - newBlockedIds.add(oldId); - availabilityMap.set(oldId); - } + // handle blocking the id from future use if possible (i.e. not used by a conflicting block) + // blockThisId requests don't modify availabilityMap, it could only be set by a block (or another item, which isn't being handled) + if (blockThisId && !availabilityMap.get(oldId)) + { + // there's no block occupying this id, thus block the id from future use + // as there may still be ItemStacks in the world referencing it + newBlockedIds.add(oldId); + availabilityMap.set(oldId); } } @@ -350,9 +283,9 @@ public class GameData { // confirm missing mods causing item removal Set modsMissing = new HashSet(); - for (String itemName : itemsToRemove) + for (String name : itemsToRemove) { - modsMissing.add(itemName.substring(1, itemName.indexOf(':'))); + modsMissing.add(name.substring(0, name.indexOf(':'))); } for (Iterator it = modsMissing.iterator(); it.hasNext(); ) @@ -396,32 +329,22 @@ public class GameData { } // apply fix - for (String itemName : itemsToRemove) + for (String name : itemsToRemove) { - int id = dataList.remove(itemName); - - FMLLog.warning("Removed Item %s, old id %d.", itemName.substring(1), id); + FMLLog.warning("Removed Item %s, old id %d.", name, items.ids.remove(name)); } for (Map.Entry entry : itemsToRelocate.entrySet()) { - String itemName = entry.getKey(); int newId = entry.getValue(); - - int oldId = dataList.put(itemName, newId); - - FMLLog.warning("Remapped Item %s to id %d, old id %d.", itemName.substring(1), newId, oldId); + int oldId = items.ids.put(entry.getKey(), newId); + FMLLog.warning("Remapped Item %s to id %d, old id %d.", entry.getKey(), newId, oldId); } blockedIds.addAll(newBlockedIds); } - public static List injectWorldIDMap(Map dataList, Set blockSubstitutions, Set itemSubstitutions, boolean injectFrozenData, boolean isLocalWorld) - { - return injectWorldIDMap(dataList, new HashSet(), new HashMap(), new HashMap(), blockSubstitutions, itemSubstitutions, injectFrozenData, isLocalWorld); - } - - public static List injectWorldIDMap(Map dataList, Set blockedIds, Map blockAliases, Map itemAliases, Set blockSubstitutions, Set itemSubstitutions, boolean injectFrozenData, boolean isLocalWorld) + public static List injectSnapshot(GameDataSnapshot snapshot, boolean injectFrozenData, boolean isLocalWorld) { FMLLog.info("Injecting existing block and item data into this %s instance", FMLCommonHandler.instance().getEffectiveSide().isServer() ? "server" : "client"); Map remaps = Maps.newHashMap(); @@ -430,28 +353,31 @@ public class GameData { getMain().iBlockRegistry.dump(); getMain().iItemRegistry.dump(); + GameDataSnapshot.Entry blocks = snapshot.entries.get("fml:blocks"); + GameDataSnapshot.Entry items = snapshot.entries.get("fml:items"); + GameData newData = new GameData(); - for (int id : blockedIds) + for (int id : blocks.blocked) { newData.block(id); } - for (Map.Entry entry : blockAliases.entrySet()) + for (Map.Entry entry : blocks.aliases.entrySet()) { newData.iBlockRegistry.addAlias(entry.getKey(), entry.getValue()); } - for (Map.Entry entry : itemAliases.entrySet()) + for (Map.Entry entry : items.aliases.entrySet()) { newData.iItemRegistry.addAlias(entry.getKey(), entry.getValue()); } - for (String entry : blockSubstitutions) + for (String entry : blocks.substitutions) { newData.iBlockRegistry.activateSubstitution(entry); } - for (String entry : itemSubstitutions) + for (String entry : items.substitutions) { newData.iItemRegistry.activateSubstitution(entry); } @@ -459,14 +385,14 @@ public class GameData { { for (String newBlockSubstitution : getMain().blockSubstitutions.keySet()) { - if (!blockSubstitutions.contains(newBlockSubstitution)) + if (!blocks.substitutions.contains(newBlockSubstitution)) { newData.iBlockRegistry.activateSubstitution(newBlockSubstitution); } } for (String newItemSubstitution : getMain().itemSubstitutions.keySet()) { - if (!itemSubstitutions.contains(newItemSubstitution)) + if (!items.substitutions.contains(newItemSubstitution)) { newData.iItemRegistry.activateSubstitution(newItemSubstitution); } @@ -477,16 +403,12 @@ public class GameData { for (int pass = 0; pass < 2; pass++) { boolean isBlock = (pass == 0); + Map ids = (isBlock ? blocks.ids : items.ids); - for (Entry entry : dataList.entrySet()) + for (Entry entry : ids.entrySet()) { String itemName = entry.getKey(); int newId = entry.getValue(); - - // names starting with 0x1 are blocks, skip if the type isn't handled by this pass - if ((itemName.charAt(0) == '\u0001') != isBlock) continue; - - itemName = itemName.substring(1); int currId = isBlock ? getMain().iBlockRegistry.getId(itemName) : getMain().iItemRegistry.getId(itemName); if (currId == -1) @@ -743,8 +665,8 @@ public class GameData { private GameData() { - iBlockRegistry = new FMLControlledNamespacedRegistry(new ResourceLocation("minecraft:air"), MAX_BLOCK_ID, MIN_BLOCK_ID, Block.class,'\u0001'); - iItemRegistry = new FMLControlledNamespacedRegistry(null, MAX_ITEM_ID, MIN_ITEM_ID, Item.class,'\u0002'); + iBlockRegistry = new FMLControlledNamespacedRegistry(new ResourceLocation("minecraft:air"), MAX_BLOCK_ID, MIN_BLOCK_ID, Block.class); + iItemRegistry = new FMLControlledNamespacedRegistry(null, MAX_ITEM_ID, MIN_ITEM_ID, Item.class); availabilityMap = new BitSet(MAX_ITEM_ID + 1); blockedIds = new HashSet(); } diff --git a/fml/src/main/java/net/minecraftforge/fml/common/registry/GameRegistry.java b/fml/src/main/java/net/minecraftforge/fml/common/registry/GameRegistry.java index 12cc46dbc..0286fccb6 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/registry/GameRegistry.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/registry/GameRegistry.java @@ -332,42 +332,6 @@ public class GameRegistry return GameData.findItem(modId, name); } - /** - * Manually register a custom item stack with FML for later tracking. It is automatically scoped with the active modid - * - * @param name The name to register it under - * @param itemStack The itemstack to register - */ - public static void registerCustomItemStack(String name, ItemStack itemStack) - { - GameData.registerCustomItemStack(name, itemStack); - } - /** - * Lookup an itemstack based on mod and name. It will create "default" itemstacks from blocks and items if no - * explicit itemstack is found. - * - * If it is built from a block, the metadata is by default the "wildcard" value. - * - * Custom itemstacks can be dumped from minecraft by setting the system property fml.dumpRegistry to true - * (-Dfml.dumpRegistry=true on the command line will work) - * - * @param modId The modid of the stack owner - * @param name The name of the stack - * @param stackSize The size of the stack returned - * @return The custom itemstack or null if no such itemstack was found - */ - public static ItemStack findItemStack(String modId, String name, int stackSize) - { - ItemStack foundStack = GameData.findItemStack(modId, name); - if (foundStack != null) - { - ItemStack is = foundStack.copy(); - is.stackSize = Math.min(stackSize, is.getMaxStackSize()); - return is; - } - return null; - } - public static final class UniqueIdentifier { public final String modId;