Registry: Fix Block-before-ItemBlock allocation when loading 1.6 world saves, more validation
This commit is contained in:
parent
09ff49fe58
commit
624e68e18e
2 changed files with 68 additions and 61 deletions
|
@ -285,19 +285,20 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
}
|
||||
|
||||
int idToUse = id;
|
||||
if (id == 0 || availabilityMap.get(id))
|
||||
if (idToUse < 0 || availabilityMap.get(idToUse))
|
||||
{
|
||||
idToUse = availabilityMap.nextClearBit(minId);
|
||||
}
|
||||
if (idToUse > maxId)
|
||||
{
|
||||
throw new RuntimeException(String.format("Invalid id %d - maximum id range exceeded.", id));
|
||||
throw new RuntimeException(String.format("Invalid id %d - maximum id range exceeded.", idToUse));
|
||||
}
|
||||
|
||||
ModContainer mc = Loader.instance().activeModContainer();
|
||||
if (mc != null)
|
||||
{
|
||||
String prefix = mc.getModId();
|
||||
if (name.contains(":")) FMLLog.bigWarning("Illegal extra prefix %s for name %s, invalid registry invocation/invalid name?", prefix, name);
|
||||
name = prefix + ":"+ name;
|
||||
}
|
||||
|
||||
|
@ -321,7 +322,7 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
|
||||
addObjectRaw(idToUse, name, thing);
|
||||
|
||||
FMLLog.finer("Registry add: %s %d %s", name, idToUse, thing);
|
||||
FMLLog.finer("Registry add: %s %d %s (req. id %d)", name, idToUse, thing, id);
|
||||
return idToUse;
|
||||
}
|
||||
|
||||
|
@ -369,8 +370,8 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
*/
|
||||
private void addObjectRaw(int id, String name, I thing)
|
||||
{
|
||||
if (name == null) throw new NullPointerException();
|
||||
if (thing == null) throw new NullPointerException();
|
||||
if (name == null) throw new NullPointerException("internal registry bug");
|
||||
if (thing == null) throw new NullPointerException("internal registry bug");
|
||||
|
||||
underlyingIntegerMap.func_148746_a(thing, id); // obj <-> id
|
||||
super.putObject(ensureNamespaced(name), thing); // name <-> obj
|
||||
|
|
|
@ -455,7 +455,7 @@ public class GameData {
|
|||
}
|
||||
else if (currId != newId)
|
||||
{
|
||||
FMLLog.fine("Found %s id mismatch %s : %d (was %d)", isBlock ? "block" : "item", itemName, currId, newId);
|
||||
FMLLog.fine("Fixed %s id mismatch %s: %d (init) -> %d (map).", isBlock ? "block" : "item", itemName, currId, newId);
|
||||
remaps.put(itemName, new Integer[] { currId, newId });
|
||||
}
|
||||
|
||||
|
@ -486,7 +486,7 @@ public class GameData {
|
|||
|
||||
if (!missingBlocks.isEmpty() || !missingItems.isEmpty())
|
||||
{
|
||||
FMLLog.info("Injecting new block and item data into this server instance");
|
||||
FMLLog.info("Injecting new block and item data into this server instance.");
|
||||
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
{
|
||||
|
@ -508,7 +508,7 @@ public class GameData {
|
|||
newId = newData.registerItem(frozen.iItemRegistry.getRaw(itemName), itemName, null, currId);
|
||||
}
|
||||
|
||||
FMLLog.info("Injected new block/item %s : %d (was %d)", itemName, newId, currId);
|
||||
FMLLog.info("Injected new block/item %s: %d (init) -> %d (map).", itemName, currId, newId);
|
||||
|
||||
if (newId != currId) // a new id was assigned
|
||||
{
|
||||
|
@ -568,7 +568,7 @@ public class GameData {
|
|||
|
||||
if (currId != newId)
|
||||
{
|
||||
FMLLog.info("Found %s id mismatch %s : %d (was %d)", remap.type == Type.BLOCK ? "block" : "item", newName, currId, newId);
|
||||
FMLLog.info("Fixed %s id mismatch %s: %d (init) -> %d (map).", remap.type == Type.BLOCK ? "block" : "item", newName, currId, newId);
|
||||
remaps.put(newName, new Integer[] { currId, newId });
|
||||
}
|
||||
}
|
||||
|
@ -642,6 +642,7 @@ public class GameData {
|
|||
{
|
||||
FMLLog.fine("Freezing block and item id maps");
|
||||
|
||||
getMain().testConsistency();
|
||||
frozen = new GameData(getMain());
|
||||
frozen.testConsistency();
|
||||
}
|
||||
|
@ -720,7 +721,7 @@ public class GameData {
|
|||
|
||||
int registerItem(Item item, String name, String modId)
|
||||
{
|
||||
return registerItem(item, name, modId, 0);
|
||||
return registerItem(item, name, modId, -1);
|
||||
}
|
||||
|
||||
int registerItem(Item item, String name, String modId, int idHint)
|
||||
|
@ -733,25 +734,35 @@ 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;
|
||||
idHint = iBlockRegistry.getId(block);
|
||||
int id = iBlockRegistry.getId(block);
|
||||
|
||||
if (idHint == -1) // ItemBlock before its Block
|
||||
if (id == -1) // ItemBlock before its Block
|
||||
{
|
||||
idHint = availabilityMap.nextClearBit(MIN_BLOCK_ID); // find suitable id here, iItemRegistry would search from MIN_ITEM_ID
|
||||
if (idHint > MAX_BLOCK_ID) throw new RuntimeException(String.format("Invalid id %d - maximum id range exceeded.", idHint));
|
||||
if (idHint < 0 || availabilityMap.get(idHint) || idHint > MAX_BLOCK_ID) // non-suitable id, allocate one in the block id range, add would use the item id range otherwise
|
||||
{
|
||||
id = availabilityMap.nextClearBit(MIN_BLOCK_ID); // find suitable id here, iItemRegistry would search from MIN_ITEM_ID
|
||||
if (id > MAX_BLOCK_ID) throw new RuntimeException(String.format("Invalid id %d - maximum id range exceeded.", id));
|
||||
FMLLog.fine("Allocated id %d for ItemBlock %s in the block id range, original id requested: %d.", id, name, idHint);
|
||||
}
|
||||
else // idHint is suitable without changes
|
||||
{
|
||||
id = idHint;
|
||||
}
|
||||
}
|
||||
else // ItemBlock after its Block
|
||||
{
|
||||
FMLLog.fine("Found matching Block %s for ItemBlock %s at id %d", block, item, idHint);
|
||||
freeSlot(idHint, item); // temporarily free the slot occupied by the Block for the item registration
|
||||
FMLLog.fine("Found matching Block %s for ItemBlock %s at id %d, original id requested: %d", block, item, id, idHint);
|
||||
freeSlot(id, item); // temporarily free the slot occupied by the Block for the item registration
|
||||
}
|
||||
|
||||
idHint = id;
|
||||
}
|
||||
|
||||
int itemId = iItemRegistry.add(idHint, name, item, availabilityMap);
|
||||
|
||||
if (item instanceof ItemBlock) // verify
|
||||
{
|
||||
if (itemId != idHint) throw new IllegalStateException("Block -> ItemBlock insertion failed.");
|
||||
if (itemId != idHint) throw new IllegalStateException(String.format("ItemBlock at block id %d insertion failed, got id %d.", idHint, itemId));
|
||||
verifyItemBlockName((ItemBlock) item);
|
||||
}
|
||||
|
||||
|
@ -763,7 +774,7 @@ public class GameData {
|
|||
|
||||
int registerBlock(Block block, String name, String modId)
|
||||
{
|
||||
return registerBlock(block, name, modId, 0);
|
||||
return registerBlock(block, name, modId, -1);
|
||||
}
|
||||
|
||||
int registerBlock(Block block, String name, String modId, int idHint)
|
||||
|
@ -798,7 +809,7 @@ public class GameData {
|
|||
|
||||
if (itemBlock != null) // verify
|
||||
{
|
||||
if (blockId != idHint) throw new IllegalStateException("ItemBlock -> Block insertion failed.");
|
||||
if (blockId != idHint) throw new IllegalStateException(String.format("Block at itemblock id %d insertion failed, got id %d.", idHint, blockId));
|
||||
verifyItemBlockName(itemBlock);
|
||||
}
|
||||
|
||||
|
@ -865,53 +876,48 @@ public class GameData {
|
|||
}
|
||||
}
|
||||
|
||||
// test if there's a bit in availabilityMap set for every entry in the block registry, make sure it's not a blocked id
|
||||
for (Block block : (Iterable<Block>) iBlockRegistry)
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
{
|
||||
int id = iBlockRegistry.getId(block);
|
||||
String name = iBlockRegistry.getNameForObject(block);
|
||||
boolean isBlock = pass == 0;
|
||||
String type = isBlock ? "block" : "item";
|
||||
FMLControlledNamespacedRegistry registry = isBlock ? iBlockRegistry : iItemRegistry;
|
||||
|
||||
if (id < 0) {
|
||||
throw new IllegalStateException(String.format("Registry entry for block %s, name %s, doesn't yield an id", block, name));
|
||||
}
|
||||
if (name == null) {
|
||||
throw new IllegalStateException(String.format("Registry entry for block %s, id %d, doesn't yield a name", block, id));
|
||||
}
|
||||
if (!availabilityMap.get(id)) {
|
||||
throw new IllegalStateException(String.format("Registry entry for block %s, id %d, name %s, marked as empty.", block, id, name));
|
||||
}
|
||||
if (blockedIds.contains(id)) {
|
||||
throw new IllegalStateException(String.format("Registry entry for block %s, id %d, name %s, marked as dangling.", block, id, name));
|
||||
}
|
||||
}
|
||||
|
||||
// test if there's a bit in availabilityMap set for every entry in the item registry, make sure it's not a blocked id,
|
||||
// check if ItemBlocks have blocks with matching ids in the block registry
|
||||
for (Item item : (Iterable<Item>) iItemRegistry)
|
||||
// test if the registry is consistent
|
||||
// test if there's a bit in availabilityMap set for every entry in the registry
|
||||
// make sure it's not a blocked id
|
||||
for (Object obj : registry)
|
||||
{
|
||||
int id = iItemRegistry.getId(item);
|
||||
String name = iItemRegistry.getNameForObject(item);
|
||||
int id = registry.getId(obj);
|
||||
String name = registry.getNameForObject(obj);
|
||||
|
||||
if (id < 0) {
|
||||
throw new IllegalStateException(String.format("Registry entry for item %s, name %s, doesn't yield an id", item, name));
|
||||
}
|
||||
if (name == null) {
|
||||
throw new IllegalStateException(String.format("Registry entry for item %s, id %d, doesn't yield a name", item, id));
|
||||
}
|
||||
if (!availabilityMap.get(id)) {
|
||||
throw new IllegalStateException(String.format("Registry entry for item %s, id %d, name %s, marked as empty.", item, id, name));
|
||||
}
|
||||
if (blockedIds.contains(id)) {
|
||||
throw new IllegalStateException(String.format("Registry entry for item %s, id %d, name %s, marked as dangling.", item, id, name));
|
||||
}
|
||||
// id lookup failed -> obj is not in the obj<->id map
|
||||
if (id < 0) throw new IllegalStateException(String.format("Registry entry for %s %s, name %s, doesn't yield an id.", type, obj, name));
|
||||
// id is too high
|
||||
if (id > (isBlock ? MAX_BLOCK_ID : MAX_ITEM_ID)) throw new IllegalStateException(String.format("Registry entry for %s %s, name %s uses the too large id %d.", type, obj, 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));
|
||||
// id -> obj lookup is inconsistent
|
||||
if (registry.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 (registry.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 (registry.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
|
||||
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 (item instanceof ItemBlock)
|
||||
if (obj instanceof ItemBlock)
|
||||
{
|
||||
Block block = ((ItemBlock) item).field_150939_a;
|
||||
Block block = ((ItemBlock) obj).field_150939_a;
|
||||
|
||||
// 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.", item, id, iBlockRegistry.getId(block)));
|
||||
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 > MAX_BLOCK_ID) throw new IllegalStateException(String.format("ItemBlock %s uses the id %d outside the block id range", name, id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue