Giant registry fixup
This commit is contained in:
parent
5549b06f96
commit
97ef6a5d1f
21 changed files with 801 additions and 1303 deletions
|
@ -375,6 +375,11 @@ public abstract class FluidRegistry
|
|||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getResourceName() {
|
||||
return new ResourceLocation(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Fluid> type()
|
||||
{
|
||||
|
|
|
@ -87,8 +87,8 @@ import net.minecraftforge.fml.common.WrongMinecraftVersionException;
|
|||
import net.minecraftforge.fml.common.eventhandler.EventBus;
|
||||
import net.minecraftforge.fml.common.network.FMLNetworkEvent;
|
||||
import net.minecraftforge.fml.common.network.internal.FMLNetworkHandler;
|
||||
import net.minecraftforge.fml.common.registry.GameData;
|
||||
import net.minecraftforge.fml.common.registry.LanguageRegistry;
|
||||
import net.minecraftforge.fml.common.registry.PersistentRegistryManager;
|
||||
import net.minecraftforge.fml.common.toposort.ModSortingException;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
|
@ -651,7 +651,7 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
// ONLY revert a non-local connection
|
||||
if (client != null && !client.isLocalChannel())
|
||||
{
|
||||
GameData.revertToFrozen();
|
||||
PersistentRegistryManager.revertToFrozen();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Set;
|
|||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.storage.SaveHandler;
|
||||
import net.minecraft.world.storage.WorldInfo;
|
||||
import net.minecraftforge.fml.client.FMLFileResourcePack;
|
||||
|
@ -35,6 +36,7 @@ import net.minecraftforge.fml.common.network.NetworkCheckHandler;
|
|||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
import net.minecraftforge.fml.common.network.internal.FMLNetworkHandler;
|
||||
import net.minecraftforge.fml.common.registry.GameData;
|
||||
import net.minecraftforge.fml.common.registry.PersistentRegistryManager;
|
||||
import net.minecraftforge.fml.common.registry.VillagerRegistry;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
|
@ -109,38 +111,38 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
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();
|
||||
PersistentRegistryManager.GameDataSnapshot dataSnapshot = PersistentRegistryManager.takeSnapshot();
|
||||
|
||||
for (Map.Entry<String, GameData.GameDataSnapshot.Entry> e : dataSnapshot.entries.entrySet())
|
||||
for (Map.Entry<ResourceLocation, PersistentRegistryManager.GameDataSnapshot.Entry> e : dataSnapshot.entries.entrySet())
|
||||
{
|
||||
NBTTagCompound data = new NBTTagCompound();
|
||||
registries.setTag(e.getKey(), data);
|
||||
registries.setTag(e.getKey().toString(), data);
|
||||
|
||||
NBTTagList ids = new NBTTagList();
|
||||
for (Entry<String, Integer> item : e.getValue().ids.entrySet())
|
||||
for (Entry<ResourceLocation, Integer> item : e.getValue().ids.entrySet())
|
||||
{
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setString("K", item.getKey());
|
||||
tag.setString("K", item.getKey().toString());
|
||||
tag.setInteger("V", item.getValue());
|
||||
ids.appendTag(tag);
|
||||
}
|
||||
data.setTag("ids", ids);
|
||||
|
||||
NBTTagList aliases = new NBTTagList();
|
||||
for (Entry<String, String> entry : e.getValue().aliases.entrySet())
|
||||
for (Entry<ResourceLocation, ResourceLocation> entry : e.getValue().aliases.entrySet())
|
||||
{
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setString("K", entry.getKey());
|
||||
tag.setString("V", entry.getValue());
|
||||
tag.setString("K", entry.getKey().toString());
|
||||
tag.setString("V", entry.getValue().toString());
|
||||
aliases.appendTag(tag);
|
||||
}
|
||||
data.setTag("aliases", aliases);
|
||||
|
||||
NBTTagList subs = new NBTTagList();
|
||||
for (String entry : e.getValue().substitutions)
|
||||
for (ResourceLocation entry : e.getValue().substitutions)
|
||||
{
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setString("K", entry);
|
||||
tag.setString("K", entry.toString());
|
||||
subs.appendTag(tag);
|
||||
}
|
||||
data.setTag("substitutions", subs);
|
||||
|
@ -184,39 +186,21 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
|
||||
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);
|
||||
for (int i = 0; i < modList.tagCount(); i++)
|
||||
{
|
||||
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", data.getString("ItemType"), data.getInteger("ordinal"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// all entries are Items, blocks were only saved through their ItemBlock
|
||||
String itemLabel = String.format("%s:%s", forcedModId != null ? forcedModId : data.getString("ModId"), forcedName);
|
||||
items.ids.put(itemLabel, data.getInteger("ItemId"));
|
||||
}
|
||||
}
|
||||
failedElements = GameData.injectSnapshot(snapshot, true, true);
|
||||
|
||||
StartupQuery.notify("This save predates 1.7.10, it can no longer be loaded here. Please load in 1.7.10 or 1.8 first");
|
||||
StartupQuery.abort();
|
||||
}
|
||||
else if (tag.hasKey("ItemData")) // 1.7
|
||||
{
|
||||
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);
|
||||
if (!tag.hasKey("BlockedItemIds")) // no blocked id info -> old 1.7 save
|
||||
{
|
||||
StartupQuery.notify("This save predates 1.7.10, it can no longer be loaded here. Please load in 1.7.10 or 1.8 first");
|
||||
StartupQuery.abort();
|
||||
}
|
||||
PersistentRegistryManager.GameDataSnapshot snapshot = new PersistentRegistryManager.GameDataSnapshot();
|
||||
PersistentRegistryManager.GameDataSnapshot.Entry blocks = new PersistentRegistryManager.GameDataSnapshot.Entry();
|
||||
PersistentRegistryManager.GameDataSnapshot.Entry items = new PersistentRegistryManager.GameDataSnapshot.Entry();
|
||||
snapshot.entries.put(PersistentRegistryManager.BLOCKS, blocks);
|
||||
snapshot.entries.put(PersistentRegistryManager.ITEMS, items);
|
||||
|
||||
NBTTagList list = tag.getTagList("ItemData", 10);
|
||||
for (int i = 0; i < list.tagCount(); i++)
|
||||
|
@ -225,24 +209,15 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
String name = e.getString("K");
|
||||
|
||||
if (name.charAt(0) == '\u0001')
|
||||
blocks.ids.put(name.substring(1), e.getInteger("V"));
|
||||
blocks.ids.put(new ResourceLocation(name.substring(1)), e.getInteger("V"));
|
||||
else if (name.charAt(0) == '\u0002')
|
||||
items.ids.put(name.substring(1), e.getInteger("V"));
|
||||
items.ids.put(new ResourceLocation(name.substring(1)), e.getInteger("V"));
|
||||
}
|
||||
|
||||
Set<Integer> blockedIds = new HashSet<Integer>();
|
||||
if (!tag.hasKey("BlockedItemIds")) // no blocked id info -> old 1.7 save
|
||||
for (int id : tag.getIntArray("BlockedItemIds"))
|
||||
{
|
||||
// old early 1.7 save potentially affected by the registry mapping bug
|
||||
// fix the ids the best we can...
|
||||
GameData.fixBrokenIds(blocks, items, blockedIds);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int id : tag.getIntArray("BlockedItemIds"))
|
||||
{
|
||||
blockedIds.add(id);
|
||||
}
|
||||
blockedIds.add(id);
|
||||
}
|
||||
blocks.blocked.addAll(blockedIds);
|
||||
items.blocked.addAll(blockedIds);
|
||||
|
@ -251,7 +226,7 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
for (int i = 0; i < list.tagCount(); i++)
|
||||
{
|
||||
NBTTagCompound dataTag = list.getCompoundTagAt(i);
|
||||
blocks.aliases.put(dataTag.getString("K"), dataTag.getString("V"));
|
||||
blocks.aliases.put(new ResourceLocation(dataTag.getString("K")), new ResourceLocation(dataTag.getString("V")));
|
||||
}
|
||||
|
||||
if (tag.hasKey("BlockSubstitutions", 9))
|
||||
|
@ -260,7 +235,7 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
for (int i = 0; i < list.tagCount(); i++)
|
||||
{
|
||||
NBTTagCompound dataTag = list.getCompoundTagAt(i);
|
||||
blocks.substitutions.add(dataTag.getString("K"));
|
||||
blocks.substitutions.add(new ResourceLocation(dataTag.getString("K")));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,7 +243,7 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
for (int i = 0; i < list.tagCount(); i++)
|
||||
{
|
||||
NBTTagCompound dataTag = list.getCompoundTagAt(i);
|
||||
items.aliases.put(dataTag.getString("K"), dataTag.getString("V"));
|
||||
items.aliases.put(new ResourceLocation(dataTag.getString("K")), new ResourceLocation(dataTag.getString("V")));
|
||||
}
|
||||
|
||||
if (tag.hasKey("ItemSubstitutions", 9))
|
||||
|
@ -277,39 +252,42 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
for (int i = 0; i < list.tagCount(); i++)
|
||||
{
|
||||
NBTTagCompound dataTag = list.getCompoundTagAt(i);
|
||||
items.substitutions.add(dataTag.getString("K"));
|
||||
items.substitutions.add(new ResourceLocation(dataTag.getString("K")));
|
||||
}
|
||||
}
|
||||
failedElements = GameData.injectSnapshot(snapshot, true, true);
|
||||
failedElements = PersistentRegistryManager.injectSnapshot(snapshot, true, true);
|
||||
}
|
||||
else if (tag.hasKey("Registries")) // 1.8, genericed out the 'registries' list
|
||||
{
|
||||
GameData.GameDataSnapshot snapshot = new GameData.GameDataSnapshot();
|
||||
PersistentRegistryManager.GameDataSnapshot snapshot = new PersistentRegistryManager.GameDataSnapshot();
|
||||
NBTTagCompound regs = tag.getCompoundTag("Registries");
|
||||
for (String key : (Set<String>)regs.getKeySet())
|
||||
for (String key : regs.getKeySet())
|
||||
{
|
||||
GameData.GameDataSnapshot.Entry entry = new GameData.GameDataSnapshot.Entry();
|
||||
snapshot.entries.put(key, entry);
|
||||
PersistentRegistryManager.GameDataSnapshot.Entry entry = new PersistentRegistryManager.GameDataSnapshot.Entry();
|
||||
if ("fml:blocks".equals(key)) key = "minecraft:blocks";
|
||||
if ("fml:items".equals(key)) key = "minecraft:items";
|
||||
if ("fmlgr:villagerprofessions".equals(key)) key = "minecraft:villagerprofessions";
|
||||
snapshot.entries.put(new ResourceLocation(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"));
|
||||
entry.ids.put(new ResourceLocation(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"));
|
||||
entry.aliases.put(new ResourceLocation(e.getString("K")), new ResourceLocation(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"));
|
||||
entry.substitutions.add(new ResourceLocation(e.getString("K")));
|
||||
}
|
||||
|
||||
int[] blocked = regs.getCompoundTag(key).getIntArray("blocked");
|
||||
|
@ -318,7 +296,7 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
entry.blocked.add(i);
|
||||
}
|
||||
}
|
||||
failedElements = GameData.injectSnapshot(snapshot, true, true);
|
||||
failedElements = PersistentRegistryManager.injectSnapshot(snapshot, true, true);
|
||||
}
|
||||
|
||||
if (failedElements != null && !failedElements.isEmpty())
|
||||
|
|
|
@ -21,12 +21,12 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.common.LoaderState.ModState;
|
||||
import net.minecraftforge.fml.common.ModContainer.Disableable;
|
||||
import net.minecraftforge.fml.common.ProgressManager.ProgressBar;
|
||||
|
@ -38,10 +38,7 @@ import net.minecraftforge.fml.common.event.FMLModIdMappingEvent;
|
|||
import net.minecraftforge.fml.common.event.FMLMissingMappingsEvent.MissingMapping;
|
||||
import net.minecraftforge.fml.common.functions.ArtifactVersionNameFunction;
|
||||
import net.minecraftforge.fml.common.functions.ModIdFunction;
|
||||
import net.minecraftforge.fml.common.registry.GameData;
|
||||
import net.minecraftforge.fml.common.registry.GameRegistry;
|
||||
import net.minecraftforge.fml.common.registry.ItemStackHolderInjector;
|
||||
import net.minecraftforge.fml.common.registry.ObjectHolderRegistry;
|
||||
import net.minecraftforge.fml.common.registry.*;
|
||||
import net.minecraftforge.fml.common.registry.GameRegistry.Type;
|
||||
import net.minecraftforge.fml.common.toposort.ModSorter;
|
||||
import net.minecraftforge.fml.common.toposort.ModSortingException;
|
||||
|
@ -738,7 +735,7 @@ public class Loader
|
|||
progressBar.step("Finishing up");
|
||||
modController.transition(LoaderState.AVAILABLE, false);
|
||||
modController.distributeStateMessage(LoaderState.AVAILABLE);
|
||||
GameData.freezeData();
|
||||
PersistentRegistryManager.freezeData();
|
||||
FMLLog.info("Forge Mod Loader has successfully loaded %d mod%s", mods.size(), mods.size() == 1 ? "" : "s");
|
||||
progressBar.step("Completing Minecraft initialization");
|
||||
}
|
||||
|
@ -839,7 +836,7 @@ public class Loader
|
|||
|
||||
public void serverStopped()
|
||||
{
|
||||
GameData.revertToFrozen();
|
||||
PersistentRegistryManager.revertToFrozen();
|
||||
modController.distributeStateMessage(LoaderState.SERVER_STOPPED);
|
||||
modController.transition(LoaderState.SERVER_STOPPED, true);
|
||||
modController.transition(LoaderState.AVAILABLE, true);
|
||||
|
@ -914,8 +911,7 @@ public class Loader
|
|||
* @param gameData GameData instance where the new map's config is to be loaded into.
|
||||
* @return List with the mapping results.
|
||||
*/
|
||||
public List<String> fireMissingMappingEvent(LinkedHashMap<String, Integer> missingBlocks, LinkedHashMap<String, Integer> missingItems,
|
||||
boolean isLocalWorld, GameData gameData, Map<String, Integer[]> remapBlocks, Map<String, Integer[]> remapItems)
|
||||
public List<String> fireMissingMappingEvent(Map<ResourceLocation, Integer> missingBlocks, Map<ResourceLocation, Integer> missingItems, boolean isLocalWorld, Map<ResourceLocation, Integer[]> remapBlocks, Map<ResourceLocation, Integer[]> remapItems)
|
||||
{
|
||||
if (missingBlocks.isEmpty() && missingItems.isEmpty()) // nothing to do
|
||||
{
|
||||
|
@ -925,15 +921,15 @@ public class Loader
|
|||
FMLLog.fine("There are %d mappings missing - attempting a mod remap", missingBlocks.size() + missingItems.size());
|
||||
ArrayListMultimap<String, MissingMapping> missingMappings = ArrayListMultimap.create();
|
||||
|
||||
for (Map.Entry<String, Integer> mapping : missingBlocks.entrySet())
|
||||
for (Map.Entry<ResourceLocation, Integer> mapping : missingBlocks.entrySet())
|
||||
{
|
||||
MissingMapping m = new MissingMapping(GameRegistry.Type.BLOCK, mapping.getKey(), mapping.getValue());
|
||||
missingMappings.put(m.name.substring(0, m.name.indexOf(':')), m);
|
||||
missingMappings.put(m.resourceLocation.getResourceDomain(), m);
|
||||
}
|
||||
for (Map.Entry<String, Integer> mapping : missingItems.entrySet())
|
||||
for (Map.Entry<ResourceLocation, Integer> mapping : missingItems.entrySet())
|
||||
{
|
||||
MissingMapping m = new MissingMapping(GameRegistry.Type.ITEM, mapping.getKey(), mapping.getValue());
|
||||
missingMappings.put(m.name.substring(0, m.name.indexOf(':')), m);
|
||||
missingMappings.put(m.resourceLocation.getResourceDomain(), m);
|
||||
}
|
||||
|
||||
FMLMissingMappingsEvent missingEvent = new FMLMissingMappingsEvent(missingMappings);
|
||||
|
@ -975,12 +971,12 @@ public class Loader
|
|||
}
|
||||
}
|
||||
|
||||
return GameData.processIdRematches(missingMappings.values(), isLocalWorld, gameData, remapBlocks, remapItems);
|
||||
return PersistentRegistryManager.processIdRematches(missingMappings.values(), isLocalWorld, remapBlocks, remapItems);
|
||||
}
|
||||
|
||||
public void fireRemapEvent(Map<String, Integer[]> remapBlocks, Map<String, Integer[]> remapItems)
|
||||
public void fireRemapEvent(Map<ResourceLocation, Integer[]> remapBlocks, Map<ResourceLocation, Integer[]> remapItems)
|
||||
{
|
||||
modController.propogateStateMessage(new FMLModIdMappingEvent(remapBlocks, remapItems));
|
||||
modController.propogateStateMessage(new FMLModIdMappingEvent(remapBlocks, remapItems));
|
||||
}
|
||||
|
||||
public void runtimeDisableMod(String modId)
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.List;
|
|||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.common.ModContainer;
|
||||
import net.minecraftforge.fml.common.registry.GameData;
|
||||
import net.minecraftforge.fml.common.registry.GameRegistry;
|
||||
|
@ -63,14 +64,16 @@ public class FMLMissingMappingsEvent extends FMLEvent {
|
|||
public final GameRegistry.Type type;
|
||||
public final String name;
|
||||
public final int id;
|
||||
public final ResourceLocation resourceLocation;
|
||||
private Action action = Action.DEFAULT;
|
||||
private Object target;
|
||||
|
||||
public MissingMapping(GameRegistry.Type type, String name, int id)
|
||||
public MissingMapping(GameRegistry.Type type, ResourceLocation name, int id)
|
||||
{
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.name = name.toString();
|
||||
this.id = id;
|
||||
this.resourceLocation = name;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.Map.Entry;
|
|||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Called whenever the ID mapping might have changed. If you register for this event, you
|
||||
|
@ -30,25 +31,28 @@ public class FMLModIdMappingEvent extends FMLEvent {
|
|||
public final int newId;
|
||||
public final String tag;
|
||||
public final RemapTarget remapTarget;
|
||||
public ModRemapping(int oldId, int newId, String tag, RemapTarget type)
|
||||
public final ResourceLocation resourceLocation;
|
||||
|
||||
public ModRemapping(int oldId, int newId, ResourceLocation tag, RemapTarget type)
|
||||
{
|
||||
this.oldId = oldId;
|
||||
this.newId = newId;
|
||||
this.tag = tag;
|
||||
this.tag = tag.toString();
|
||||
this.remapTarget = type;
|
||||
this.resourceLocation = tag;
|
||||
}
|
||||
|
||||
}
|
||||
public final ImmutableList<ModRemapping> remappedIds;
|
||||
|
||||
public FMLModIdMappingEvent(Map<String, Integer[]> blocks, Map<String, Integer[]> items)
|
||||
public FMLModIdMappingEvent(Map<ResourceLocation, Integer[]> blocks, Map<ResourceLocation, Integer[]> items)
|
||||
{
|
||||
List<ModRemapping> remappings = Lists.newArrayList();
|
||||
for (Entry<String, Integer[]> mapping : blocks.entrySet())
|
||||
for (Entry<ResourceLocation, Integer[]> mapping : blocks.entrySet())
|
||||
{
|
||||
remappings.add(new ModRemapping(mapping.getValue()[0], mapping.getValue()[1], mapping.getKey(), RemapTarget.BLOCK));
|
||||
}
|
||||
for (Entry<String, Integer[]> mapping : items.entrySet())
|
||||
for (Entry<ResourceLocation, Integer[]> mapping : items.entrySet())
|
||||
{
|
||||
remappings.add(new ModRemapping(mapping.getValue()[0], mapping.getValue()[1], mapping.getKey(), RemapTarget.ITEM));
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package net.minecraftforge.fml.common.network.handshake;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
|
@ -9,6 +10,7 @@ import net.minecraftforge.fml.common.network.handshake.FMLHandshakeMessage.Serve
|
|||
import net.minecraftforge.fml.common.network.internal.FMLMessage;
|
||||
import net.minecraftforge.fml.common.network.internal.FMLNetworkHandler;
|
||||
import net.minecraftforge.fml.common.registry.GameData;
|
||||
import net.minecraftforge.fml.common.registry.PersistentRegistryManager;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
@ -94,14 +96,14 @@ enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
|
|||
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
{
|
||||
FMLHandshakeMessage.RegistryData pkt = (FMLHandshakeMessage.RegistryData)msg;
|
||||
GameData.GameDataSnapshot snap = ctx.channel().attr(NetworkDispatcher.FML_GAMEDATA_SNAPSHOT).get();
|
||||
PersistentRegistryManager.GameDataSnapshot snap = ctx.channel().attr(NetworkDispatcher.FML_GAMEDATA_SNAPSHOT).get();
|
||||
if (snap == null)
|
||||
{
|
||||
snap = new GameData.GameDataSnapshot();
|
||||
snap = new PersistentRegistryManager.GameDataSnapshot();
|
||||
ctx.channel().attr(NetworkDispatcher.FML_GAMEDATA_SNAPSHOT).set(snap);
|
||||
}
|
||||
|
||||
GameData.GameDataSnapshot.Entry entry = new GameData.GameDataSnapshot.Entry();
|
||||
PersistentRegistryManager.GameDataSnapshot.Entry entry = new PersistentRegistryManager.GameDataSnapshot.Entry();
|
||||
entry.ids.putAll(pkt.getIdMap());
|
||||
entry.substitutions.addAll(pkt.getSubstitutions());
|
||||
snap.entries.put(pkt.getName(), entry);
|
||||
|
@ -114,7 +116,7 @@ enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
|
|||
|
||||
ctx.channel().attr(NetworkDispatcher.FML_GAMEDATA_SNAPSHOT).remove();
|
||||
|
||||
List<String> locallyMissing = GameData.injectSnapshot(snap, false, false);
|
||||
List<String> locallyMissing = PersistentRegistryManager.injectSnapshot(snap, false, false);
|
||||
if (!locallyMissing.isEmpty())
|
||||
{
|
||||
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
||||
|
@ -156,7 +158,7 @@ enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
|
|||
{
|
||||
if (msg instanceof FMLHandshakeMessage.HandshakeReset)
|
||||
{
|
||||
GameData.revertToFrozen();
|
||||
PersistentRegistryManager.revertToFrozen();
|
||||
return HELLO;
|
||||
}
|
||||
return this;
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.util.Map.Entry;
|
|||
import java.util.Set;
|
||||
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.ModContainer;
|
||||
import net.minecraftforge.fml.common.network.ByteBufUtils;
|
||||
|
@ -22,6 +23,7 @@ import com.google.common.base.Joiner;
|
|||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import net.minecraftforge.fml.common.registry.PersistentRegistryManager;
|
||||
|
||||
public abstract class FMLHandshakeMessage {
|
||||
public static FMLProxyPacket makeCustomChannelRegistration(Set<String> channels)
|
||||
|
@ -158,7 +160,7 @@ public abstract class FMLHandshakeMessage {
|
|||
|
||||
}
|
||||
|
||||
public RegistryData(boolean hasMore, String name, GameData.GameDataSnapshot.Entry entry)
|
||||
public RegistryData(boolean hasMore, ResourceLocation name, PersistentRegistryManager.GameDataSnapshot.Entry entry)
|
||||
{
|
||||
this.hasMore = hasMore;
|
||||
this.name = name;
|
||||
|
@ -167,22 +169,22 @@ public abstract class FMLHandshakeMessage {
|
|||
}
|
||||
|
||||
private boolean hasMore;
|
||||
private String name;
|
||||
private Map<String,Integer> ids;
|
||||
private Set<String> substitutions;
|
||||
private ResourceLocation name;
|
||||
private Map<ResourceLocation, Integer> ids;
|
||||
private Set<ResourceLocation> substitutions;
|
||||
|
||||
@Override
|
||||
public void fromBytes(ByteBuf buffer)
|
||||
{
|
||||
this.hasMore = buffer.readBoolean();
|
||||
this.name = ByteBufUtils.readUTF8String(buffer);
|
||||
this.name = new ResourceLocation(ByteBufUtils.readUTF8String(buffer));
|
||||
|
||||
int length = ByteBufUtils.readVarInt(buffer, 3);
|
||||
ids = Maps.newHashMap();
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
ids.put(ByteBufUtils.readUTF8String(buffer), ByteBufUtils.readVarInt(buffer, 3));
|
||||
ids.put(new ResourceLocation(ByteBufUtils.readUTF8String(buffer)), ByteBufUtils.readVarInt(buffer, 3));
|
||||
}
|
||||
|
||||
length = ByteBufUtils.readVarInt(buffer, 3);
|
||||
|
@ -190,7 +192,7 @@ public abstract class FMLHandshakeMessage {
|
|||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
substitutions.add(ByteBufUtils.readUTF8String(buffer));
|
||||
substitutions.add(new ResourceLocation(ByteBufUtils.readUTF8String(buffer)));
|
||||
}
|
||||
//if (!buffer.isReadable()) return; // In case we expand
|
||||
}
|
||||
|
@ -199,31 +201,31 @@ public abstract class FMLHandshakeMessage {
|
|||
public void toBytes(ByteBuf buffer)
|
||||
{
|
||||
buffer.writeBoolean(this.hasMore);
|
||||
ByteBufUtils.writeUTF8String(buffer, this.name);
|
||||
ByteBufUtils.writeUTF8String(buffer, this.name.toString());
|
||||
|
||||
ByteBufUtils.writeVarInt(buffer, ids.size(), 3);
|
||||
for (Entry<String, Integer> entry: ids.entrySet())
|
||||
for (Entry<ResourceLocation, Integer> entry: ids.entrySet())
|
||||
{
|
||||
ByteBufUtils.writeUTF8String(buffer, entry.getKey());
|
||||
ByteBufUtils.writeUTF8String(buffer, entry.getKey().toString());
|
||||
ByteBufUtils.writeVarInt(buffer, entry.getValue(), 3);
|
||||
}
|
||||
|
||||
ByteBufUtils.writeVarInt(buffer, substitutions.size(), 3);
|
||||
for (String entry: substitutions)
|
||||
for (ResourceLocation entry: substitutions)
|
||||
{
|
||||
ByteBufUtils.writeUTF8String(buffer, entry);
|
||||
ByteBufUtils.writeUTF8String(buffer, entry.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String,Integer> getIdMap()
|
||||
public Map<ResourceLocation,Integer> getIdMap()
|
||||
{
|
||||
return ids;
|
||||
}
|
||||
public Set<String> getSubstitutions()
|
||||
public Set<ResourceLocation> getSubstitutions()
|
||||
{
|
||||
return substitutions;
|
||||
}
|
||||
public String getName()
|
||||
public ResourceLocation getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
|
|
@ -4,12 +4,14 @@ import java.util.Iterator;
|
|||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
import net.minecraftforge.fml.common.network.internal.FMLMessage;
|
||||
import net.minecraftforge.fml.common.network.internal.FMLNetworkHandler;
|
||||
import net.minecraftforge.fml.common.registry.GameData;
|
||||
import net.minecraftforge.fml.common.registry.PersistentRegistryManager;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
@ -61,11 +63,11 @@ enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
|
|||
{
|
||||
if (!ctx.channel().attr(NetworkDispatcher.IS_LOCAL).get())
|
||||
{
|
||||
GameData.GameDataSnapshot snapshot = GameData.takeSnapshot();
|
||||
Iterator<Map.Entry<String, GameData.GameDataSnapshot.Entry>> itr = snapshot.entries.entrySet().iterator();
|
||||
PersistentRegistryManager.GameDataSnapshot snapshot = PersistentRegistryManager.takeSnapshot();
|
||||
Iterator<Map.Entry<ResourceLocation, PersistentRegistryManager.GameDataSnapshot.Entry>> itr = snapshot.entries.entrySet().iterator();
|
||||
while (itr.hasNext())
|
||||
{
|
||||
Entry<String, GameData.GameDataSnapshot.Entry> e = itr.next();
|
||||
Entry<ResourceLocation, PersistentRegistryManager.GameDataSnapshot.Entry> e = itr.next();
|
||||
ctx.writeAndFlush(new FMLHandshakeMessage.RegistryData(itr.hasNext(), e.getKey(), e.getValue())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraftforge.fml.common.registry.PersistentRegistryManager;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
|
@ -82,7 +83,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
|
|||
|
||||
public static final AttributeKey<NetworkDispatcher> FML_DISPATCHER = AttributeKey.valueOf("fml:dispatcher");
|
||||
public static final AttributeKey<Boolean> IS_LOCAL = AttributeKey.valueOf("fml:isLocal");
|
||||
public static final AttributeKey<GameData.GameDataSnapshot> FML_GAMEDATA_SNAPSHOT = AttributeKey.valueOf("fml:gameDataSnapshot");
|
||||
public static final AttributeKey<PersistentRegistryManager.GameDataSnapshot> FML_GAMEDATA_SNAPSHOT = AttributeKey.valueOf("fml:gameDataSnapshot");
|
||||
public final NetworkManager manager;
|
||||
private final ServerConfigurationManager scm;
|
||||
private EntityPlayerMP player;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package net.minecraftforge.fml.common.registry;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class ExistingSubstitutionException extends Exception {
|
||||
public ExistingSubstitutionException(String fromName, Object toReplace) {
|
||||
public ExistingSubstitutionException(ResourceLocation fromName, Object toReplace) {
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.minecraftforge.fml.common.registry;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collections;
|
||||
|
@ -8,7 +9,10 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.*;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
|
@ -17,128 +21,128 @@ import net.minecraft.item.Item;
|
|||
import net.minecraft.item.ItemBanner;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
import net.minecraft.util.ObjectIntIdentityMap;
|
||||
import net.minecraft.util.RegistryNamespaced;
|
||||
import net.minecraft.util.RegistryNamespacedDefaultedByKey;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.functions.GenericIterableFactory;
|
||||
import net.minecraftforge.fml.common.registry.RegistryDelegate.Delegate;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.base.Function;
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"}) // cpw is working on these classes just shut them up for now.
|
||||
public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaultedByKey {
|
||||
public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaultedByKey<ResourceLocation,I> {
|
||||
public static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("fml.debugRegistryEntries", "false"));
|
||||
private final Class<I> superType;
|
||||
private Object optionalDefaultKey;
|
||||
private final boolean isDelegated;
|
||||
private final Field delegateAccessor;
|
||||
private ResourceLocation optionalDefaultKey;
|
||||
private I optionalDefaultObject;
|
||||
private int maxId;
|
||||
private int minId;
|
||||
// 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<String, String> aliases = new HashMap<String, String>();
|
||||
private BiMap<String, I> persistentSubstitutions;
|
||||
private BiMap<String, I> activeSubstitutions = HashBiMap.create();
|
||||
/**
|
||||
* Aliases are resource location to resource location pointers, allowing for alternative names to be supplied
|
||||
* pointing at the same thing. They are used to allow programmatic migration of an ID.
|
||||
*/
|
||||
private final Map <ResourceLocation, ResourceLocation> aliases = Maps.newHashMap();
|
||||
/**
|
||||
* Persistent substitutions are the mechanism to allow mods to override specific behaviours with new behaviours.
|
||||
*/
|
||||
private final BiMap<ResourceLocation, I> persistentSubstitutions = HashBiMap.create();
|
||||
/**
|
||||
* This is the current active substitution set for a particular world. It will change as worlds come and go.
|
||||
*/
|
||||
private final BiMap<ResourceLocation, I> activeSubstitutions = HashBiMap.create();
|
||||
/**
|
||||
* The list of IDs blocked for this world. IDs will never be allocated in this set.
|
||||
*/
|
||||
private final Set<Integer> blockedIds = Sets.newHashSet();
|
||||
|
||||
FMLControlledNamespacedRegistry(Object defaultKey, int maxIdValue, int minIdValue, Class<I> type)
|
||||
private final BitSet availabilityMap;
|
||||
FMLControlledNamespacedRegistry(ResourceLocation defaultKey, int maxIdValue, int minIdValue, Class<I> type, boolean isDelegated)
|
||||
{
|
||||
super(defaultKey);
|
||||
this.superType = type;
|
||||
this.optionalDefaultKey = defaultKey;
|
||||
this.maxId = maxIdValue;
|
||||
this.minId = minIdValue;
|
||||
this.availabilityMap = new BitSet(maxIdValue + 1);
|
||||
this.isDelegated = isDelegated;
|
||||
if (this.isDelegated) {
|
||||
try {
|
||||
this.delegateAccessor = type.getField("delegate");
|
||||
} catch (NoSuchFieldException e) {
|
||||
FMLLog.log(Level.ERROR, e, "Delegate class identified with missing delegate field");
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
} else {
|
||||
this.delegateAccessor = null;
|
||||
}
|
||||
}
|
||||
|
||||
void validateContent(int maxId, String type, BitSet availabilityMap, Set<Integer> blockedIds, FMLControlledNamespacedRegistry<Block> iBlockRegistry)
|
||||
void validateContent(ResourceLocation registryName)
|
||||
{
|
||||
for (I obj : typeSafeIterable())
|
||||
{
|
||||
int id = getId(obj);
|
||||
Object name = getNameForObject(obj);
|
||||
ResourceLocation name = getNameForObject(obj);
|
||||
boolean isSubstituted = activeSubstitutions.containsKey(name);
|
||||
|
||||
// name lookup failed -> obj is not in the obj<->name map
|
||||
if (name == null) throw new IllegalStateException(String.format("Registry entry for %s %s, id %d, doesn't yield a name.", type, obj, id));
|
||||
|
||||
ResourceLocation loc = (name instanceof ResourceLocation) ? (ResourceLocation)name : null;
|
||||
String nameS = (name instanceof String) ? (String)name : (loc != null ? name.toString() : null);
|
||||
if (loc == null && nameS == null) throw new IllegalStateException(String.format("Registry entry for %s %s name is invalid, must be a String or ResourceLocation %s", type, obj, name));
|
||||
|
||||
if (name == null) throw new IllegalStateException(String.format("Registry entry for %s %s, id %d, doesn't yield a name.", registryName, obj, id));
|
||||
// id lookup failed -> obj is not in the obj<->id map
|
||||
if (!isSubstituted && id < 0) throw new IllegalStateException(String.format("Registry entry for %s %s, name %s, doesn't yield an id.", type, obj, name));
|
||||
if (!isSubstituted && id < 0) throw new IllegalStateException(String.format("Registry entry for %s %s, name %s, doesn't yield an id.", registryName, obj, name));
|
||||
// id is too high
|
||||
if (id > maxId) throw new IllegalStateException(String.format("Registry entry for %s %s, name %s uses the too large id %d.", type, obj, name));
|
||||
// empty name
|
||||
if (name.toString().isEmpty()) throw new IllegalStateException(String.format("Registry entry for %s %s, id %d, yields an empty name.", type, obj, id));
|
||||
// non-prefixed name
|
||||
if (name.toString().indexOf(':') == -1) throw new IllegalStateException(String.format("Registry entry for %s %s, id %d, has the non-prefixed name %s.", type, obj, id, name));
|
||||
if (id > maxId) throw new IllegalStateException(String.format("Registry entry for %s %s, name %s uses the too large id %d.", registryName, obj, name, id));
|
||||
// the rest of the tests don't really work for substituted items or blocks
|
||||
if (isSubstituted) continue;
|
||||
// id -> obj lookup is inconsistent
|
||||
if (getRaw(id) != obj) throw new IllegalStateException(String.format("Registry entry for id %d, name %s, doesn't yield the expected %s %s.", id, name, type, obj));
|
||||
if (getRaw(id) != obj) throw new IllegalStateException(String.format("Registry entry for id %d, name %s, doesn't yield the expected %s %s.", id, name, registryName, obj));
|
||||
// name -> obj lookup is inconsistent
|
||||
if (getRaw(nameS) != obj ) throw new IllegalStateException(String.format("Registry entry for name %s, id %d, doesn't yield the expected %s %s.", name, id, type, obj));
|
||||
if (getRaw(name) != obj ) throw new IllegalStateException(String.format("Registry entry for name %s, id %d, doesn't yield the expected %s %s.", name, id, registryName, obj));
|
||||
// name -> id lookup is inconsistent
|
||||
if (getId(nameS) != id) throw new IllegalStateException(String.format("Registry entry for name %s doesn't yield the expected id %d.", name, id));
|
||||
// id isn't marked as unavailable
|
||||
if (!availabilityMap.get(id)) throw new IllegalStateException(String.format("Registry entry for %s %s, id %d, name %s, marked as empty.", type, obj, id, name));
|
||||
if (getId(name) != id) throw new IllegalStateException(String.format("Registry entry for name %s doesn't yield the expected id %d.", name, id));
|
||||
// entry is blocked, thus should be empty
|
||||
if (blockedIds.contains(id)) throw new IllegalStateException(String.format("Registry entry for %s %s, id %d, name %s, marked as dangling.", type, obj, id, name));
|
||||
|
||||
if (obj instanceof ItemBlock && !(obj instanceof ItemBanner)) //Dammet Mojang not linking Banners
|
||||
{
|
||||
Block block = ((ItemBlock) obj).block;
|
||||
|
||||
// verify matching block entry
|
||||
if (iBlockRegistry.getId(block) != id)
|
||||
{
|
||||
throw new IllegalStateException(String.format("Registry entry for ItemBlock %s, id %d, is missing or uses the non-matching id %d.", obj, id, iBlockRegistry.getId(block)));
|
||||
}
|
||||
// verify id range
|
||||
if (id > GameData.MAX_BLOCK_ID) throw new IllegalStateException(String.format("ItemBlock %s uses the id %d outside the block id range", name, id));
|
||||
}
|
||||
if (blockedIds.contains(id)) throw new IllegalStateException(String.format("Registry entry for %s %s, id %d, name %s, marked as dangling.", registryName, obj, id, name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void setFrom(FMLControlledNamespacedRegistry<?> registry) {
|
||||
set((FMLControlledNamespacedRegistry<I>) registry);
|
||||
}
|
||||
void set(FMLControlledNamespacedRegistry<I> registry)
|
||||
@SuppressWarnings("unchecked")
|
||||
void set(FMLControlledNamespacedRegistry<I> otherRegistry)
|
||||
{
|
||||
if (this.superType != registry.superType) throw new IllegalArgumentException("incompatible registry");
|
||||
if (this.superType != otherRegistry.superType) throw new IllegalArgumentException("incompatible registry");
|
||||
|
||||
this.optionalDefaultKey = registry.optionalDefaultKey;
|
||||
this.maxId = registry.maxId;
|
||||
this.minId = registry.minId;
|
||||
this.optionalDefaultKey = otherRegistry.optionalDefaultKey;
|
||||
this.maxId = otherRegistry.maxId;
|
||||
this.minId = otherRegistry.minId;
|
||||
this.aliases.clear();
|
||||
this.aliases.putAll(registry.aliases);
|
||||
this.aliases.putAll(otherRegistry.aliases);
|
||||
this.activeSubstitutions.clear();
|
||||
|
||||
underlyingIntegerMap = new ObjectIntIdentityMap();
|
||||
underlyingIntegerMap = new ObjectIntIdentityMap<I>();
|
||||
registryObjects.clear();
|
||||
|
||||
for (I thing : registry.typeSafeIterable())
|
||||
for (I thing : otherRegistry.typeSafeIterable())
|
||||
{
|
||||
addObjectRaw(registry.getId(thing), registry.getNameForObject(thing), thing);
|
||||
addObjectRaw(otherRegistry.getId(thing), otherRegistry.getNameForObject(thing), thing);
|
||||
}
|
||||
this.activeSubstitutions.putAll(registry.activeSubstitutions);
|
||||
this.activeSubstitutions.putAll(otherRegistry.activeSubstitutions);
|
||||
}
|
||||
|
||||
// public api
|
||||
|
||||
/**
|
||||
* Add an object to the registry, trying to use the specified id.
|
||||
* This is required, to re-route vanilla block and item registration through to
|
||||
* the {@link #add} method.
|
||||
*
|
||||
* @deprecated register through {@link GameRegistry} instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public void register(int id, Object name, Object thing)
|
||||
public void register(int id, ResourceLocation name, I thing)
|
||||
{
|
||||
Validate.isInstanceOf(ResourceLocation.class, name);
|
||||
GameData.getMain().register(thing, name.toString(), id);
|
||||
add(id, name, thing);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,17 +152,13 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public void putObject(Object objName, Object obj)
|
||||
public void putObject(ResourceLocation name, I thing)
|
||||
{
|
||||
String name = objName.toString();
|
||||
I thing = superType.cast(obj);
|
||||
|
||||
if (name == null) throw new NullPointerException("Can't use a null-name for the registry.");
|
||||
if (name.isEmpty()) throw new IllegalArgumentException("Can't use an empty name for the registry.");
|
||||
if (thing == null) throw new NullPointerException("Can't add null-object to the registry.");
|
||||
|
||||
name = new ResourceLocation(name).toString();
|
||||
Object existingName = getNameForObject(thing);
|
||||
ResourceLocation existingName = getNameForObject(thing);
|
||||
|
||||
if (existingName == null)
|
||||
{
|
||||
|
@ -171,7 +171,7 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
else
|
||||
{
|
||||
FMLLog.bigWarning("Ignoring putObject(%s, %s), adding alias to %s instead", name, thing, existingName);
|
||||
addAlias(name, existingName.toString());
|
||||
addAlias(name, existingName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,11 +184,9 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
* @return Registered object of the default object if it wasn't found-
|
||||
*/
|
||||
@Override
|
||||
public I getObject(Object name)
|
||||
public I getObject(ResourceLocation name)
|
||||
{
|
||||
I object = null;
|
||||
if (name instanceof ResourceLocation) object = getRaw((ResourceLocation)name);
|
||||
if (name instanceof String) object = getRaw((String)name);
|
||||
I object = getRaw(name);
|
||||
return object == null ? this.optionalDefaultObject : object;
|
||||
}
|
||||
|
||||
|
@ -207,24 +205,6 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
return object == null ? this.optionalDefaultObject : object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use getObjectById instead
|
||||
*/
|
||||
@Deprecated
|
||||
public I get(int id)
|
||||
{
|
||||
return getObjectById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use getObject instead
|
||||
*/
|
||||
@Deprecated
|
||||
public I get(String name)
|
||||
{
|
||||
return getObject(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id for the specified object.
|
||||
*
|
||||
|
@ -249,27 +229,7 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
*/
|
||||
public I getRaw(int id)
|
||||
{
|
||||
return cast(super.getObjectById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* superType.cast appears to be expensive. Skip it for speed?
|
||||
* @param obj
|
||||
* @return
|
||||
*/
|
||||
private I cast(Object obj)
|
||||
{
|
||||
return (I)(obj);
|
||||
}
|
||||
/**
|
||||
* Get the object identified by the specified name.
|
||||
*
|
||||
* @param name Block/Item name.
|
||||
* @return Block/Item object or null if it wasn't found.
|
||||
*/
|
||||
public I getRaw(String name)
|
||||
{
|
||||
return getRaw(new ResourceLocation(name));
|
||||
return super.getObjectById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -278,13 +238,13 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
* @param name Block/Item name.
|
||||
* @return Block/Item object or null if it wasn't found.
|
||||
*/
|
||||
private I getRaw(ResourceLocation loc)
|
||||
private I getRaw(ResourceLocation name)
|
||||
{
|
||||
I ret = superType.cast(super.getObject(loc));
|
||||
I ret = super.getObject(name);
|
||||
|
||||
if (ret == null) // no match, try aliases recursively
|
||||
{
|
||||
String name = aliases.get(loc.toString());
|
||||
name = aliases.get(name);
|
||||
|
||||
if (name != null) return getRaw(name);
|
||||
}
|
||||
|
@ -301,7 +261,7 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
* @return true if a matching entry was found.
|
||||
*/
|
||||
@Override
|
||||
public boolean containsKey(Object name)
|
||||
public boolean containsKey(ResourceLocation name)
|
||||
{
|
||||
boolean ret = super.containsKey(name);
|
||||
|
||||
|
@ -326,7 +286,7 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
* @param itemName Block/Item registry name.
|
||||
* @return Block/Item id or -1 if it wasn't found.
|
||||
*/
|
||||
public int getId(String itemName)
|
||||
public int getId(ResourceLocation itemName)
|
||||
{
|
||||
I obj = getRaw(itemName);
|
||||
if (obj == null) return -1;
|
||||
|
@ -334,15 +294,6 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
return getId(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use containsKey instead
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean contains(String itemName)
|
||||
{
|
||||
return containsKey(itemName);
|
||||
}
|
||||
|
||||
/*
|
||||
* This iterator is used by FML to visit the actual block sets, it should use the super.iterator method instead
|
||||
* Compare #iterator()
|
||||
|
@ -354,44 +305,36 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
|
||||
// internal
|
||||
|
||||
public void serializeInto(Map<String, Integer> idMapping) // for saving
|
||||
public void serializeIds(Map<ResourceLocation, Integer> idMapping) // for saving
|
||||
{
|
||||
for (I thing : this.typeSafeIterable())
|
||||
{
|
||||
idMapping.put(getNameForObject(thing).toString(), getId(thing));
|
||||
idMapping.put(getNameForObject(thing), getId(thing));
|
||||
}
|
||||
}
|
||||
public void serializeAliases(Map<String, String> map)
|
||||
public void serializeAliases(Map<ResourceLocation, ResourceLocation> map)
|
||||
{
|
||||
map.putAll(this.aliases);
|
||||
}
|
||||
public void serializeSubstitutions(Set<String> set)
|
||||
|
||||
public void serializeSubstitutions(Set<ResourceLocation> set)
|
||||
{
|
||||
set.addAll(activeSubstitutions.keySet());
|
||||
}
|
||||
|
||||
private BitSet internalAvailabilityMap = new BitSet();
|
||||
|
||||
int add(int id, String name, Object thing) {
|
||||
return add(id, name, superType.cast(thing), internalAvailabilityMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the specified object to the registry.
|
||||
*
|
||||
* @param id ID to use if available, auto-assigned otherwise.
|
||||
* @param name Name to use, prefixed by the mod id.
|
||||
* @param thing Object to add.
|
||||
* @param availabilityMap Map marking available IDs for auto assignment.
|
||||
* @return ID eventually allocated.
|
||||
*/
|
||||
int add(int id, String name, I thing, BitSet availabilityMap)
|
||||
int add(int id, ResourceLocation name, I thing)
|
||||
{
|
||||
if (name == null) throw new NullPointerException(String.format("Can't use a null-name for the registry, object %s.", thing));
|
||||
if (name.isEmpty()) throw new IllegalArgumentException(String.format("Can't use an empty name for the registry, object %s.", thing));
|
||||
if (name.indexOf(':') == -1) throw new IllegalArgumentException(String.format("Can't add the name (%s) without a prefix, object %s", name, thing));
|
||||
if (thing == null) throw new NullPointerException(String.format("Can't add null-object to the registry, name %s.", name));
|
||||
if (optionalDefaultKey != null && optionalDefaultKey.toString().equals(name) && this.optionalDefaultObject == null)
|
||||
if (optionalDefaultKey != null && optionalDefaultKey.equals(name) && this.optionalDefaultObject == null)
|
||||
{
|
||||
this.optionalDefaultObject = thing;
|
||||
}
|
||||
|
@ -421,43 +364,50 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
if (getId(thing) >= 0) // duplicate object - but only if it's not being substituted
|
||||
{
|
||||
int foundId = getId(thing);
|
||||
Object otherThing = getRaw(foundId);
|
||||
I otherThing = getRaw(foundId);
|
||||
throw new IllegalArgumentException(String.format("The object %s{%x} has been registered twice, using the names %s and %s. (Other object at this id is %s{%x})", thing, System.identityHashCode(thing), getNameForObject(thing), name, otherThing, System.identityHashCode(otherThing)));
|
||||
}
|
||||
if (GameData.isFrozen(this))
|
||||
if (PersistentRegistryManager.isFrozen(this))
|
||||
{
|
||||
FMLLog.bigWarning("The object %s (name %s) is being added too late.", thing, name);
|
||||
}
|
||||
|
||||
if (activeSubstitutions.containsKey(name))
|
||||
{
|
||||
I oldThing = thing;
|
||||
thing = activeSubstitutions.get(name);
|
||||
if (DEBUG) FMLLog.getLogger().log(Level.DEBUG, "Active substitution: {} {}@{} -> {}@{}",name, oldThing.getClass().getName(), System.identityHashCode(oldThing), thing.getClass().getName(), System.identityHashCode(thing));
|
||||
}
|
||||
addObjectRaw(idToUse, new ResourceLocation(name), thing);
|
||||
|
||||
|
||||
addObjectRaw(idToUse, name, thing);
|
||||
if (isDelegated)
|
||||
{
|
||||
getExistingDelegate(thing).setResourceName(name);
|
||||
}
|
||||
if (DEBUG)
|
||||
FMLLog.finer("Registry add: %s %d %s (req. id %d)", name, idToUse, thing, id);
|
||||
return idToUse;
|
||||
}
|
||||
|
||||
void addAlias(String from, String to)
|
||||
void addAlias(ResourceLocation from, ResourceLocation to)
|
||||
{
|
||||
aliases.put(from, to);
|
||||
if (DEBUG)
|
||||
FMLLog.finer("Registry alias: %s -> %s", from, to);
|
||||
}
|
||||
|
||||
Map<String,Integer> getEntriesNotIn(FMLControlledNamespacedRegistry<I> registry)
|
||||
Map<ResourceLocation,Integer> getEntriesNotIn(FMLControlledNamespacedRegistry<I> registry)
|
||||
{
|
||||
Map<String,Integer> ret = new HashMap<String, Integer>();
|
||||
Map<ResourceLocation,Integer> ret = new HashMap<ResourceLocation, Integer>();
|
||||
|
||||
for (I thing : this.typeSafeIterable())
|
||||
{
|
||||
if (!registry.inverseObjectRegistry.containsKey(thing))
|
||||
{
|
||||
if (!registry.activeSubstitutions.containsKey(getNameForObject(thing).toString()))
|
||||
if (!registry.activeSubstitutions.containsKey(getNameForObject(thing)))
|
||||
{
|
||||
ret.put(getNameForObject(thing).toString(), getId(thing));
|
||||
ret.put(getNameForObject(thing), getId(thing));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -465,7 +415,7 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
return ret;
|
||||
}
|
||||
|
||||
void dump()
|
||||
void dump(ResourceLocation registryName)
|
||||
{
|
||||
if (!DEBUG)
|
||||
return;
|
||||
|
@ -479,7 +429,7 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
|
||||
// sort by id
|
||||
Collections.sort(ids);
|
||||
|
||||
FMLLog.finer("Registry Name : {}", registryName);
|
||||
for (int id : ids)
|
||||
{
|
||||
I thing = getRaw(id);
|
||||
|
@ -490,7 +440,7 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
/**
|
||||
* Version of addObject not using the API restricting overrides.
|
||||
*/
|
||||
private void addObjectRaw(int id, Object name, I thing)
|
||||
private void addObjectRaw(int id, ResourceLocation name, I thing)
|
||||
{
|
||||
if (name == null) throw new NullPointerException("The name to be added to the registry is null. This can only happen with a corrupted registry state. Reflection/ASM hackery? Registry bug?");
|
||||
if (thing == null) throw new NullPointerException("The object to be added to the registry is null. This can only happen with a corrupted registry state. Reflection/ASM hackery? Registry bug?");
|
||||
|
@ -498,6 +448,7 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
|
||||
underlyingIntegerMap.put(thing, id); // obj <-> id
|
||||
super.putObject(name, thing); // name <-> obj
|
||||
availabilityMap.set(id);
|
||||
}
|
||||
|
||||
public I getDefaultValue()
|
||||
|
@ -506,37 +457,35 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
}
|
||||
|
||||
public RegistryDelegate<I> getDelegate(I thing, Class<I> clazz) {
|
||||
return GameData.buildDelegate(thing, clazz);
|
||||
return new RegistryDelegate.Delegate<I>(thing, clazz);
|
||||
}
|
||||
|
||||
void activateSubstitution(String nameToReplace)
|
||||
@SuppressWarnings("unchecked")
|
||||
public Delegate<I> getExistingDelegate(I thing) {
|
||||
try {
|
||||
return (Delegate<I>) delegateAccessor.get(thing);
|
||||
} catch (IllegalAccessException e) {
|
||||
FMLLog.log(Level.ERROR, e, "Illegal attempt to access delegate");
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
void activateSubstitution(ResourceLocation nameToReplace)
|
||||
{
|
||||
if (getPersistentSubstitutions().containsKey(nameToReplace))
|
||||
{
|
||||
I original = getRaw(nameToReplace);
|
||||
if (superType == Item.class) {
|
||||
Item sub = (Item) getPersistentSubstitutions().get(nameToReplace);
|
||||
if (original == null) {
|
||||
// When we're activated from the server side, we need to set the delegate on the original instance to
|
||||
// point to us. Go to the "default state" registry to get it
|
||||
original = (I)GameData.getItemRegistry().getRaw(nameToReplace);
|
||||
}
|
||||
FMLLog.log(Level.DEBUG, "Replacing %s with %s (name %s)", original, sub, nameToReplace);
|
||||
Delegate<Item> delegate = (Delegate<Item>)((Item)original).delegate;
|
||||
delegate.changeReference(sub);
|
||||
((Delegate<Item>)sub.delegate).setName(nameToReplace);
|
||||
}
|
||||
activeSubstitutions.put(nameToReplace, getPersistentSubstitutions().get(nameToReplace));
|
||||
I sub = getPersistentSubstitutions().get(nameToReplace);
|
||||
getExistingDelegate(original).changeReference(sub);
|
||||
activeSubstitutions.put(nameToReplace, sub);
|
||||
}
|
||||
}
|
||||
|
||||
void addSubstitutionAlias(String modId, String nameToReplace, Object toReplace) throws ExistingSubstitutionException {
|
||||
if (getPersistentSubstitutions().containsKey(nameToReplace) || getPersistentSubstitutions().containsValue(toReplace))
|
||||
void addSubstitutionAlias(String modId, ResourceLocation nameToReplace, I replacement) throws ExistingSubstitutionException {
|
||||
if (getPersistentSubstitutions().containsKey(nameToReplace) || getPersistentSubstitutions().containsValue(replacement))
|
||||
{
|
||||
FMLLog.severe("The substitution of %s has already occured. You cannot duplicate substitutions", nameToReplace);
|
||||
throw new ExistingSubstitutionException(nameToReplace, toReplace);
|
||||
FMLLog.severe("The substitution of %s has already occurred. You cannot duplicate substitutions", nameToReplace);
|
||||
throw new ExistingSubstitutionException(nameToReplace, replacement);
|
||||
}
|
||||
I replacement = cast(toReplace);
|
||||
I original = getRaw(nameToReplace);
|
||||
if (original == null)
|
||||
{
|
||||
|
@ -557,12 +506,8 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
getPersistentSubstitutions().put(nameToReplace, replacement);
|
||||
}
|
||||
|
||||
private BiMap<String, I> getPersistentSubstitutions()
|
||||
private BiMap<ResourceLocation, I> getPersistentSubstitutions()
|
||||
{
|
||||
if (persistentSubstitutions == null)
|
||||
{
|
||||
persistentSubstitutions = GameData.getMain().getPersistentSubstitutionMap(superType);
|
||||
}
|
||||
return persistentSubstitutions;
|
||||
}
|
||||
|
||||
|
@ -576,6 +521,7 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
* This iterator is used by some regular MC methods to visit all blocks, we need to include substitutions
|
||||
* Compare #typeSafeIterable()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Iterator<I> iterator()
|
||||
{
|
||||
|
@ -585,14 +531,72 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
|
||||
|
||||
FMLControlledNamespacedRegistry<I> makeShallowCopy() {
|
||||
return new FMLControlledNamespacedRegistry<I>(optionalDefaultKey, maxId, minId, superType);
|
||||
return new FMLControlledNamespacedRegistry<I>(optionalDefaultKey, maxId, minId, superType, isDelegated);
|
||||
}
|
||||
// ONLY CALLED ON ITEM registry
|
||||
|
||||
void resetSubstitutionDelegates()
|
||||
{
|
||||
for (I item: typeSafeIterable()) {
|
||||
Delegate<Item> delegate = (Delegate<Item>)((Item)item).delegate;
|
||||
delegate.changeReference((Item)item);
|
||||
if (!isDelegated) return;
|
||||
for (I obj: typeSafeIterable()) {
|
||||
Delegate<I> delegate = getExistingDelegate(obj);
|
||||
delegate.changeReference(obj);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> FMLControlledNamespacedRegistry<T> asType(Class<? extends T> type)
|
||||
{
|
||||
return (FMLControlledNamespacedRegistry<T>) this;
|
||||
}
|
||||
|
||||
public void serializeBlockList(Set<Integer> blocked) {
|
||||
blocked.addAll(this.blockedIds);
|
||||
}
|
||||
|
||||
public Set<? extends ResourceLocation> getActiveSubstitutions() {
|
||||
return activeSubstitutions.keySet();
|
||||
}
|
||||
|
||||
public void loadAliases(Map<ResourceLocation, ResourceLocation> aliases) {
|
||||
for (Map.Entry<ResourceLocation, ResourceLocation> alias : aliases.entrySet()) {
|
||||
addAlias(alias.getKey(), alias.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void loadSubstitutions(Set<ResourceLocation> substitutions) {
|
||||
for (ResourceLocation rl : substitutions) {
|
||||
activateSubstitution(rl);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadBlocked(Set<Integer> blocked) {
|
||||
for (Integer id : blocked) {
|
||||
blockedIds.add(id);
|
||||
availabilityMap.set(id);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadIds(Map<ResourceLocation, Integer> ids, Map<ResourceLocation, Integer> missingIds, Map<ResourceLocation, Integer[]> remappedIds, FMLControlledNamespacedRegistry<I> currentRegistry, ResourceLocation registryName) {
|
||||
for (Map.Entry<ResourceLocation, Integer> entry : ids.entrySet()) {
|
||||
ResourceLocation itemName = entry.getKey();
|
||||
int newId = entry.getValue();
|
||||
int currId = currentRegistry.getId(itemName);
|
||||
|
||||
if (currId == -1) {
|
||||
FMLLog.info("Found a missing id from the world %s", itemName);
|
||||
missingIds.put(entry.getKey(), newId);
|
||||
continue; // no block/item -> nothing to add
|
||||
} else if (currId != newId) {
|
||||
FMLLog.fine("Fixed %s id mismatch %s: %d (init) -> %d (map).", registryName, itemName, currId, newId);
|
||||
remappedIds.put(itemName, new Integer[]{currId, newId});
|
||||
}
|
||||
I obj = currentRegistry.getRaw(itemName);
|
||||
|
||||
add(newId, itemName, obj);
|
||||
}
|
||||
}
|
||||
|
||||
public void blockId(int id) {
|
||||
blockedIds.add(id);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -392,22 +392,8 @@ public class GameRegistry
|
|||
}
|
||||
|
||||
public enum Type {
|
||||
BLOCK
|
||||
{
|
||||
@Override
|
||||
public FMLControlledNamespacedRegistry<?> getRegistry() {
|
||||
return GameData.getBlockRegistry();
|
||||
}
|
||||
},
|
||||
ITEM
|
||||
{
|
||||
@Override
|
||||
public FMLControlledNamespacedRegistry<?> getRegistry() {
|
||||
return GameData.getItemRegistry();
|
||||
}
|
||||
};
|
||||
|
||||
public abstract FMLControlledNamespacedRegistry<?> getRegistry();
|
||||
BLOCK,
|
||||
ITEM;
|
||||
}
|
||||
/**
|
||||
* Look up the mod identifier data for a block.
|
||||
|
@ -505,7 +491,7 @@ public class GameRegistry
|
|||
public static ItemStack makeItemStack(String itemName, int meta, int stackSize, String nbtString)
|
||||
{
|
||||
if (itemName == null) throw new IllegalArgumentException("The itemName cannot be null");
|
||||
Item item = GameData.getItemRegistry().getObject(itemName);
|
||||
Item item = GameData.getItemRegistry().getObject(new ResourceLocation(itemName));
|
||||
if (item == null) {
|
||||
FMLLog.getLogger().log(Level.TRACE, "Unable to find item with name {}", itemName);
|
||||
return null;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package net.minecraftforge.fml.common.registry;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class IncompatibleSubstitutionException extends RuntimeException {
|
||||
public IncompatibleSubstitutionException(String fromName, Object replacement, Object original)
|
||||
public IncompatibleSubstitutionException(ResourceLocation fromName, Object replacement, Object original)
|
||||
{
|
||||
super(String.format("The substitute %s for %s (type %s) is type incompatible.", replacement.getClass().getName(), fromName, original.getClass().getName()));
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.lang.reflect.Field;
|
|||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
|
@ -23,12 +24,12 @@ import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder;
|
|||
*/
|
||||
class ObjectHolderRef {
|
||||
private Field field;
|
||||
private String injectedObject;
|
||||
private ResourceLocation injectedObject;
|
||||
private boolean isBlock;
|
||||
private boolean isItem;
|
||||
|
||||
|
||||
ObjectHolderRef(Field field, String injectedObject, boolean extractFromExistingValues)
|
||||
ObjectHolderRef(Field field, ResourceLocation injectedObject, boolean extractFromExistingValues)
|
||||
{
|
||||
this.field = field;
|
||||
this.isBlock = Block.class.isAssignableFrom(field.getType());
|
||||
|
@ -49,10 +50,9 @@ class ObjectHolderRef {
|
|||
}
|
||||
else
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
Object tmp = isBlock ? GameData.getBlockRegistry().getNameForObject(existing) :
|
||||
isItem ? GameData.getItemRegistry().getNameForObject(existing) : null;
|
||||
this.injectedObject = tmp != null ? tmp.toString() : null;
|
||||
ResourceLocation tmp = isBlock ? GameData.getBlockRegistry().getNameForObject((Block)existing) :
|
||||
isItem ? GameData.getItemRegistry().getNameForObject((Item)existing) : null;
|
||||
this.injectedObject = tmp;
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.discovery.ASMDataTable;
|
||||
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
|
||||
|
@ -97,7 +98,7 @@ public enum ObjectHolderRegistry {
|
|||
try
|
||||
{
|
||||
Field f = clazz.getField(annotationTarget);
|
||||
addHolderReference(new ObjectHolderRef(f, value, extractFromValue));
|
||||
addHolderReference(new ObjectHolderRef(f, new ResourceLocation(value), extractFromValue));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -118,7 +119,7 @@ public enum ObjectHolderRegistry {
|
|||
{
|
||||
continue;
|
||||
}
|
||||
addHolderReference(new ObjectHolderRef(f, value + ":"+ f.getName(), extractFromExistingValues));
|
||||
addHolderReference(new ObjectHolderRef(f, new ResourceLocation(value, f.getName()), extractFromExistingValues));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,407 @@
|
|||
package net.minecraftforge.fml.common.registry;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.*;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraftforge.fml.common.*;
|
||||
import net.minecraftforge.fml.common.event.FMLMissingMappingsEvent;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import com.google.common.collect.Sets.SetView;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Persistent registry manager. Manages the registries loading from disk, and from network. Handles staging
|
||||
* registry data before loading uniformly into the active registry, and keeps a frozen registry instance
|
||||
* for reversion after connection.
|
||||
* @author cpw
|
||||
*/
|
||||
public class PersistentRegistryManager
|
||||
{
|
||||
private enum PersistentRegistry {
|
||||
ACTIVE, FROZEN, STAGING;
|
||||
|
||||
private final BiMap<ResourceLocation,FMLControlledNamespacedRegistry<?>> registries = HashBiMap.create();
|
||||
private final BiMap<Class<?>,ResourceLocation> registrySuperTypes = HashBiMap.create();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> FMLControlledNamespacedRegistry<T> getRegistry(ResourceLocation key, Class<T> regType)
|
||||
{
|
||||
return (FMLControlledNamespacedRegistry<T>) registries.get(key);
|
||||
}
|
||||
|
||||
<T> FMLControlledNamespacedRegistry<T> getOrShallowCopyRegistry(ResourceLocation key, Class<T> regType, FMLControlledNamespacedRegistry<T> other)
|
||||
{
|
||||
if (!registries.containsKey(key)) {
|
||||
registries.put(key, other.makeShallowCopy());
|
||||
registrySuperTypes.put(regType, key);
|
||||
}
|
||||
return getRegistry(key, regType);
|
||||
}
|
||||
|
||||
private <T> FMLControlledNamespacedRegistry<T> createRegistry(ResourceLocation registryName, Class<T> type, ResourceLocation defaultObjectKey, int minId, int maxId, boolean isDelegated) {
|
||||
Set<Class<?>> parents = Sets.newHashSet();
|
||||
findSuperTypes(type, parents);
|
||||
SetView<Class<?>> overlappedTypes = Sets.intersection(parents, registrySuperTypes.keySet());
|
||||
if (!overlappedTypes.isEmpty()) {
|
||||
Class<?> foundType = overlappedTypes.iterator().next();
|
||||
FMLLog.severe("Found existing registry of type %1s named %2s, you cannot create a new registry (%3s) with type %4s, as %4s has a parent of that type", foundType, registrySuperTypes.get(foundType), registryName, type);
|
||||
throw new IllegalArgumentException("Duplicate registry parent type found - you can only have one registry for a particular super type");
|
||||
}
|
||||
FMLControlledNamespacedRegistry<T> fmlControlledNamespacedRegistry = new FMLControlledNamespacedRegistry<T>(defaultObjectKey, maxId, minId, type, isDelegated);
|
||||
registries.put(registryName, fmlControlledNamespacedRegistry);
|
||||
registrySuperTypes.put(type, registryName);
|
||||
return getRegistry(registryName, type);
|
||||
}
|
||||
|
||||
private void findSuperTypes(Class<?> type, Set<Class<?>> types)
|
||||
{
|
||||
if (type == null || type == Object.class) {
|
||||
return;
|
||||
}
|
||||
types.add(type);
|
||||
for (Class<?> interfac : type.getInterfaces()) {
|
||||
findSuperTypes(interfac, types);
|
||||
}
|
||||
findSuperTypes(type.getSuperclass(),types);
|
||||
}
|
||||
|
||||
|
||||
void clean() {
|
||||
registries.clear();
|
||||
registrySuperTypes.clear();
|
||||
}
|
||||
|
||||
boolean isPopulated() {
|
||||
return !registries.isEmpty();
|
||||
}
|
||||
|
||||
boolean containsRegistry(FMLControlledNamespacedRegistry<?> registry) {
|
||||
return registries.containsValue(registry);
|
||||
}
|
||||
|
||||
public <T> FMLControlledNamespacedRegistry<T> getRegistry(Class<T> rootClass) {
|
||||
ResourceLocation rl = registrySuperTypes.get(rootClass);
|
||||
return getRegistry(rl, rootClass);
|
||||
}
|
||||
}
|
||||
|
||||
public static final ResourceLocation BLOCKS = new ResourceLocation("minecraft:blocks");
|
||||
public static final ResourceLocation ITEMS = new ResourceLocation("minecraft:items");
|
||||
|
||||
public static <T> FMLControlledNamespacedRegistry<T> createRegistry(ResourceLocation registryName, Class<T> registryType, ResourceLocation optionalDefaultKey, int maxId, int minId, boolean hasDelegates) {
|
||||
return PersistentRegistry.ACTIVE.createRegistry(registryName,registryType,optionalDefaultKey,minId, maxId, hasDelegates);
|
||||
}
|
||||
|
||||
|
||||
public static List<String> injectSnapshot(GameDataSnapshot snapshot, boolean injectFrozenData, boolean isLocalWorld) {
|
||||
FMLLog.info("Injecting existing block and item data into this {} instance", FMLCommonHandler.instance().getEffectiveSide().isServer() ? "server" : "client");
|
||||
final Map<ResourceLocation, Map<ResourceLocation,Integer[]>> remaps = Maps.newHashMap();
|
||||
final LinkedHashMap<ResourceLocation, Map<ResourceLocation,Integer>> missing = Maps.newLinkedHashMap();
|
||||
|
||||
forAllRegistries(PersistentRegistry.ACTIVE, ValidateRegistryFunction.OPERATION);
|
||||
forAllRegistries(PersistentRegistry.ACTIVE, DumpRegistryFunction.OPERATION);
|
||||
forAllRegistries(PersistentRegistry.ACTIVE, ResetDelegatesFunction.OPERATION);
|
||||
|
||||
// Load the snapshot into the "STAGING" registry
|
||||
for (Map.Entry<ResourceLocation, GameDataSnapshot.Entry> snapshotEntry : snapshot.entries.entrySet())
|
||||
{
|
||||
loadPersistentDataToStagingRegistry(injectFrozenData, remaps, missing, snapshotEntry, PersistentRegistry.ACTIVE.registrySuperTypes.inverse().get(snapshotEntry.getKey()));
|
||||
}
|
||||
|
||||
// If we have missed data, fire the missing mapping event
|
||||
List<String> 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
|
||||
if (!missedMappings.isEmpty()) return missedMappings;
|
||||
|
||||
// If we're loading up the world from disk, we want to add in the new data that might have been provisioned by mods
|
||||
if (injectFrozenData)
|
||||
{
|
||||
// So we load it from the frozen persistent registry
|
||||
for (Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> r : PersistentRegistry.ACTIVE.registries.entrySet()) {
|
||||
loadFrozenDataToStagingRegistry(remaps, r.getKey(), PersistentRegistry.ACTIVE.registrySuperTypes.inverse().get(r.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
// Validate that all the STAGING data is good
|
||||
forAllRegistries(PersistentRegistry.STAGING, ValidateRegistryFunction.OPERATION);
|
||||
|
||||
// Load the STAGING registry into the ACTIVE registry
|
||||
for (Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> r : PersistentRegistry.ACTIVE.registries.entrySet()) {
|
||||
loadRegistry(r.getKey(), PersistentRegistry.STAGING, PersistentRegistry.ACTIVE, PersistentRegistry.ACTIVE.registrySuperTypes.inverse().get(r.getKey()));
|
||||
}
|
||||
|
||||
// Dump the active registry
|
||||
forAllRegistries(PersistentRegistry.ACTIVE, DumpRegistryFunction.OPERATION);
|
||||
|
||||
// Tell mods that the ids have changed
|
||||
Loader.instance().fireRemapEvent(remaps.get(BLOCKS), remaps.get(ITEMS));
|
||||
|
||||
// The id map changed, ensure we apply object holders
|
||||
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
||||
|
||||
// Return an empty list, because we're good
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
private static void forAllRegistries(PersistentRegistry registrySet, Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void> operation) {
|
||||
for (Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> r : registrySet.registries.entrySet())
|
||||
{
|
||||
operation.apply(r);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void loadRegistry(ResourceLocation registryName, PersistentRegistry from, PersistentRegistry to, Class<T> regType) {
|
||||
FMLControlledNamespacedRegistry<T> fromRegistry = from.getRegistry(registryName, regType);
|
||||
FMLControlledNamespacedRegistry<T> toRegistry = to.getOrShallowCopyRegistry(registryName, regType, fromRegistry);
|
||||
toRegistry.set(fromRegistry);
|
||||
}
|
||||
|
||||
private static <T> void loadFrozenDataToStagingRegistry(Map<ResourceLocation, Map<ResourceLocation, Integer[]>> remaps, ResourceLocation registryName, Class<T> regType) {
|
||||
FMLControlledNamespacedRegistry<T> newRegistry = PersistentRegistry.STAGING.getRegistry(registryName, regType);
|
||||
FMLControlledNamespacedRegistry<T> frozenRegistry = PersistentRegistry.FROZEN.getRegistry(registryName, regType);
|
||||
newRegistry.loadIds(frozenRegistry.getEntriesNotIn(newRegistry), Maps.<ResourceLocation, Integer>newLinkedHashMap(), remaps.get(registryName), frozenRegistry, registryName);
|
||||
}
|
||||
|
||||
private static <T> void loadPersistentDataToStagingRegistry(boolean injectFrozenData, Map<ResourceLocation, Map<ResourceLocation, Integer[]>> remaps, LinkedHashMap<ResourceLocation, Map<ResourceLocation, Integer>> missing, Map.Entry<ResourceLocation, GameDataSnapshot.Entry> snapEntry, Class<T> regType) {
|
||||
ResourceLocation registryName = snapEntry.getKey();
|
||||
FMLControlledNamespacedRegistry<T> currentRegistry = PersistentRegistry.ACTIVE.getRegistry(registryName, regType);
|
||||
if (currentRegistry == null) {
|
||||
FMLLog.severe("An unknown persistent registry type {} has been encountered. This Forge instance cannot understand it.", registryName);
|
||||
StartupQuery.abort();
|
||||
}
|
||||
FMLControlledNamespacedRegistry<T> newRegistry = PersistentRegistry.STAGING.getOrShallowCopyRegistry(registryName, regType, currentRegistry);
|
||||
GameDataSnapshot.Entry snapshotEntry = snapEntry.getValue();
|
||||
Set<ResourceLocation> substitutions = snapshotEntry.substitutions;
|
||||
if (injectFrozenData)
|
||||
{
|
||||
substitutions = Sets.union(snapshotEntry.substitutions, currentRegistry.getActiveSubstitutions());
|
||||
}
|
||||
newRegistry.loadAliases(snapshotEntry.aliases);
|
||||
newRegistry.loadSubstitutions(substitutions);
|
||||
newRegistry.loadBlocked(snapshotEntry.blocked);
|
||||
missing.put(registryName, Maps.<ResourceLocation, Integer>newLinkedHashMap());
|
||||
remaps.put(registryName, Maps.<ResourceLocation, Integer[]>newHashMap());
|
||||
newRegistry.loadIds(snapshotEntry.ids, missing.get(registryName), remaps.get(registryName), currentRegistry, registryName);
|
||||
}
|
||||
|
||||
public static boolean isFrozen(FMLControlledNamespacedRegistry<?> registry) {
|
||||
return PersistentRegistry.FROZEN.containsRegistry(registry);
|
||||
}
|
||||
|
||||
public static void revertToFrozen() {
|
||||
if (!PersistentRegistry.FROZEN.isPopulated()) {
|
||||
FMLLog.warning("Can't revert to frozen GameData state without freezing first.");
|
||||
} else {
|
||||
FMLLog.fine("Reverting to frozen data state.");
|
||||
}
|
||||
for (Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> r : PersistentRegistry.ACTIVE.registries.entrySet()) {
|
||||
loadRegistry(r.getKey(), PersistentRegistry.FROZEN, PersistentRegistry.ACTIVE, PersistentRegistry.ACTIVE.registrySuperTypes.inverse().get(r.getKey()));
|
||||
}
|
||||
// the id mapping has reverted, fire remap events for those that care about id changes
|
||||
Loader.instance().fireRemapEvent(ImmutableMap.<ResourceLocation, Integer[]>of(), ImmutableMap.<ResourceLocation, Integer[]>of());
|
||||
// the id mapping has reverted, ensure we sync up the object holders
|
||||
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
||||
}
|
||||
|
||||
public static void freezeData() {
|
||||
FMLLog.fine("Freezing block and item id maps");
|
||||
for (Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> r : PersistentRegistry.ACTIVE.registries.entrySet()) {
|
||||
loadRegistry(r.getKey(), PersistentRegistry.ACTIVE, PersistentRegistry.FROZEN, PersistentRegistry.ACTIVE.registrySuperTypes.inverse().get(r.getKey()));
|
||||
}
|
||||
forAllRegistries(PersistentRegistry.FROZEN, ValidateRegistryFunction.OPERATION);
|
||||
}
|
||||
|
||||
public static List<String> processIdRematches(Iterable<FMLMissingMappingsEvent.MissingMapping> missedMappings, boolean isLocalWorld, Map<ResourceLocation, Integer[]> remapBlocks, Map<ResourceLocation, Integer[]> remapItems) {
|
||||
List<String> failed = Lists.newArrayList();
|
||||
List<String> ignored = Lists.newArrayList();
|
||||
List<String> warned = Lists.newArrayList();
|
||||
List<String> defaulted = Lists.newArrayList();
|
||||
|
||||
final PersistentRegistry staging = PersistentRegistry.STAGING;
|
||||
final PersistentRegistry active = PersistentRegistry.ACTIVE;
|
||||
for (FMLMissingMappingsEvent.MissingMapping remap : missedMappings) {
|
||||
FMLMissingMappingsEvent.Action action = remap.getAction();
|
||||
|
||||
if (action == FMLMissingMappingsEvent.Action.REMAP) {
|
||||
// block/item re-mapped, finish the registration with the new name/object, but the old id
|
||||
int currId = -1, newId = -1;
|
||||
ResourceLocation newName;
|
||||
|
||||
if (remap.type == GameRegistry.Type.BLOCK) {
|
||||
currId = staging.getRegistry(BLOCKS, Block.class).getId((Block) remap.getTarget());
|
||||
newName = active.getRegistry(BLOCKS, Block.class).getNameForObject((Block)remap.getTarget());
|
||||
FMLLog.fine("The Block %s is being remapped to %s.", remap.name, newName);
|
||||
|
||||
newId = staging.getRegistry(BLOCKS,Block.class).add(remap.id, newName, (Block) remap.getTarget());
|
||||
staging.getRegistry(BLOCKS,Block.class).addAlias(remap.resourceLocation, newName);
|
||||
} else if (remap.type == GameRegistry.Type.ITEM) {
|
||||
currId = staging.getRegistry(ITEMS, Item.class).getId((Item) remap.getTarget());
|
||||
newName = active.getRegistry(ITEMS, Item.class).getNameForObject((Item)remap.getTarget());
|
||||
FMLLog.fine("The Item %s is being remapped to %s.", remap.name, newName);
|
||||
|
||||
newId = staging.getRegistry(ITEMS,Item.class).add(remap.id, newName, (Item) remap.getTarget());
|
||||
staging.getRegistry(ITEMS,Item.class).addAlias(remap.resourceLocation, newName);
|
||||
} else {
|
||||
// currently not remapping non-blocks and items
|
||||
continue;
|
||||
}
|
||||
|
||||
if (newId != remap.id) throw new IllegalStateException();
|
||||
|
||||
if (currId != newId) {
|
||||
FMLLog.info("Fixed %s id mismatch %s: %d (init) -> %d (map).", remap.type == GameRegistry.Type.BLOCK ? "block" : "item", newName, currId, newId);
|
||||
(remap.type == GameRegistry.Type.BLOCK ? remapBlocks : remapItems).put(newName, new Integer[]{currId, newId});
|
||||
}
|
||||
} else if (action == FMLMissingMappingsEvent.Action.BLOCKONLY) {
|
||||
// Pulled out specifically so the block doesn't get reassigned a new ID just because it's
|
||||
// Item block has gone away
|
||||
FMLLog.fine("The ItemBlock %s is no longer present in the game. The residual block will remain", remap.name);
|
||||
} else {
|
||||
// block item missing, warn as requested and block the id
|
||||
if (action == FMLMissingMappingsEvent.Action.DEFAULT) {
|
||||
defaulted.add(remap.name);
|
||||
} else if (action == FMLMissingMappingsEvent.Action.IGNORE) {
|
||||
ignored.add(remap.name);
|
||||
} else if (action == FMLMissingMappingsEvent.Action.FAIL) {
|
||||
failed.add(remap.name);
|
||||
} else if (action == FMLMissingMappingsEvent.Action.WARN) {
|
||||
warned.add(remap.name);
|
||||
}
|
||||
// prevent the id from being reused later
|
||||
if (remap.type == GameRegistry.Type.BLOCK) {
|
||||
staging.getRegistry(BLOCKS, Block.class).blockId(remap.id);
|
||||
} else if (remap.type == GameRegistry.Type.ITEM) {
|
||||
staging.getRegistry(ITEMS, Item.class).blockId(remap.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!defaulted.isEmpty()) {
|
||||
String text = "Forge Mod Loader detected missing blocks/items.\n\n" +
|
||||
"There are " + defaulted.size() + " missing blocks and items in this save.\n" +
|
||||
"If you continue the missing blocks/items will get removed.\n" +
|
||||
"A world backup will be automatically created in your saves directory.\n\n" +
|
||||
"Missing Blocks/Items:\n";
|
||||
|
||||
for (String s : defaulted) text += s + "\n";
|
||||
|
||||
boolean confirmed = StartupQuery.confirm(text);
|
||||
if (!confirmed) StartupQuery.abort();
|
||||
|
||||
try {
|
||||
String skip = System.getProperty("fml.doNotBackup");
|
||||
if (skip == null || !"true".equals(skip)) {
|
||||
ZipperUtil.backupWorld();
|
||||
} else {
|
||||
for (int x = 0; x < 10; x++)
|
||||
FMLLog.severe("!!!!!!!!!! UPDATING WORLD WITHOUT DOING BACKUP !!!!!!!!!!!!!!!!");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
StartupQuery.notify("The world backup couldn't be created.\n\n" + e);
|
||||
StartupQuery.abort();
|
||||
}
|
||||
|
||||
warned.addAll(defaulted);
|
||||
}
|
||||
if (!failed.isEmpty()) {
|
||||
FMLLog.severe("This world contains blocks and items that refuse to be remapped. The world will not be loaded");
|
||||
return failed;
|
||||
}
|
||||
if (!warned.isEmpty()) {
|
||||
FMLLog.warning("This world contains block and item mappings that may cause world breakage");
|
||||
return failed;
|
||||
} else if (!ignored.isEmpty()) {
|
||||
FMLLog.fine("There were %d missing mappings that have been ignored", ignored.size());
|
||||
}
|
||||
return failed;
|
||||
}
|
||||
|
||||
|
||||
public static GameDataSnapshot takeSnapshot() {
|
||||
final GameDataSnapshot snap = new GameDataSnapshot();
|
||||
forAllRegistries(PersistentRegistry.ACTIVE, new Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void>() {
|
||||
@Override
|
||||
public Void apply(Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> input) {
|
||||
snap.entries.put(input.getKey(), new GameDataSnapshot.Entry(input.getValue()));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return snap;
|
||||
}
|
||||
|
||||
|
||||
public static class GameDataSnapshot {
|
||||
public static class Entry {
|
||||
public final Map<ResourceLocation, Integer> ids;
|
||||
public final Set<ResourceLocation> substitutions;
|
||||
public final Map<ResourceLocation, ResourceLocation> aliases;
|
||||
public final Set<Integer> blocked;
|
||||
|
||||
public Entry() {
|
||||
this(new HashMap<ResourceLocation, Integer>(), new HashSet<ResourceLocation>(), new HashMap<ResourceLocation, ResourceLocation>(), new HashSet<Integer>());
|
||||
}
|
||||
|
||||
public Entry(Map<ResourceLocation, Integer> ids, Set<ResourceLocation> substitutions, Map<ResourceLocation, ResourceLocation> aliases, Set<Integer> blocked) {
|
||||
this.ids = ids;
|
||||
this.substitutions = substitutions;
|
||||
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.serializeIds(this.ids);
|
||||
registry.serializeSubstitutions(this.substitutions);
|
||||
registry.serializeAliases(this.aliases);
|
||||
registry.serializeBlockList(this.blocked);
|
||||
}
|
||||
}
|
||||
|
||||
public final Map<ResourceLocation, Entry> entries = Maps.newHashMap();
|
||||
}
|
||||
|
||||
public static <T> RegistryDelegate<T> makeDelegate(T obj, Class<T> rootClass) {
|
||||
return PersistentRegistry.ACTIVE.getRegistry(rootClass).getDelegate(obj, rootClass);
|
||||
}
|
||||
|
||||
|
||||
private static class DumpRegistryFunction implements Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void> {
|
||||
static final DumpRegistryFunction OPERATION = new DumpRegistryFunction();
|
||||
|
||||
@Override
|
||||
public Void apply(Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> input) {
|
||||
input.getValue().dump(input.getKey());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static class ValidateRegistryFunction implements Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void> {
|
||||
static final ValidateRegistryFunction OPERATION = new ValidateRegistryFunction();
|
||||
|
||||
@Override
|
||||
public Void apply(Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> input) {
|
||||
input.getValue().validateContent(input.getKey());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static class ResetDelegatesFunction implements Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void> {
|
||||
static final ResetDelegatesFunction OPERATION = new ResetDelegatesFunction();
|
||||
|
||||
@Override
|
||||
public Void apply(Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> input) {
|
||||
input.getValue().resetSubstitutionDelegates();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package net.minecraftforge.fml.common.registry;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -24,12 +25,24 @@ public interface RegistryDelegate<T> {
|
|||
|
||||
/**
|
||||
* Get the name of this delegate. This is completely static after registration has completed and will never change.
|
||||
*
|
||||
* Deprecated in favour of the resource location.
|
||||
*
|
||||
* @see #getResourceName()
|
||||
* @return The name
|
||||
*/
|
||||
@Deprecated
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Get the delegate type. It will be Item or Block.
|
||||
* Get the unique resource location for this delegate. Completely static after registration has completed, and
|
||||
* will never change.
|
||||
* @return The name
|
||||
*/
|
||||
ResourceLocation getResourceName();
|
||||
|
||||
/**
|
||||
* Get the delegate type. It will be dependent on the registry this delegate is sourced from.
|
||||
* @return The type of delegate
|
||||
*/
|
||||
Class<T> type();
|
||||
|
@ -40,7 +53,7 @@ public interface RegistryDelegate<T> {
|
|||
final class Delegate<T> implements RegistryDelegate<T>
|
||||
{
|
||||
private T referant;
|
||||
private String name;
|
||||
private ResourceLocation name;
|
||||
private final Class<T> type;
|
||||
|
||||
public Delegate(T referant, Class<T> type) {
|
||||
|
@ -55,9 +68,12 @@ public interface RegistryDelegate<T> {
|
|||
|
||||
@Override
|
||||
public String name() {
|
||||
return name;
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getResourceName() { return name; }
|
||||
|
||||
@Override
|
||||
public Class<T> type()
|
||||
{
|
||||
|
@ -69,10 +85,7 @@ public interface RegistryDelegate<T> {
|
|||
this.referant = newTarget;
|
||||
}
|
||||
|
||||
void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
void setResourceName(ResourceLocation name) { this.name = name; }
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
|
|
|
@ -17,6 +17,8 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import net.minecraft.entity.passive.EntityVillager;
|
||||
|
@ -191,14 +193,13 @@ public class VillagerRegistry
|
|||
{
|
||||
register(prof, -1);
|
||||
}
|
||||
@SuppressWarnings("deprecation")
|
||||
private void register(VillagerProfession prof, int id)
|
||||
{
|
||||
professions.register(id, prof.name, prof);
|
||||
}
|
||||
|
||||
private boolean hasInit = false;
|
||||
private FMLControlledNamespacedRegistry<VillagerProfession> professions = GameData.createRegistry("villagerprofessions", VillagerProfession.class, 0, 1024);
|
||||
private FMLControlledNamespacedRegistry<VillagerProfession> professions = PersistentRegistryManager.createRegistry(new ResourceLocation("minecraft:villagerprofessions"), VillagerProfession.class, null, 1024, 0, true);
|
||||
|
||||
|
||||
private void init()
|
||||
|
@ -242,22 +243,22 @@ public class VillagerRegistry
|
|||
public static class VillagerProfession
|
||||
{
|
||||
private ResourceLocation name;
|
||||
//private ResourceLocation texture;
|
||||
private ResourceLocation texture;
|
||||
private List<VillagerCareer> careers = Lists.newArrayList();
|
||||
private RegistryDelegate<VillagerProfession> delegate = GameData.getRegistry("villagerprofessions", VillagerProfession.class).getDelegate(this, VillagerProfession.class);
|
||||
public final RegistryDelegate<VillagerProfession> delegate = PersistentRegistryManager.makeDelegate(this, VillagerProfession.class);
|
||||
|
||||
public VillagerProfession(String name, String texture)
|
||||
{
|
||||
this.name = new ResourceLocation(name);
|
||||
//this.texture = new ResourceLocation(texture);
|
||||
((RegistryDelegate.Delegate<VillagerProfession>)delegate).setName(name);
|
||||
this.texture = new ResourceLocation(texture);
|
||||
((RegistryDelegate.Delegate<VillagerProfession>)delegate).setResourceName(this.name);
|
||||
}
|
||||
|
||||
private void register(VillagerCareer career)
|
||||
{
|
||||
Validate.isTrue(!careers.contains(career), "Attempted to register career that is already registered.");
|
||||
Validate.isTrue(career.profession == this, "Attempted to register career for the wrong profession.");
|
||||
//career.id = careers.size();
|
||||
career.id = careers.size();
|
||||
careers.add(career);
|
||||
}
|
||||
}
|
||||
|
@ -266,7 +267,7 @@ public class VillagerRegistry
|
|||
{
|
||||
private VillagerProfession profession;
|
||||
private String name;
|
||||
//private int id;
|
||||
private int id;
|
||||
public VillagerCareer(VillagerProfession parent, String name)
|
||||
{
|
||||
this.profession = parent;
|
||||
|
@ -297,8 +298,8 @@ public class VillagerRegistry
|
|||
*/
|
||||
public static void setRandomProfession(EntityVillager entity, Random rand)
|
||||
{
|
||||
//int count = INSTANCE.professions.getKeys().size();
|
||||
//int prof = rand.nextInt(count);
|
||||
Set<ResourceLocation> entries = INSTANCE.professions.getKeys();
|
||||
int prof = rand.nextInt(entries.size());
|
||||
//TODO: Grab id range from internal registry
|
||||
entity.setProfession(rand.nextInt(5));
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
|
@ -325,7 +326,7 @@ public class OreDictionary
|
|||
// HACK: use the registry name's ID. It is unique and it knows about substitutions. Fallback to a -1 value (what Item.getIDForItem would have returned) in the case where the registry is not aware of the item yet
|
||||
// IT should be noted that -1 will fail the gate further down, if an entry already exists with value -1 for this name. This is what is broken and being warned about.
|
||||
// APPARENTLY it's quite common to do this. OreDictionary should be considered alongside Recipes - you can't make them properly until you've registered with the game.
|
||||
String registryName = stack.getItem().delegate.name();
|
||||
ResourceLocation registryName = stack.getItem().delegate.getResourceName();
|
||||
int id;
|
||||
if (registryName == null)
|
||||
{
|
||||
|
@ -449,7 +450,7 @@ public class OreDictionary
|
|||
// HACK: use the registry name's ID. It is unique and it knows about substitutions. Fallback to a -1 value (what Item.getIDForItem would have returned) in the case where the registry is not aware of the item yet
|
||||
// IT should be noted that -1 will fail the gate further down, if an entry already exists with value -1 for this name. This is what is broken and being warned about.
|
||||
// APPARENTLY it's quite common to do this. OreDictionary should be considered alongside Recipes - you can't make them properly until you've registered with the game.
|
||||
String registryName = ore.getItem().delegate.name();
|
||||
ResourceLocation registryName = ore.getItem().delegate.getResourceName();
|
||||
int hash;
|
||||
if (registryName == null)
|
||||
{
|
||||
|
@ -506,7 +507,7 @@ public class OreDictionary
|
|||
for (ItemStack ore : ores)
|
||||
{
|
||||
// HACK: use the registry name's ID. It is unique and it knows about substitutions
|
||||
String name = ore.getItem().delegate.name();
|
||||
ResourceLocation name = ore.getItem().delegate.getResourceName();
|
||||
int hash;
|
||||
if (name == null)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue