Registry: Protect against putObject misuse, handle duplicate registrations better
This commit is contained in:
parent
6ffbcc5903
commit
07d5d5c7af
3 changed files with 96 additions and 46 deletions
|
@ -45,6 +45,13 @@ public class FMLLog
|
|||
log(Level.ERROR, format, data);
|
||||
}
|
||||
|
||||
public static void bigWarning(String format, Object... data)
|
||||
{
|
||||
log(Level.WARN, "****************************************");
|
||||
log(Level.WARN, "* "+format, data);
|
||||
log(Level.WARN, "****************************************");
|
||||
}
|
||||
|
||||
public static void warning(String format, Object... data)
|
||||
{
|
||||
log(Level.WARN, format, data);
|
||||
|
|
|
@ -52,7 +52,7 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
|
||||
for (I thing : (Iterable<I>) registry)
|
||||
{
|
||||
super.addObject(registry.getId(thing), registry.getNameForObject(thing), thing);
|
||||
addObjectRaw(registry.getId(thing), registry.getNameForObject(thing), thing);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,39 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
GameData.getMain().register(thing, name, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* DANGEROUS! EVIL! DO NOT USE!
|
||||
*
|
||||
* @deprecated register through {@link GameRegistry} instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public void putObject(Object objName, Object obj)
|
||||
{
|
||||
String name = (String) objName;
|
||||
I thing = (I) 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.");
|
||||
|
||||
String existingName = getNameForObject(thing);
|
||||
|
||||
if (existingName == null)
|
||||
{
|
||||
FMLLog.bigWarning("Ignoring putObject(%s, %s), not resolvable", name, thing);
|
||||
}
|
||||
else if (existingName.equals(name))
|
||||
{
|
||||
FMLLog.bigWarning("Ignoring putObject(%s, %s), already added", name, thing);
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.bigWarning("Ignoring putObject(%s, %s), adding alias to %s instead", name, thing, existingName);
|
||||
addAlias(name, existingName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public I getObject(String name)
|
||||
{
|
||||
|
@ -235,33 +268,34 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
name = prefix + ":"+ name;
|
||||
}
|
||||
|
||||
if (getRaw(name) != null)
|
||||
if (getRaw(name) == thing) // already registered, return prev registration's id
|
||||
{
|
||||
FMLLog.warning("****************************************");
|
||||
FMLLog.warning("* The name %s has been registered twice, for %s and %s.", name, getRaw(name), thing);
|
||||
FMLLog.warning("****************************************");
|
||||
FMLLog.bigWarning("The object %s has been registered twice for the same name %s.", thing, name);
|
||||
return getId(thing);
|
||||
}
|
||||
if (getId(thing) >= 0)
|
||||
if (getRaw(name) != null) // duplicate name, will crash later due to the BiMap
|
||||
{
|
||||
FMLLog.warning("****************************************");
|
||||
FMLLog.warning("* The object %s has been registered twice, using the names %s and %s.", thing, getNameForObject(thing), name);
|
||||
FMLLog.warning("****************************************");
|
||||
FMLLog.bigWarning("The name %s has been registered twice, for %s and %s.", name, getRaw(name), thing);
|
||||
}
|
||||
if (getId(thing) >= 0) // duplicate object, will crash later due to the BiMap
|
||||
{
|
||||
FMLLog.bigWarning("The object %s has been registered twice, using the names %s and %s.", thing, getNameForObject(thing), name);
|
||||
}
|
||||
if (GameData.isFrozen(this))
|
||||
{
|
||||
FMLLog.warning("****************************************");
|
||||
FMLLog.warning("* The object %s (name %s) is being added too late.", thing, name);
|
||||
FMLLog.warning("****************************************");
|
||||
FMLLog.bigWarning("The object %s (name %s) is being added too late.", thing, name);
|
||||
}
|
||||
|
||||
super.addObject(idToUse, name, thing);
|
||||
FMLLog.finer("Add : %s %d %s", name, idToUse, thing);
|
||||
addObjectRaw(idToUse, name, thing);
|
||||
|
||||
FMLLog.finer("Registry add: %s %d %s", name, idToUse, thing);
|
||||
return idToUse;
|
||||
}
|
||||
|
||||
void addAlias(String from, String to)
|
||||
{
|
||||
aliases.put(from, to);
|
||||
FMLLog.finer("Registry alias: %s -> %s", from, to);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -293,7 +327,19 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespaced {
|
|||
for (int id : ids)
|
||||
{
|
||||
I thing = getRaw(id);
|
||||
FMLLog.finer("Registry : %s %d %s", getNameForObject(thing), id, thing);
|
||||
FMLLog.finer("Registry: %s %d %s", getNameForObject(thing), id, thing);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of addObject not using the API restricting overrides.
|
||||
*/
|
||||
private void addObjectRaw(int id, String name, I thing)
|
||||
{
|
||||
if (name == null) throw new NullPointerException();
|
||||
if (thing == null) throw new NullPointerException();
|
||||
|
||||
underlyingIntegerMap.func_148746_a(thing, id); // obj <-> id
|
||||
super.putObject(ensureNamespaced(name), thing); // name <-> obj
|
||||
}
|
||||
}
|
||||
|
|
|
@ -740,10 +740,7 @@ public class GameData {
|
|||
throw new IllegalStateException(String.format("The Item Registry slot %d is already used by %s", idHint, iItemRegistry.getObjectById(idHint)));
|
||||
}
|
||||
|
||||
if (!freeSlot(idHint)) // temporarily free the slot occupied by the Block for the ItemBlock registration
|
||||
{
|
||||
throw new IllegalStateException(String.format("The Registry slot %d is supposed to be blocked by the ItemBlock's Block's blockId at this point.", idHint));
|
||||
}
|
||||
freeSlot(idHint); // temporarily free the slot occupied by the Block for the item registration
|
||||
}
|
||||
|
||||
int itemId = iItemRegistry.add(idHint, name, item, availabilityMap);
|
||||
|
@ -756,11 +753,8 @@ public class GameData {
|
|||
}
|
||||
}
|
||||
|
||||
// normal item, block the Block Registry slot with the same id
|
||||
if (useSlot(itemId))
|
||||
{
|
||||
throw new IllegalStateException(String.format("Registry slot %d is supposed to be empty when adding a non-ItemBlock with the same id.", itemId));
|
||||
}
|
||||
// block the Block Registry slot with the same id
|
||||
useSlot(itemId);
|
||||
|
||||
return itemId;
|
||||
}
|
||||
|
@ -779,10 +773,7 @@ public class GameData {
|
|||
}
|
||||
int blockId = iBlockRegistry.add(idHint, name, block, availabilityMap);
|
||||
|
||||
if (useSlot(blockId))
|
||||
{
|
||||
throw new IllegalStateException(String.format("Registry slot %d is supposed to be empty when adding a Block with the same id.", blockId));
|
||||
}
|
||||
useSlot(blockId);
|
||||
|
||||
return blockId;
|
||||
}
|
||||
|
@ -796,18 +787,14 @@ public class GameData {
|
|||
useSlot(id);
|
||||
}
|
||||
|
||||
private boolean useSlot(int id)
|
||||
private void useSlot(int id)
|
||||
{
|
||||
boolean oldValue = availabilityMap.get(id);
|
||||
availabilityMap.set(id);
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
private boolean freeSlot(int id)
|
||||
private void freeSlot(int id)
|
||||
{
|
||||
boolean oldValue = availabilityMap.get(id);
|
||||
availabilityMap.clear(id);
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -825,14 +812,19 @@ public class GameData {
|
|||
for (Block block : (Iterable<Block>) iBlockRegistry)
|
||||
{
|
||||
int id = iBlockRegistry.getId(block);
|
||||
String name = iBlockRegistry.getNameForObject(block);
|
||||
|
||||
if (!availabilityMap.get(id))
|
||||
{
|
||||
throw new IllegalStateException(String.format("Registry entry for block %s, id %d, marked as empty.", block, id));
|
||||
if (id < 0) {
|
||||
throw new IllegalStateException(String.format("Registry entry for block %s, name %s, doesn't yield an id", block, name));
|
||||
}
|
||||
if (blockedIds.contains(id))
|
||||
{
|
||||
throw new IllegalStateException(String.format("Registry entry for block %s, id %d, marked as dangling.", block, id));
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -841,14 +833,19 @@ public class GameData {
|
|||
for (Item item : (Iterable<Item>) iItemRegistry)
|
||||
{
|
||||
int id = iItemRegistry.getId(item);
|
||||
String name = iItemRegistry.getNameForObject(item);
|
||||
|
||||
if (!availabilityMap.get(id))
|
||||
{
|
||||
throw new IllegalStateException(String.format("Registry entry for item %s, id %d, marked as empty.", item, id));
|
||||
if (id < 0) {
|
||||
throw new IllegalStateException(String.format("Registry entry for item %s, name %s, doesn't yield an id", item, name));
|
||||
}
|
||||
if (blockedIds.contains(id))
|
||||
{
|
||||
throw new IllegalStateException(String.format("Registry entry for item %s, id %d, marked as dangling.", item, id));
|
||||
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));
|
||||
}
|
||||
|
||||
if (item instanceof ItemBlock)
|
||||
|
|
Loading…
Reference in a new issue