Add support for server side only recipes, as well as detection of vanilla client recipe book filter to prevent errors.

This commit is contained in:
LexManos committed 2017-08-15 05:10:07 -07:00
1 parent ee27276ba2
commit 28e341002f
14 files changed
+168 -55

No files matched your search

@@ -30,8 +30,11 @@ import net.minecraft.block.state.IBlockState;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.init.Items;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionType;
@@ -40,6 +43,7 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.registry.RegistryNamespaced;
import net.minecraft.util.registry.RegistryNamespacedDefaultedByKey;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.RegistryEvent;
@@ -128,7 +132,7 @@ public class GameData
makeRegistry(SOUNDEVENTS, SoundEvent.class, MAX_SOUND_ID).create();
makeRegistry(POTIONTYPES, PotionType.class, MAX_POTIONTYPE_ID, new ResourceLocation("empty")).create();
makeRegistry(ENCHANTMENTS, Enchantment.class, MAX_ENCHANTMENT_ID).create();
makeRegistry(RECIPES, IRecipe.class, MAX_RECIPE_ID).disableSaving().allowModification().create();
makeRegistry(RECIPES, IRecipe.class, MAX_RECIPE_ID).disableSaving().allowModification().addCallback(RecipeCallbacks.INSTANCE).create();
makeRegistry(PROFESSIONS, VillagerProfession.class, MAX_PROFESSION_ID).create();
entityRegistry = (ForgeRegistry<EntityEntry>)makeRegistry(ENTITIES, EntityEntry.class, MAX_ENTITY_ID).addCallback(EntityCallbacks.INSTANCE).create();
}
@@ -276,7 +280,6 @@ public class GameData
private static class BlockCallbacks implements IForgeRegistry.AddCallback<Block>, IForgeRegistry.ClearCallback<Block>, IForgeRegistry.CreateCallback<Block>, IForgeRegistry.DummyFactory<Block>
{
static final BlockCallbacks INSTANCE = new BlockCallbacks();
Field regName;
@SuppressWarnings("deprecation")
@Override
@@ -349,31 +352,8 @@ public class GameData
@Override
public Block createDummy(ResourceLocation key)
{
if (regName == null)
{
try
{
regName = IForgeRegistryEntry.Impl.class.getDeclaredField("registryName");
regName.setAccessible(true);
}
catch (NoSuchFieldException | SecurityException e)
{
FMLLog.log.error("Could not get `registryName` field from IForgeRegistryEntry.Impl");
FMLLog.log.throwing(Level.ERROR, e);
throw new RuntimeException(e);
}
}
Block ret = new BlockDummyAir().setUnlocalizedName("air");
try
{
regName.set(ret, key);
}
catch (IllegalArgumentException | IllegalAccessException e)
{
FMLLog.log.error("Could not set `registryName` field in IForgeRegistryEntry.Impl to `{}`", key.toString());
FMLLog.log.throwing(Level.ERROR, e);
throw new RuntimeException(e);
}
GameData.forceRegistryName(ret, key);
return ret;
}
private static class BlockDummyAir extends BlockAir //A named class so DummyBlockReplacementTest can detect if its a dummy
@@ -414,6 +394,35 @@ public class GameData
}
}
private static class RecipeCallbacks implements IForgeRegistry.MissingFactory<IRecipe>
{
static final RecipeCallbacks INSTANCE = new RecipeCallbacks();
@Override
public IRecipe createMissing(ResourceLocation key, boolean isNetwork)
{
return isNetwork ? new DummyRecipe().setRegistryName(key) : null;
}
private static class DummyRecipe implements IRecipe
{
private static ItemStack result = new ItemStack(Items.DIAMOND, 64);
private ResourceLocation name;
@Override
public IRecipe setRegistryName(ResourceLocation name) {
this.name = name;
return this;
}
@Override public ResourceLocation getRegistryName() { return name; }
@Override public Class<IRecipe> getRegistryType() { return IRecipe.class; }
@Override public boolean matches(InventoryCrafting inv, World worldIn) { return false; } //dirt?
@Override public ItemStack getCraftingResult(InventoryCrafting inv) { return result; }
@Override public boolean canFit(int width, int height) { return false; }
@Override public ItemStack getRecipeOutput() { return result; }
@Override public boolean isHidden() { return true; }
}
}
private static ForgeRegistry<EntityEntry> entityRegistry;
public static ForgeRegistry<EntityEntry> getEntityRegistry() { return entityRegistry; }
@@ -559,16 +568,12 @@ public class GameData
if (!lst.isEmpty())
{
FMLLog.log.error("Unidentified mapping from registry {}", name);
lst.forEach(map -> {
FMLLog.log.error(" {}: {}", map.key, map.id);
if (!isLocalWorld)
defaulted.put(name, map.key);
});
lst.forEach(map -> FMLLog.log.error(" {}: {}", map.key, map.id));
}
event.getAllMappings().stream().filter(e -> e.getAction() == MissingMappings.Action.FAIL).forEach(fail -> failed.put(name, fail.key));
final Class<? extends IForgeRegistryEntry> clazz = RegistryManager.ACTIVE.getSuperType(name);
processMissing(clazz, name, STAGING, event, m.getValue(), remaps.get(name), defaulted.get(name), failed.get(name));
processMissing(clazz, name, STAGING, event, m.getValue(), remaps.get(name), defaulted.get(name), failed.get(name), !isLocalWorld);
});
if (!defaulted.isEmpty() && !isLocalWorld)
@@ -679,12 +684,12 @@ public class GameData
//Another bouncer for generic reasons
@SuppressWarnings("unchecked")
private static <T extends IForgeRegistryEntry<T>> void processMissing(Class<T> clazz, ResourceLocation name, RegistryManager STAGING, MissingMappings<?> e, Map<ResourceLocation, Integer> missing, Map<ResourceLocation, Integer[]> remaps, Collection<ResourceLocation> defaulted, Collection<ResourceLocation> failed)
private static <T extends IForgeRegistryEntry<T>> void processMissing(Class<T> clazz, ResourceLocation name, RegistryManager STAGING, MissingMappings<?> e, Map<ResourceLocation, Integer> missing, Map<ResourceLocation, Integer[]> remaps, Collection<ResourceLocation> defaulted, Collection<ResourceLocation> failed, boolean injectNetworkDummies)
{
List<MissingMappings.Mapping<T>> mappings = ((MissingMappings<T>)e).getAllMappings();
ForgeRegistry<T> active = RegistryManager.ACTIVE.getRegistry(name);
ForgeRegistry<T> staging = STAGING.getRegistry(name);
staging.processMissingEvent(name, active, mappings, missing, remaps, defaulted, failed);
staging.processMissingEvent(name, active, mappings, missing, remaps, defaulted, failed, injectNetworkDummies);
}
private static <T extends IForgeRegistryEntry<T>> void loadFrozenDataToStagingRegistry(RegistryManager STAGING, ResourceLocation name, Map<ResourceLocation, Integer[]> remaps, Class<T> clazz)
@@ -742,4 +747,34 @@ public class GameData
});
*/
}
private static Field regName;
private static void forceRegistryName(IForgeRegistryEntry<?> entry, ResourceLocation name)
{
if (regName == null)
{
try
{
regName = IForgeRegistryEntry.Impl.class.getDeclaredField("registryName");
regName.setAccessible(true);
}
catch (NoSuchFieldException | SecurityException e)
{
FMLLog.log.error("Could not get `registryName` field from IForgeRegistryEntry.Impl");
FMLLog.log.throwing(Level.ERROR, e);
throw new RuntimeException(e);
}
}
try
{
regName.set(entry, name);
}
catch (IllegalArgumentException | IllegalAccessException e)
{
FMLLog.log.error("Could not set `registryName` field in IForgeRegistryEntry.Impl to `{}`", name.toString());
FMLLog.log.throwing(Level.ERROR, e);
throw new RuntimeException(e);
}
}
}