ItemStack swapping
This commit is contained in:
parent
2ca75b3fa4
commit
dddbbd3bac
11 changed files with 313 additions and 81 deletions
|
@ -30,9 +30,9 @@ import net.minecraft.world.storage.WorldInfo;
|
|||
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
|
@ -105,8 +105,8 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
// name <-> id mappings
|
||||
NBTTagList dataList = new NBTTagList();
|
||||
FMLLog.fine("Gathering id map for writing to world save %s", info.getWorldName());
|
||||
Map<String,Integer> itemList = GameData.buildItemDataList();
|
||||
for (Entry<String, Integer> item : itemList.entrySet())
|
||||
GameData.GameDataSnapshot dataSnapshot = GameData.buildItemDataList();
|
||||
for (Entry<String, Integer> item : dataSnapshot.idMap.entrySet())
|
||||
{
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setString("K",item.getKey());
|
||||
|
@ -126,15 +126,14 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
blockAliasList.appendTag(tag);
|
||||
}
|
||||
fmlData.setTag("BlockAliases", blockAliasList);
|
||||
NBTTagList blockPersistentAliasList = new NBTTagList();
|
||||
for (Entry<String, String> entry : GameData.getBlockRegistry().getPersistentAliases().entrySet())
|
||||
NBTTagList blockSubstitutionsList = new NBTTagList();
|
||||
for (String entry : dataSnapshot.blockSubstitutions)
|
||||
{
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setString("K", entry.getKey());
|
||||
tag.setString("V", entry.getValue());
|
||||
blockPersistentAliasList.appendTag(tag);
|
||||
tag.setString("K", entry);
|
||||
blockSubstitutionsList.appendTag(tag);
|
||||
}
|
||||
fmlData.setTag("PersistentBlockAliases", blockPersistentAliasList);
|
||||
fmlData.setTag("BlockSubstitutions", blockSubstitutionsList);
|
||||
// item aliases
|
||||
NBTTagList itemAliasList = new NBTTagList();
|
||||
for (Entry<String, String> entry : GameData.getItemRegistry().getAliases().entrySet())
|
||||
|
@ -146,15 +145,14 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
}
|
||||
fmlData.setTag("ItemAliases", itemAliasList);
|
||||
|
||||
NBTTagList itemPersistentAliasList = new NBTTagList();
|
||||
for (Entry<String, String> entry : GameData.getItemRegistry().getPersistentAliases().entrySet())
|
||||
NBTTagList itemSubstitutionsList = new NBTTagList();
|
||||
for (String entry : dataSnapshot.itemSubstitutions)
|
||||
{
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setString("K", entry.getKey());
|
||||
tag.setString("V", entry.getValue());
|
||||
itemPersistentAliasList.appendTag(tag);
|
||||
tag.setString("K", entry);
|
||||
itemSubstitutionsList.appendTag(tag);
|
||||
}
|
||||
fmlData.setTag("ItemPersistentAliases", itemPersistentAliasList);
|
||||
fmlData.setTag("ItemSubstitutions", itemSubstitutionsList);
|
||||
return fmlData;
|
||||
}
|
||||
|
||||
|
@ -209,7 +207,7 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
dataList.put(itemLabel, itemId);
|
||||
}
|
||||
}
|
||||
failedElements = GameData.injectWorldIDMap(dataList, true, true);
|
||||
failedElements = GameData.injectWorldIDMap(dataList, ImmutableSet.<String>of(), ImmutableSet.<String>of(), true, true);
|
||||
|
||||
}
|
||||
else if (tag.hasKey("ItemData"))
|
||||
|
@ -245,14 +243,14 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
NBTTagCompound dataTag = list.getCompoundTagAt(i);
|
||||
blockAliases.put(dataTag.getString("K"), dataTag.getString("V"));
|
||||
}
|
||||
BiMap<String, String> blockPersistentAliases = HashBiMap.create();
|
||||
if (tag.hasKey("BlockPersistentAliases", 10))
|
||||
Set<String> blockSubstitutions = Sets.newHashSet();
|
||||
if (tag.hasKey("BlockSubstitutions", 9))
|
||||
{
|
||||
list = tag.getTagList("BlockPersistentAliases", 10);
|
||||
list = tag.getTagList("BlockSubstitutions", 10);
|
||||
for (int i = 0; i < list.tagCount(); i++)
|
||||
{
|
||||
NBTTagCompound dataTag = list.getCompoundTagAt(i);
|
||||
blockPersistentAliases.put(dataTag.getString("K"), dataTag.getString("V"));
|
||||
blockSubstitutions.add(dataTag.getString("K"));
|
||||
}
|
||||
}
|
||||
// item aliases
|
||||
|
@ -264,17 +262,17 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
itemAliases.put(dataTag.getString("K"), dataTag.getString("V"));
|
||||
}
|
||||
|
||||
BiMap<String, String> itemPersistentAliases = HashBiMap.create();
|
||||
if (tag.hasKey("ItemPersistentAliases", 10))
|
||||
Set<String> itemSubstitutions = Sets.newHashSet();
|
||||
if (tag.hasKey("ItemSubstitutions", 9))
|
||||
{
|
||||
list = tag.getTagList("ItemPersistentAliases", 10);
|
||||
list = tag.getTagList("ItemSubstitutions", 10);
|
||||
for (int i = 0; i < list.tagCount(); i++)
|
||||
{
|
||||
NBTTagCompound dataTag = list.getCompoundTagAt(i);
|
||||
itemPersistentAliases.put(dataTag.getString("K"), dataTag.getString("V"));
|
||||
itemSubstitutions.add(dataTag.getString("K"));
|
||||
}
|
||||
}
|
||||
failedElements = GameData.injectWorldIDMap(dataList, blockedIds, blockAliases, itemAliases, true, true);
|
||||
failedElements = GameData.injectWorldIDMap(dataList, blockedIds, blockAliases, itemAliases, blockSubstitutions, itemSubstitutions, true, true);
|
||||
}
|
||||
|
||||
if (failedElements != null && !failedElements.isEmpty())
|
||||
|
|
|
@ -32,7 +32,28 @@ public class FMLMissingMappingsEvent extends FMLEvent {
|
|||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public static enum Action { DEFAULT, IGNORE, WARN, FAIL, REMAP }
|
||||
public static enum Action {
|
||||
/**
|
||||
* Take the default action
|
||||
*/
|
||||
DEFAULT,
|
||||
/**
|
||||
* Ignore this missing mapping. This means the mapping will be abandoned
|
||||
*/
|
||||
IGNORE,
|
||||
/**
|
||||
* Generate a warning but allow loading to continue
|
||||
*/
|
||||
WARN,
|
||||
/**
|
||||
* Fail to load
|
||||
*/
|
||||
FAIL,
|
||||
/**
|
||||
* Remap this name to a new name (add a migration mapping)
|
||||
*/
|
||||
REMAP
|
||||
}
|
||||
public static class MissingMapping {
|
||||
public final GameRegistry.Type type;
|
||||
public final String name;
|
||||
|
|
|
@ -85,7 +85,7 @@ enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
|
|||
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
{
|
||||
FMLHandshakeMessage.ModIdData modIds = (FMLHandshakeMessage.ModIdData)msg;
|
||||
List<String> locallyMissing = GameData.injectWorldIDMap(modIds.dataList(), false, false);
|
||||
List<String> locallyMissing = GameData.injectWorldIDMap(modIds.dataList(), modIds.blockSubstitutions(), modIds.itemSubstitutions(), false, false);
|
||||
if (!locallyMissing.isEmpty())
|
||||
{
|
||||
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
||||
|
|
|
@ -13,11 +13,13 @@ import com.google.common.base.Charsets;
|
|||
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 cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.network.ByteBufUtils;
|
||||
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
|
||||
import cpw.mods.fml.common.registry.GameData;
|
||||
|
||||
public abstract class FMLHandshakeMessage {
|
||||
public static FMLProxyPacket makeCustomChannelRegistration(Set<String> channels)
|
||||
|
@ -128,22 +130,43 @@ public abstract class FMLHandshakeMessage {
|
|||
|
||||
}
|
||||
|
||||
public ModIdData(Map<String,Integer> modIds)
|
||||
public ModIdData(GameData.GameDataSnapshot snapshot)
|
||||
{
|
||||
this.modIds = modIds;
|
||||
this.modIds = snapshot.idMap;
|
||||
this.blockSubstitutions = snapshot.blockSubstitutions;
|
||||
this.itemSubstitutions = snapshot.itemSubstitutions;
|
||||
}
|
||||
|
||||
private Map<String,Integer> modIds;
|
||||
private Set<String> blockSubstitutions;
|
||||
private Set<String> itemSubstitutions;
|
||||
@Override
|
||||
public void fromBytes(ByteBuf buffer)
|
||||
{
|
||||
int length = ByteBufUtils.readVarInt(buffer, 3);
|
||||
modIds = Maps.newHashMap();
|
||||
blockSubstitutions = Sets.newHashSet();
|
||||
itemSubstitutions = Sets.newHashSet();
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
modIds.put(ByteBufUtils.readUTF8String(buffer),ByteBufUtils.readVarInt(buffer, 3));
|
||||
}
|
||||
// we don't have any more data to read
|
||||
if (!buffer.isReadable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
length = ByteBufUtils.readVarInt(buffer, 3);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
blockSubstitutions.add(ByteBufUtils.readUTF8String(buffer));
|
||||
}
|
||||
length = ByteBufUtils.readVarInt(buffer, 3);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
itemSubstitutions.add(ByteBufUtils.readUTF8String(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -155,12 +178,33 @@ public abstract class FMLHandshakeMessage {
|
|||
ByteBufUtils.writeUTF8String(buffer, entry.getKey());
|
||||
ByteBufUtils.writeVarInt(buffer, entry.getValue(), 3);
|
||||
}
|
||||
|
||||
ByteBufUtils.writeVarInt(buffer, blockSubstitutions.size(), 3);
|
||||
for (String entry: blockSubstitutions)
|
||||
{
|
||||
ByteBufUtils.writeUTF8String(buffer, entry);
|
||||
}
|
||||
ByteBufUtils.writeVarInt(buffer, blockSubstitutions.size(), 3);
|
||||
|
||||
for (String entry: itemSubstitutions)
|
||||
{
|
||||
ByteBufUtils.writeUTF8String(buffer, entry);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String,Integer> dataList()
|
||||
{
|
||||
return modIds;
|
||||
}
|
||||
public Set<String> blockSubstitutions()
|
||||
{
|
||||
return blockSubstitutions;
|
||||
}
|
||||
public Set<String> itemSubstitutions()
|
||||
{
|
||||
return itemSubstitutions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(Class<? extends Enum<?>> side)
|
||||
{
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
package cpw.mods.fml.common.registry;
|
||||
|
||||
public class ExistingAliasException extends Exception {
|
||||
public ExistingAliasException(String fromName, String toName) {
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package cpw.mods.fml.common.registry;
|
||||
|
||||
public class ExistingSubstitutionException extends Exception {
|
||||
public ExistingSubstitutionException(String fromName, Object toReplace) {
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
|
@ -15,7 +15,6 @@ import net.minecraft.util.RegistryNamespaced;
|
|||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
|
@ -31,7 +30,8 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
// 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, String> persistentAliases = HashBiMap.create();
|
||||
private BiMap<String, I> persistentSubstitutions;
|
||||
private BiMap<String, I> activeSubstitutions = HashBiMap.create();
|
||||
|
||||
FMLControlledNamespacedRegistry(String optionalDefault, int maxIdValue, int minIdValue, Class<I> type, char discriminator)
|
||||
{
|
||||
|
@ -62,9 +62,9 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
// 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));
|
||||
// name -> obj lookup is inconsistent
|
||||
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, type, obj));
|
||||
if (!(activeSubstitutions.containsKey(name) || activeSubstitutions.containsValue(name)) && getRaw(name) != obj ) throw new IllegalStateException(String.format("Registry entry for name %s, id %d, doesn't yield the expected %s %s.", name, id, type, obj));
|
||||
// name -> id lookup is inconsistent
|
||||
if (getId(name) != id) throw new IllegalStateException(String.format("Registry entry for name %s doesn't yield the expected id %d.", name, id));
|
||||
if (!(activeSubstitutions.containsKey(name) || activeSubstitutions.containsValue(name)) && getId(name) != 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));
|
||||
// entry is blocked, thus should be empty
|
||||
|
@ -235,9 +235,6 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
*/
|
||||
public I getRaw(String name)
|
||||
{
|
||||
String aliasName = persistentAliases.get(name);
|
||||
name = aliasName != null ? aliasName : name;
|
||||
|
||||
I ret = superType.cast(super.getObject(name));
|
||||
|
||||
if (ret == null) // no match, try aliases recursively
|
||||
|
@ -322,10 +319,6 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
return ImmutableMap.copyOf(aliases);
|
||||
}
|
||||
|
||||
public Map<String, String> getPersistentAliases()
|
||||
{
|
||||
return ImmutableBiMap.copyOf(persistentAliases);
|
||||
}
|
||||
/**
|
||||
* Add the specified object to the registry.
|
||||
*
|
||||
|
@ -345,7 +338,10 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
{
|
||||
this.optionalDefaultObject = thing;
|
||||
}
|
||||
|
||||
if (getPersistentSubstitutions().containsValue(thing))
|
||||
{
|
||||
throw new IllegalArgumentException(String.format("The object %s (%s) cannot be added to the registry. It is already being used as a substitute for %s", thing.getClass(), name, getPersistentSubstitutions().inverse().get(thing)));
|
||||
}
|
||||
int idToUse = id;
|
||||
if (idToUse < 0 || availabilityMap.get(idToUse))
|
||||
{
|
||||
|
@ -365,7 +361,7 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
{
|
||||
throw new IllegalArgumentException(String.format("The name %s has been registered twice, for %s and %s.", name, getRaw(name), thing));
|
||||
}
|
||||
if (getId(thing) >= 0) // duplicate object
|
||||
if (getId(thing) >= 0) // duplicate object - but only if it's not being substituted
|
||||
{
|
||||
int foundId = getId(thing);
|
||||
Object otherThing = getRaw(foundId);
|
||||
|
@ -376,6 +372,10 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
FMLLog.bigWarning("The object %s (name %s) is being added too late.", thing, name);
|
||||
}
|
||||
|
||||
if (activeSubstitutions.containsKey(name))
|
||||
{
|
||||
thing = activeSubstitutions.get(name);
|
||||
}
|
||||
addObjectRaw(idToUse, name, thing);
|
||||
|
||||
FMLLog.finer("Registry add: %s %d %s (req. id %d)", name, idToUse, thing, id);
|
||||
|
@ -394,7 +394,13 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
|
||||
for (I thing : this.typeSafeIterable())
|
||||
{
|
||||
if (!registry.field_148758_b.containsKey(thing)) ret.put(getNameForObject(thing), getId(thing));
|
||||
if (!registry.field_148758_b.containsKey(thing))
|
||||
{
|
||||
if (!registry.activeSubstitutions.containsKey(getNameForObject(thing)))
|
||||
{
|
||||
ret.put(getNameForObject(thing), getId(thing));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -441,11 +447,54 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
return GameData.buildDelegate(thing, clazz);
|
||||
}
|
||||
|
||||
public void addPersistentAlias(String fromName, String toName) throws ExistingAliasException {
|
||||
if (persistentAliases.containsKey(fromName) || persistentAliases.containsKey(toName) || persistentAliases.containsValue(fromName) || persistentAliases.containsValue(toName))
|
||||
void activateSubstitution(String nameToReplace)
|
||||
{
|
||||
if (getPersistentSubstitutions().containsKey(nameToReplace))
|
||||
{
|
||||
throw new ExistingAliasException(fromName, toName);
|
||||
activeSubstitutions.put(nameToReplace, getPersistentSubstitutions().get(nameToReplace));
|
||||
}
|
||||
persistentAliases.put(fromName, toName);
|
||||
}
|
||||
|
||||
public void addSubstitutionAlias(String modId, String nameToReplace, Object toReplace) throws ExistingSubstitutionException {
|
||||
if (getPersistentSubstitutions().containsKey(nameToReplace) || getPersistentSubstitutions().containsValue(toReplace))
|
||||
{
|
||||
FMLLog.severe("The substitution of %s has already occured. You cannot duplicate substitutions", nameToReplace);
|
||||
throw new ExistingSubstitutionException(nameToReplace, toReplace);
|
||||
}
|
||||
I replacement = superType.cast(toReplace);
|
||||
I original = getRaw(nameToReplace);
|
||||
if (!original.getClass().isAssignableFrom(replacement.getClass()))
|
||||
{
|
||||
FMLLog.severe("The substitute %s for %s (type %s) is type incompatible. This won't work", replacement.getClass().getName(), nameToReplace, original.getClass().getName());
|
||||
throw new IncompatibleSubstitutionException(nameToReplace, replacement, original);
|
||||
}
|
||||
int existingId = getId(replacement);
|
||||
if (existingId != -1)
|
||||
{
|
||||
FMLLog.severe("The substitute %s for %s is registered into the game independently. This won't work", replacement.getClass().getName(), nameToReplace);
|
||||
throw new IllegalArgumentException("The object substitution is already registered. This won't work");
|
||||
}
|
||||
getPersistentSubstitutions().put(nameToReplace, replacement);
|
||||
}
|
||||
|
||||
public void serializeSubstitutions(Set<String> blockSubs)
|
||||
{
|
||||
blockSubs.addAll(activeSubstitutions.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIDForObject(Object p_148757_1_)
|
||||
{
|
||||
|
||||
int id = super.getIDForObject(p_148757_1_);
|
||||
return id;
|
||||
}
|
||||
private BiMap<String, I> getPersistentSubstitutions()
|
||||
{
|
||||
if (persistentSubstitutions == null)
|
||||
{
|
||||
persistentSubstitutions = GameData.getMain().getPersistentSubstitutionMap(superType);
|
||||
}
|
||||
return persistentSubstitutions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,11 +34,14 @@ import org.apache.logging.log4j.Level;
|
|||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Joiner.MapJoiner;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
|
@ -112,12 +115,27 @@ public class GameData {
|
|||
|
||||
// internal from here
|
||||
|
||||
public static Map<String,Integer> buildItemDataList()
|
||||
public static class GameDataSnapshot {
|
||||
public final Map<String,Integer> idMap;
|
||||
public final Set<String> blockSubstitutions;
|
||||
public final Set<String> itemSubstitutions;
|
||||
public GameDataSnapshot(Map<String, Integer> idMap, Set<String> blockSubstitutions, Set<String> itemSubstitutions)
|
||||
{
|
||||
this.idMap = idMap;
|
||||
this.blockSubstitutions = blockSubstitutions;
|
||||
this.itemSubstitutions = itemSubstitutions;
|
||||
}
|
||||
}
|
||||
public static GameDataSnapshot buildItemDataList()
|
||||
{
|
||||
Map<String,Integer> idMapping = Maps.newHashMap();
|
||||
getMain().iBlockRegistry.serializeInto(idMapping);
|
||||
getMain().iItemRegistry.serializeInto(idMapping);
|
||||
return idMapping;
|
||||
Set<String> blockSubs = Sets.newHashSet();
|
||||
getMain().iBlockRegistry.serializeSubstitutions(blockSubs);
|
||||
Set<String> itemSubs = Sets.newHashSet();
|
||||
getMain().iItemRegistry.serializeSubstitutions(itemSubs);
|
||||
return new GameDataSnapshot(idMapping, blockSubs, itemSubs);
|
||||
}
|
||||
|
||||
public static int[] getBlockedIds()
|
||||
|
@ -407,12 +425,12 @@ public class GameData {
|
|||
blockedIds.addAll(newBlockedIds);
|
||||
}
|
||||
|
||||
public static List<String> injectWorldIDMap(Map<String, Integer> dataList, boolean injectFrozenData, boolean isLocalWorld)
|
||||
public static List<String> injectWorldIDMap(Map<String, Integer> dataList, Set<String> blockSubstitutions, Set<String> itemSubstitutions, boolean injectFrozenData, boolean isLocalWorld)
|
||||
{
|
||||
return injectWorldIDMap(dataList, new HashSet<Integer>(), new HashMap<String, String>(), new HashMap<String, String>(), injectFrozenData, isLocalWorld);
|
||||
return injectWorldIDMap(dataList, new HashSet<Integer>(), new HashMap<String, String>(), new HashMap<String, String>(), blockSubstitutions, itemSubstitutions, injectFrozenData, isLocalWorld);
|
||||
}
|
||||
|
||||
public static List<String> injectWorldIDMap(Map<String, Integer> dataList, Set<Integer> blockedIds, Map<String, String> blockAliases, Map<String, String> itemAliases, boolean injectFrozenData, boolean isLocalWorld)
|
||||
public static List<String> injectWorldIDMap(Map<String, Integer> dataList, Set<Integer> blockedIds, Map<String, String> blockAliases, Map<String, String> itemAliases, Set<String> blockSubstitutions, Set<String> itemSubstitutions, boolean injectFrozenData, boolean isLocalWorld)
|
||||
{
|
||||
FMLLog.info("Injecting existing block and item data into this %s instance", FMLCommonHandler.instance().getEffectiveSide().isServer() ? "server" : "client");
|
||||
Map<String, Integer[]> remaps = Maps.newHashMap();
|
||||
|
@ -438,6 +456,31 @@ public class GameData {
|
|||
newData.iItemRegistry.addAlias(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
for (String entry : blockSubstitutions)
|
||||
{
|
||||
newData.iBlockRegistry.activateSubstitution(entry);
|
||||
}
|
||||
for (String entry : itemSubstitutions)
|
||||
{
|
||||
newData.iItemRegistry.activateSubstitution(entry);
|
||||
}
|
||||
if (injectFrozenData)
|
||||
{
|
||||
for (String newBlockSubstitution : getMain().blockSubstitutions.keySet())
|
||||
{
|
||||
if (!blockSubstitutions.contains(newBlockSubstitution))
|
||||
{
|
||||
newData.iBlockRegistry.activateSubstitution(newBlockSubstitution);
|
||||
}
|
||||
}
|
||||
for (String newItemSubstitution : getMain().itemSubstitutions.keySet())
|
||||
{
|
||||
if (!itemSubstitutions.contains(newItemSubstitution))
|
||||
{
|
||||
newData.iItemRegistry.activateSubstitution(newItemSubstitution);
|
||||
}
|
||||
}
|
||||
}
|
||||
// process blocks and items in the world, blocks in the first pass, items in the second
|
||||
// blocks need to be added first for proper ItemBlock handling
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
|
@ -479,10 +522,11 @@ public class GameData {
|
|||
|
||||
if (currId != newId)
|
||||
{
|
||||
throw new IllegalStateException(String.format("Can't map %s %s to id %d, already occupied by %s, blocked %b, ItemBlock %b",
|
||||
throw new IllegalStateException(String.format("Can't map %s %s to id %d (seen at: %d), already occupied by %s, blocked %b, ItemBlock %b",
|
||||
isBlock ? "block" : "item",
|
||||
itemName,
|
||||
newId,
|
||||
currId,
|
||||
isBlock ? newData.iBlockRegistry.getRaw(newId) : newData.iItemRegistry.getRaw(newId),
|
||||
newData.blockedIds.contains(newId),
|
||||
isBlock ? false : (getMain().iItemRegistry.getRaw(currId) instanceof ItemBlock)));
|
||||
|
@ -763,6 +807,10 @@ public class GameData {
|
|||
if (item instanceof ItemBlock) // ItemBlock, adjust id and clear the slot already occupied by the corresponding block
|
||||
{
|
||||
Block block = ((ItemBlock) item).field_150939_a;
|
||||
if (idHint != -1 && getMain().blockSubstitutions.containsKey(name))
|
||||
{
|
||||
block = getMain().blockSubstitutions.get(name);
|
||||
}
|
||||
int id = iBlockRegistry.getId(block);
|
||||
|
||||
if (id == -1) // ItemBlock before its Block
|
||||
|
@ -948,13 +996,32 @@ public class GameData {
|
|||
|
||||
FMLLog.fine("Registry consistency check successful");
|
||||
}
|
||||
|
||||
void registerPersistentAlias(String fromName, String toName, GameRegistry.Type type) throws ExistingAliasException
|
||||
|
||||
void registerSubstitutionAlias(String nameToSubstitute, Type type, Object toReplace) throws ExistingSubstitutionException
|
||||
{
|
||||
type.getRegistry().addPersistentAlias(fromName, toName);
|
||||
type.getRegistry().addSubstitutionAlias(Loader.instance().activeModContainer().getModId(),nameToSubstitute, toReplace);
|
||||
}
|
||||
static <T> RegistryDelegate<T> buildDelegate(T referant, Class<T> type)
|
||||
{
|
||||
return new RegistryDelegate.Delegate<T>(referant, type);
|
||||
}
|
||||
|
||||
private BiMap<String, Item> itemSubstitutions = HashBiMap.create();
|
||||
private BiMap<String, Block> blockSubstitutions = HashBiMap.create();
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> BiMap<String, T> getPersistentSubstitutionMap(Class<T> type)
|
||||
{
|
||||
if (type.equals(Item.class))
|
||||
{
|
||||
return (BiMap<String, T>) itemSubstitutions;
|
||||
}
|
||||
else if (type.equals(Block.class))
|
||||
{
|
||||
return (BiMap<String, T>) blockSubstitutions;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("WHAT?");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,18 +146,19 @@ public class GameRegistry
|
|||
|
||||
|
||||
/**
|
||||
* Add a forced persistent alias for the block or item to another block or item. This will have
|
||||
* the effect of using the substituted block or item instead of the original, whereever it is
|
||||
* Add a forced persistent substitution alias for the block or item to another block or item. This will have
|
||||
* the effect of using the substituted block or item instead of the original, where ever it is
|
||||
* referenced.
|
||||
*
|
||||
* @param toName The name to link to (this is the NEW block or item)
|
||||
* @param fromName The name to link from (this is the OLD block or item being substituted)
|
||||
*
|
||||
* @param nameToSubstitute The name to link to (this is the NEW block or item)
|
||||
* @param type The type (Block or Item)
|
||||
* @throws ExistingAliasException if someone else has already registered an alias either from or to one of the names
|
||||
* @param object a NEW instance that is type compatible with the existing instance
|
||||
* @throws ExistingSubstitutionException if someone else has already registered an alias either from or to one of the names
|
||||
* @throws IncompatibleSubstitutionException if the substitution is incompatible
|
||||
*/
|
||||
public static void addAlias(String toName, String fromName, GameRegistry.Type type) throws ExistingAliasException
|
||||
public static void addSubstitutionAlias(String nameToSubstitute, GameRegistry.Type type, Object object) throws ExistingSubstitutionException
|
||||
{
|
||||
GameData.getMain().registerPersistentAlias(fromName, toName, type);
|
||||
GameData.getMain().registerSubstitutionAlias(nameToSubstitute, type, object);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -406,7 +407,7 @@ public class GameRegistry
|
|||
}
|
||||
}
|
||||
|
||||
public static enum Type {
|
||||
public static enum Type {
|
||||
BLOCK
|
||||
{
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package cpw.mods.fml.common.registry;
|
||||
|
||||
public class IncompatibleSubstitutionException extends RuntimeException {
|
||||
public IncompatibleSubstitutionException(String fromName, Object replacement, Object original)
|
||||
{
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
|
@ -1,29 +1,53 @@
|
|||
package cpw.mods.fml.common.registry;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
|
||||
/**
|
||||
* A registry delegate for holding references to items or blocks
|
||||
*
|
||||
* These should be safe to use in things like lists though aliased items and blocks will not
|
||||
* have object identity with respect to their delegate.
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
* @param <T> the type of thing we're holding onto
|
||||
*/
|
||||
public interface RegistryDelegate<T> {
|
||||
/**
|
||||
* Get the referent pointed at by this delegate. This will be the currently active item or block, and will change
|
||||
* as world saves come and go. Note that item.delegate.get() may NOT be the same object as item, due to item and
|
||||
* block substitution.
|
||||
*
|
||||
* @return The referred object
|
||||
*/
|
||||
T get();
|
||||
|
||||
/**
|
||||
* Get the name of this delegate. This is completely static after registration has completed and will never change.
|
||||
* @return The name
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Get the delegate type. It will be Item or Block.
|
||||
* @return The type of delegate
|
||||
*/
|
||||
Class<T> type();
|
||||
|
||||
|
||||
/*
|
||||
* This is the internal implementation class of the delegate.
|
||||
*/
|
||||
final class Delegate<T> implements RegistryDelegate<T>
|
||||
{
|
||||
private T referant;
|
||||
private String name;
|
||||
private final Class<T> type;
|
||||
|
||||
|
||||
public Delegate(T referant, Class<T> type) {
|
||||
this.referant = referant;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return referant;
|
||||
|
@ -34,19 +58,37 @@ public interface RegistryDelegate<T> {
|
|||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> type()
|
||||
{
|
||||
return this.type;
|
||||
}
|
||||
|
||||
|
||||
void changeReference(T newTarget)
|
||||
{
|
||||
this.referant = newTarget;
|
||||
}
|
||||
|
||||
|
||||
void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj instanceof Delegate)
|
||||
{
|
||||
Delegate<?> other = (Delegate<?>) obj;
|
||||
return Objects.equal(other.name, name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hashCode(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue