Fix old 1.7 worlds with broken ID mappings
This commit is contained in:
parent
939a095896
commit
d392ddf3be
2 changed files with 80 additions and 0 deletions
|
@ -216,6 +216,14 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
||||||
NBTTagCompound dataTag = list.func_150305_b(i);
|
NBTTagCompound dataTag = list.func_150305_b(i);
|
||||||
dataList.put(dataTag.func_74779_i("K"), dataTag.func_74762_e("V"));
|
dataList.put(dataTag.func_74779_i("K"), dataTag.func_74762_e("V"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tag.func_74764_b("BlockedItemIds")) // no blocked id info -> old 1.7 save
|
||||||
|
{
|
||||||
|
// old 1.7 save potentially affected by the registry mapping bug
|
||||||
|
// fix the ids the best we can...
|
||||||
|
GameData.fixBrokenIds(dataList);
|
||||||
|
}
|
||||||
|
|
||||||
// blocked ids
|
// blocked ids
|
||||||
int[] blockedIds = tag.func_74759_k("BlockedItemIds");
|
int[] blockedIds = tag.func_74759_k("BlockedItemIds");
|
||||||
// block aliases
|
// block aliases
|
||||||
|
|
|
@ -218,6 +218,78 @@ public class GameData {
|
||||||
return ui;
|
return ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix IDs improperly allocated by early versions of the registry, best-effort.
|
||||||
|
*
|
||||||
|
* Items sharing the same ID with a block, but not sharing the same registry name will be
|
||||||
|
* mapped to an unused id. Losing items instead of blocks should minimize the damage.
|
||||||
|
*
|
||||||
|
* @param dataList List containing the IDs to fix
|
||||||
|
*/
|
||||||
|
public static void fixBrokenIds(Map<String, Integer> dataList)
|
||||||
|
{
|
||||||
|
BitSet availabilityMap = new BitSet(32000);
|
||||||
|
|
||||||
|
// reserve all ids occupied by blocks
|
||||||
|
for (Entry<String, Integer> entry : dataList.entrySet())
|
||||||
|
{
|
||||||
|
String itemName = entry.getKey();
|
||||||
|
|
||||||
|
if (itemName.charAt(0) == '\u0001') // is a block
|
||||||
|
{
|
||||||
|
availabilityMap.set(entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> itemsToAllocate = new HashSet<String>();
|
||||||
|
|
||||||
|
// check all ids occupied by items
|
||||||
|
for (Entry<String, Integer> entry : dataList.entrySet())
|
||||||
|
{
|
||||||
|
String itemName = entry.getKey();
|
||||||
|
|
||||||
|
if (itemName.charAt(0) != '\u0001') // is an item
|
||||||
|
{
|
||||||
|
int oldId = entry.getValue();
|
||||||
|
|
||||||
|
if (availabilityMap.get(oldId)) // id is already occupied
|
||||||
|
{
|
||||||
|
String realName = itemName.substring(1);
|
||||||
|
String blockName = '\u0001' + realName;
|
||||||
|
|
||||||
|
if (!dataList.containsKey(blockName) ||
|
||||||
|
!(getMain().iItemRegistry.getRaw(realName) instanceof ItemBlock)) // the slot is occupied by something else and this item is no ItemBlock
|
||||||
|
{
|
||||||
|
// relocate the item later, after all correct ids have been claimed
|
||||||
|
itemsToAllocate.add(itemName);
|
||||||
|
}
|
||||||
|
else if (dataList.get(blockName) != oldId) // occupied, but this is an ItemBlock for a different block than whatever may use its id
|
||||||
|
{
|
||||||
|
// relocate to the matching block
|
||||||
|
int newId = dataList.get(blockName);
|
||||||
|
entry.setValue(newId);
|
||||||
|
|
||||||
|
FMLLog.warning("Fixed ItemBlock %s not using the id of its block, old id %d, new id %d.", realName, oldId, newId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // unused id, occupy
|
||||||
|
{
|
||||||
|
availabilityMap.set(oldId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String itemName : itemsToAllocate)
|
||||||
|
{
|
||||||
|
int oldId = dataList.get(itemName);
|
||||||
|
int newId = availabilityMap.nextClearBit(4096);
|
||||||
|
|
||||||
|
dataList.put(itemName, newId);
|
||||||
|
|
||||||
|
FMLLog.warning("Fixed Item %s conflicting with another block/item, old id %d, new id %d.", itemName.substring(1), oldId, newId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static List<String> injectWorldIDMap(Map<String, Integer> dataList, boolean injectFrozenData, boolean isLocalWorld)
|
public static List<String> injectWorldIDMap(Map<String, Integer> dataList, boolean injectFrozenData, boolean isLocalWorld)
|
||||||
{
|
{
|
||||||
return injectWorldIDMap(dataList, new int[0], new HashMap<String, String>(), new HashMap<String, String>(), injectFrozenData, isLocalWorld);
|
return injectWorldIDMap(dataList, new int[0], new HashMap<String, String>(), new HashMap<String, String>(), injectFrozenData, isLocalWorld);
|
||||||
|
|
Loading…
Reference in a new issue