From 416bf9e3bff1df662f7944b1197bfce03700f99e Mon Sep 17 00:00:00 2001 From: tterrag Date: Sun, 2 Dec 2018 00:46:19 +0000 Subject: [PATCH] Allow loading json constants outside of _constants --- .../common/crafting/CraftingHelper.java | 113 ++++++++++-------- .../registries/ForgeRegistryEntry.java | 2 +- .../minecraftforge/registries/GameData.java | 21 +++- .../debug/gameplay/ConstantLoadingTest.java | 62 ++++++++++ .../constantloadingtest/test/_constants.json | 8 ++ 5 files changed, 151 insertions(+), 55 deletions(-) create mode 100644 src/test/java/net/minecraftforge/debug/gameplay/ConstantLoadingTest.java create mode 100644 src/test/resources/assets/constantloadingtest/test/_constants.json diff --git a/src/main/java/net/minecraftforge/common/crafting/CraftingHelper.java b/src/main/java/net/minecraftforge/common/crafting/CraftingHelper.java index 67ffc5249..aaa7298a2 100644 --- a/src/main/java/net/minecraftforge/common/crafting/CraftingHelper.java +++ b/src/main/java/net/minecraftforge/common/crafting/CraftingHelper.java @@ -31,6 +31,7 @@ import java.util.stream.Stream; import javax.annotation.Nullable; import net.minecraftforge.fml.ModList; + import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.Lists; @@ -302,60 +303,66 @@ public class CraftingHelper String path = key.getPath(); if (!path.equals("recipes/_constants.json")) //Top level only continue; - - try (IResource iresource = manager.getResource(key)) - { - JsonObject[] elements = JsonUtils.fromJson(GSON, IOUtils.toString(iresource.getInputStream(), StandardCharsets.UTF_8), JsonObject[].class); - for (int x = 0; x < elements.length; x++) - { - JsonObject json = elements[x]; - //Force namespace to the directory that this constants file is in, to prevent modders from overriding other's sneakily - //TODO: Move back to a resource pack/mod specific constant list? - ResourceLocation name = json.has("name") ? new ResourceLocation(JsonUtils.getString(json, "name")) : null; - if (name != null) - name = new ResourceLocation(key.getNamespace(), name.getPath()); - - if (json == null || json.size() == 0) - LOGGER.error(CRAFTHELPER, "Couldn't load constant #{} from {} as it's null or empty", x, key); - else if (!processConditions(json, "conditions")) - LOGGER.info(CRAFTHELPER, "Skipping loading constant #{} from {} as it's conditions were not met", x, key); - else if (name == null) - LOGGER.error(CRAFTHELPER, "Couldn't load constant #{} from {} as it's missing `name`", x, key); - else if (json.has("items")) - { - List items = new ArrayList<>(); - for (JsonElement item : JsonUtils.getJsonArray(json, "items")) - { - if (item.isJsonObject()) - items.add(getItemStack(item.getAsJsonObject(), true)); - else - { - LOGGER.error(CRAFTHELPER, "Couldn't load constant #{} from {} as it's `items` entry is not a object", x, key); - items.clear(); - break; - } - } - if (!items.isEmpty()) - tmp.put(name, new StackList(items)); - } - else if (json.has("tag")) - tmp.put(name, Ingredient.deserializeItemList(json)); - else if (json.has("item")) - tmp.put(name, new StackList(Lists.newArrayList(getItemStack(JsonUtils.getJsonObject(json, "item"), true)))); - else - LOGGER.error(CRAFTHELPER, "Couldn't load constant #{} from {} as it's missing `item` or `items` element", x, key); - } - - } - catch (IllegalArgumentException | JsonParseException e) - { - LOGGER.error(CRAFTHELPER, "Parsing error loading constants {}", key, e); - } - catch (IOException e) - { - LOGGER.error(CRAFTHELPER, "Couldn't read constants from {}", key, e); - } + + tmp.putAll(loadConstants(manager, key)); } constants = tmp; } + + public static Map loadConstants(IResourceManager manager, ResourceLocation key) { + Map tmp = new HashMap<>(); + try (IResource iresource = manager.getResource(key)) + { + JsonObject[] elements = JsonUtils.fromJson(GSON, IOUtils.toString(iresource.getInputStream(), StandardCharsets.UTF_8), JsonObject[].class); + for (int x = 0; x < elements.length; x++) + { + JsonObject json = elements[x]; + //Force namespace to the directory that this constants file is in, to prevent modders from overriding other's sneakily + //TODO: Move back to a resource pack/mod specific constant list? + ResourceLocation name = json.has("name") ? new ResourceLocation(JsonUtils.getString(json, "name")) : null; + if (name != null) + name = new ResourceLocation(key.getNamespace(), name.getPath()); + + if (json == null || json.size() == 0) + LOGGER.error(CRAFTHELPER, "Couldn't load constant #{} from {} as it's null or empty", x, key); + else if (!processConditions(json, "conditions")) + LOGGER.info(CRAFTHELPER, "Skipping loading constant #{} from {} as it's conditions were not met", x, key); + else if (name == null) + LOGGER.error(CRAFTHELPER, "Couldn't load constant #{} from {} as it's missing `name`", x, key); + else if (json.has("items")) + { + List items = new ArrayList<>(); + for (JsonElement item : JsonUtils.getJsonArray(json, "items")) + { + if (item.isJsonObject()) + items.add(getItemStack(item.getAsJsonObject(), true)); + else + { + LOGGER.error(CRAFTHELPER, "Couldn't load constant #{} from {} as it's `items` entry is not a object", x, key); + items.clear(); + break; + } + } + if (!items.isEmpty()) + tmp.put(name, new StackList(items)); + } + else if (json.has("tag")) + tmp.put(name, Ingredient.deserializeItemList(json)); + else if (json.has("item")) + tmp.put(name, new StackList(Lists.newArrayList(getItemStack(JsonUtils.getJsonObject(json, "item"), true)))); + else + LOGGER.error(CRAFTHELPER, "Couldn't load constant #{} from {} as it's missing `item` or `items` element", x, key); + } + + } + catch (IllegalArgumentException | JsonParseException e) + { + LOGGER.error(CRAFTHELPER, "Parsing error loading constants {}", key, e); + } + catch (IOException e) + { + LOGGER.error(CRAFTHELPER, "Couldn't read constants from {}", key, e); + } + return tmp; + } } diff --git a/src/main/java/net/minecraftforge/registries/ForgeRegistryEntry.java b/src/main/java/net/minecraftforge/registries/ForgeRegistryEntry.java index 26b0de2a2..b11fa7362 100644 --- a/src/main/java/net/minecraftforge/registries/ForgeRegistryEntry.java +++ b/src/main/java/net/minecraftforge/registries/ForgeRegistryEntry.java @@ -42,7 +42,7 @@ public abstract class ForgeRegistryEntry> imple if (getRegistryName() != null) throw new IllegalStateException("Attempted to set registry name with existing registry name! New: " + name + " Old: " + getRegistryName()); - this.registryName = GameData.checkPrefix(name); + this.registryName = GameData.checkPrefix(name, true); return (V)this; } diff --git a/src/main/java/net/minecraftforge/registries/GameData.java b/src/main/java/net/minecraftforge/registries/GameData.java index 0280f5083..a25c1e6e8 100644 --- a/src/main/java/net/minecraftforge/registries/GameData.java +++ b/src/main/java/net/minecraftforge/registries/GameData.java @@ -896,13 +896,32 @@ public class GameData } } + /** + * @deprecated Use {@link #checkPrefix(String, boolean)}. + */ + @Deprecated public static ResourceLocation checkPrefix(String name) + { + return checkPrefix(name, true); + } + + /** + * Check a name for a domain prefix, and if not present infer it from the + * current active mod container. + * + * @param name The name or resource location + * @param warnOverrides If true, logs a warning if domain differs from that of + * the currently currently active mod container + * + * @return The {@link ResourceLocation} with given or inferred domain + */ + public static ResourceLocation checkPrefix(String name, boolean warnOverrides) { int index = name.lastIndexOf(':'); String oldPrefix = index == -1 ? "" : name.substring(0, index).toLowerCase(Locale.ROOT); name = index == -1 ? name : name.substring(index + 1); String prefix = ModLoadingContext.get().getActiveContainer().getNamespace(); - if (!oldPrefix.equals(prefix) && oldPrefix.length() > 0) + if (warnOverrides && !oldPrefix.equals(prefix) && oldPrefix.length() > 0) { LogManager.getLogger().info("Potentially Dangerous alternative prefix `{}` for name `{}`, expected `{}`. This could be a intended override, but in most cases indicates a broken mod.", oldPrefix, name, prefix); prefix = oldPrefix; diff --git a/src/test/java/net/minecraftforge/debug/gameplay/ConstantLoadingTest.java b/src/test/java/net/minecraftforge/debug/gameplay/ConstantLoadingTest.java new file mode 100644 index 000000000..e7ff74633 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/gameplay/ConstantLoadingTest.java @@ -0,0 +1,62 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2018. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.debug.gameplay; + +import java.io.IOException; +import java.util.Map; +import java.util.stream.Stream; + +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.item.crafting.Ingredient.IItemList; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.crafting.CraftingHelper; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.server.FMLServerStartedEvent; + +@Mod(ConstantLoadingTest.MODID) +@Mod.EventBusSubscriber +public class ConstantLoadingTest +{ + public static final String MODID = "constantloadingtest"; + private static final boolean ENABLED = true; + + @SubscribeEvent + public void init(FMLServerStartedEvent event) throws IOException + { + if (!ENABLED) + { + return; + } + + Map constants = CraftingHelper.loadConstants(event.getServer().getResourceManager(), new ResourceLocation(MODID, "test/_constants.json")); + Ingredient flint = Ingredient.fromItemListStream(Stream.of(constants.get(new ResourceLocation("FLINT")))); + if (flint == null) + { + throw new IllegalStateException("Constant ingredient not loaded properly"); + } + if (!flint.test(new ItemStack(Items.FLINT))) + { + throw new IllegalStateException("Constant ingredient failed to match test input"); + } + } +} diff --git a/src/test/resources/assets/constantloadingtest/test/_constants.json b/src/test/resources/assets/constantloadingtest/test/_constants.json new file mode 100644 index 000000000..2b5301ea2 --- /dev/null +++ b/src/test/resources/assets/constantloadingtest/test/_constants.json @@ -0,0 +1,8 @@ +[ + { + "ingredient": { + "item": "minecraft:flint" + }, + "name": "FLINT" + } +] \ No newline at end of file