Add validation to recipe registry (#4957)

This commit is contained in:
Ben Staddon 2018-06-27 06:00:53 +01:00 committed by mezz
parent d09a8d98d7
commit 43895d773e
6 changed files with 71 additions and 6 deletions

View file

@ -70,6 +70,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
private final CreateCallback<V> create;
private final AddCallback<V> add;
private final ClearCallback<V> clear;
private final ValidateCallback<V> validate;
private final MissingFactory<V> missing;
private final BitSet availabilityMap;
private final Set<ResourceLocation> dummies = Sets.newHashSet();
@ -86,7 +87,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
private V defaultValue = null;
boolean isFrozen = false;
ForgeRegistry(Class<V> superType, ResourceLocation defaultKey, int min, int max, @Nullable CreateCallback<V> create, @Nullable AddCallback<V> add, @Nullable ClearCallback<V> clear, RegistryManager stage, boolean allowOverrides, boolean isModifiable, @Nullable DummyFactory<V> dummyFactory, @Nullable MissingFactory<V> missing)
ForgeRegistry(Class<V> superType, ResourceLocation defaultKey, int min, int max, @Nullable CreateCallback<V> create, @Nullable AddCallback<V> add, @Nullable ClearCallback<V> clear, @Nullable ValidateCallback<V> validate, RegistryManager stage, boolean allowOverrides, boolean isModifiable, @Nullable DummyFactory<V> dummyFactory, @Nullable MissingFactory<V> missing)
{
this.stage = stage;
this.superType = superType;
@ -97,6 +98,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
this.create = create;
this.add = add;
this.clear = clear;
this.validate = validate;
this.missing = missing;
this.isDelegated = IForgeRegistryEntry.Impl.class.isAssignableFrom(superType); //TODO: Make this IDelegatedRegistryEntry?
this.allowOverrides = allowOverrides;
@ -269,7 +271,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
ForgeRegistry<V> copy(RegistryManager stage)
{
return new ForgeRegistry<V>(superType, defaultKey, min, max, create, add, clear, stage, allowOverrides, isModifiable, dummyFactory, missing);
return new ForgeRegistry<V>(superType, defaultKey, min, max, create, add, clear, validate, stage, allowOverrides, isModifiable, dummyFactory, missing);
}
int add(int id, V value)
@ -464,6 +466,10 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
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));
*/
// registry-specific validation
if (this.validate != null)
this.validate.onValidate(this, this.stage, id, name, obj);
}
}

View file

@ -402,10 +402,22 @@ public class GameData
}
}
private static class RecipeCallbacks implements IForgeRegistry.MissingFactory<IRecipe>
private static class RecipeCallbacks implements IForgeRegistry.ValidateCallback<IRecipe>, IForgeRegistry.MissingFactory<IRecipe>
{
static final RecipeCallbacks INSTANCE = new RecipeCallbacks();
@Override
public void onValidate(IForgeRegistryInternal<IRecipe> owner, RegistryManager stage, int id, ResourceLocation key, IRecipe obj)
{
if (stage != RegistryManager.ACTIVE) return;
// verify the recipe output yields a registered item
Item item = obj.getRecipeOutput().getItem();
if (!stage.getRegistry(Item.class).containsValue(item))
{
throw new IllegalStateException(String.format("Recipe %s (%s) produces unregistered item %s (%s)", key, obj, item.getRegistryName(), item));
}
}
@Override
public IRecipe createMissing(ResourceLocation key, boolean isNetwork)
{

View file

@ -94,6 +94,14 @@ public interface IForgeRegistry<V extends IForgeRegistryEntry<V>> extends Iterab
void onCreate(IForgeRegistryInternal<V> owner, RegistryManager stage);
}
/**
* Callback fired when the registry contents are validated.
*/
interface ValidateCallback<V extends IForgeRegistryEntry<V>>
{
void onValidate(IForgeRegistryInternal<V> owner, RegistryManager stage, int id, ResourceLocation key, V obj);
}
/**
* Factory for creating dummy entries, allowing worlds to be loaded and keep the missing block references.
*/

View file

@ -38,6 +38,7 @@ public class RegistryBuilder<T extends IForgeRegistryEntry<T>>
private List<AddCallback<T>> addCallback = Lists.newArrayList();
private List<ClearCallback<T>> clearCallback = Lists.newArrayList();
private List<CreateCallback<T>> createCallback = Lists.newArrayList();
private List<ValidateCallback<T>> validateCallback = Lists.newArrayList();
private boolean saveToDisc = true;
private boolean allowOverrides = true;
private boolean allowModifications = false;
@ -83,6 +84,8 @@ public class RegistryBuilder<T extends IForgeRegistryEntry<T>>
this.add((ClearCallback<T>)inst);
if (inst instanceof CreateCallback)
this.add((CreateCallback<T>)inst);
if (inst instanceof ValidateCallback)
this.add((ValidateCallback<T>)inst);
if (inst instanceof DummyFactory)
this.set((DummyFactory<T>)inst);
if (inst instanceof MissingFactory)
@ -108,6 +111,12 @@ public class RegistryBuilder<T extends IForgeRegistryEntry<T>>
return this;
}
public RegistryBuilder<T> add(ValidateCallback<T> validate)
{
this.validateCallback.add(validate);
return this;
}
public RegistryBuilder<T> set(DummyFactory<T> factory)
{
this.dummyFactory = factory;
@ -141,7 +150,7 @@ public class RegistryBuilder<T extends IForgeRegistryEntry<T>>
public IForgeRegistry<T> create()
{
return RegistryManager.ACTIVE.createRegistry(registryName, registryType, optionalDefaultKey, minId, maxId,
getAdd(), getClear(), getCreate(), saveToDisc, allowOverrides, allowModifications, dummyFactory, missingFactory);
getAdd(), getClear(), getCreate(), getValidate(), saveToDisc, allowOverrides, allowModifications, dummyFactory, missingFactory);
}
@Nullable
@ -188,4 +197,19 @@ public class RegistryBuilder<T extends IForgeRegistryEntry<T>>
cb.onCreate(owner, stage);
};
}
@Nullable
private ValidateCallback<T> getValidate()
{
if (validateCallback.isEmpty())
return null;
if (validateCallback.size() == 1)
return validateCallback.get(0);
return (owner, stage, id, key, obj) ->
{
for (ValidateCallback<T> cb : this.validateCallback)
cb.onValidate(owner, stage, id, key, obj);
};
}
}

View file

@ -75,7 +75,7 @@ public class RegistryManager
}
<V extends IForgeRegistryEntry<V>> ForgeRegistry<V> createRegistry(ResourceLocation name, Class<V> type, ResourceLocation defaultKey, int min, int max,
@Nullable AddCallback<V> add, @Nullable ClearCallback<V> clear, @Nullable CreateCallback<V> create,
@Nullable AddCallback<V> add, @Nullable ClearCallback<V> clear, @Nullable CreateCallback<V> create, @Nullable ValidateCallback<V> validate,
boolean persisted, boolean allowOverrides, boolean isModifiable, @Nullable DummyFactory<V> dummyFactory, @Nullable MissingFactory<V> missing)
{
Set<Class<?>> parents = Sets.newHashSet();
@ -87,7 +87,7 @@ public class RegistryManager
FMLLog.log.error("Found existing registry of type {} named {}, you cannot create a new registry ({}) with type {}, as {} has a parent of that type", foundType, superTypes.get(foundType), name, type, type);
throw new IllegalArgumentException("Duplicate registry parent type found - you can only have one registry for a particular super type");
}
ForgeRegistry<V> reg = new ForgeRegistry<V>(type, defaultKey, min, max, create, add, clear, this, allowOverrides, isModifiable, dummyFactory, missing);
ForgeRegistry<V> reg = new ForgeRegistry<V>(type, defaultKey, min, max, create, add, clear, validate, this, allowOverrides, isModifiable, dummyFactory, missing);
registries.put(name, reg);
superTypes.put(type, name);
if (persisted)

View file

@ -24,6 +24,7 @@ import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.AxisAlignedBB;
@ -50,6 +51,20 @@ public class RegistryOverrideTest
}
}
@SubscribeEvent
public static void registerItems(RegistryEvent.Register<Item> event)
{
if (!ENABLED) return;
event.getRegistry().register(
new Item()
.setFull3D()
.setUnlocalizedName("stick")
.setCreativeTab(CreativeTabs.MATERIALS)
.setRegistryName("minecraft:stick")
);
}
private static class BlockReplacement extends Block
{
AxisAlignedBB BB = FULL_BLOCK_AABB.contract(0.1, 0, 0.1);