Add support for loading mod advancements from the mod jar files.

This commit is contained in:
LexManos committed 2017-06-27 15:18:52 -07:00
1 parent cab4f783e9
commit a4fb33d945
4 files changed
+174 -54

No files matched your search

@@ -19,12 +19,16 @@
package net.minecraftforge.common;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.regex.Matcher;
@@ -37,6 +41,8 @@ import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.AdvancementManager;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.material.Material;
@@ -94,6 +100,7 @@ import net.minecraft.world.storage.loot.LootEntry;
import net.minecraft.world.storage.loot.LootTable;
import net.minecraft.world.storage.loot.LootTableManager;
import net.minecraft.world.storage.loot.conditions.LootCondition;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.AnvilUpdateEvent;
import net.minecraftforge.event.DifficultyChangeEvent;
@@ -118,12 +125,17 @@ import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.world.NoteBlockEvent;
import net.minecraftforge.fluids.IFluidBlock;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
public class ForgeHooks
{
//TODO: Loot tables?
@@ -1232,4 +1244,61 @@ public class ForgeHooks
{
MinecraftForge.EVENT_BUS.post(new BlockEvent.CropGrowEvent.Post(worldIn, pos, state, worldIn.getBlockState(pos)));
}
public static boolean loadAdvancements(Map<ResourceLocation, Advancement.Builder> map)
{
boolean errored = false;
Loader.instance().setActiveModContainer(null);
//Loader.instance().getActiveModList().forEach((mod) -> loadFactories(mod));
for (ModContainer mod : Loader.instance().getActiveModList())
{
errored |= !loadAdvancements(map, mod);
}
Loader.instance().setActiveModContainer(null);
return errored;
}
private static boolean loadAdvancements(Map<ResourceLocation, Advancement.Builder> map, ModContainer mod)
{
return CraftingHelper.findFiles(mod, "assets/" + mod.getModId() + "/advancements", null,
(root, file) ->
{
String relative = root.relativize(file).toString();
if (!"json".equals(FilenameUtils.getExtension(file.toString())) || relative.startsWith("_"))
return true;
String name = FilenameUtils.removeExtension(relative).replaceAll("\\\\", "/");
ResourceLocation key = new ResourceLocation(mod.getModId(), name);
if (!map.containsKey(key))
{
BufferedReader reader = null;
try
{
reader = Files.newBufferedReader(file);
Advancement.Builder builder = JsonUtils.fromJson(AdvancementManager.GSON, reader, Advancement.Builder.class);
map.put(key, builder);
}
catch (JsonParseException jsonparseexception)
{
FMLLog.log.error("Parsing error loading built-in advancement " + key, (Throwable)jsonparseexception);
return false;
}
catch (IOException ioexception)
{
FMLLog.log.error("Couldn't read advancement " + key + " from " + file, (Throwable)ioexception);
return false;
}
finally
{
IOUtils.closeQuietly(reader);
}
}
return true;
}
);
}
}
@@ -34,7 +34,9 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
import javax.annotation.Nonnull;
@@ -651,12 +653,80 @@ public class CraftingHelper {
}
private static boolean loadRecipes(ModContainer mod)
{
JsonContext ctx = new JsonContext(mod.getModId());
return findFiles(mod, "assets/" + mod.getModId() + "/recipes",
root ->
{
Path fPath = root.resolve("_constants.json");
if (fPath != null && Files.exists(fPath))
{
BufferedReader reader = null;
try
{
reader = Files.newBufferedReader(fPath);
JsonObject[] json = JsonUtils.fromJson(GSON, reader, JsonObject[].class);
ctx.loadConstants(json);
}
catch (IOException e)
{
FMLLog.log.error("Error loading _constants.json: ", e);
return false;
}
finally
{
IOUtils.closeQuietly(reader);
}
}
return true;
},
(root, file) ->
{
Loader.instance().setActiveModContainer(mod);
String relative = root.relativize(file).toString();
if (!"json".equals(FilenameUtils.getExtension(file.toString())) || relative.startsWith("_"))
return true;
String name = FilenameUtils.removeExtension(relative).replaceAll("\\\\", "/");
ResourceLocation key = new ResourceLocation(ctx.getModId(), name);
BufferedReader reader = null;
try
{
reader = Files.newBufferedReader(file);
JsonObject json = JsonUtils.fromJson(GSON, reader, JsonObject.class);
if (json.has("conditions") && !CraftingHelper.processConditions(JsonUtils.getJsonArray(json, "conditions"), ctx))
return true;
IRecipe recipe = CraftingHelper.getRecipe(json, ctx);
ForgeRegistries.RECIPES.register(recipe.setRegistryName(key));
}
catch (JsonParseException e)
{
FMLLog.log.error("Parsing error loading recipe {}", key, e);
return false;
}
catch (IOException e)
{
FMLLog.log.error("Couldn't read recipe {} from {}", key, file, e);
return false;
}
finally
{
IOUtils.closeQuietly(reader);
}
return true;
}
);
}
public static boolean findFiles(ModContainer mod, String base, Function<Path, Boolean> preprocessor, BiFunction<Path, Path, Boolean> processor)
{
FileSystem fs = null;
BufferedReader reader = null;
try
{
JsonContext ctx = new JsonContext(mod.getModId());
File source = mod.getSource();
if ("minecraft".equals(mod.getModId()) && DEBUG_LOAD_MINECRAFT)
@@ -679,7 +749,7 @@ public class CraftingHelper {
try
{
fs = FileSystems.newFileSystem(source.toPath(), null);
root = fs.getPath("/assets/" + ctx.getModId() + "/recipes");
root = fs.getPath("/" + base);
}
catch (IOException e)
{
@@ -689,77 +759,45 @@ public class CraftingHelper {
}
else if (source.isDirectory())
{
root = source.toPath().resolve("assets/" + ctx.getModId() + "/recipes");
root = source.toPath().resolve(base);
}
if (root == null || !Files.exists(root))
return false;
Path fPath = root.resolve("_constants.json");
if (fPath != null && Files.exists(fPath))
if (preprocessor != null)
{
Boolean cont = preprocessor.apply(root);
if (cont == null || !cont.booleanValue())
return false;
}
if (processor != null)
{
Iterator<Path> itr = null;
try
{
reader = Files.newBufferedReader(fPath);
JsonObject[] json = JsonUtils.fromJson(GSON, reader, JsonObject[].class);
ctx.loadConstants(json);
itr = Files.walk(root).iterator();
}
catch (IOException e)
{
FMLLog.log.error("Error loading _constants.json: ", e);
FMLLog.log.error("Error iterating filesystem for: {}", mod.getModId(), e);
return false;
}
}
Iterator<Path> itr = null;
try
{
itr = Files.walk(root).iterator();
}
catch (IOException e)
{
FMLLog.log.error("Error iterating recipes for: {}", ctx.getModId(), e);
return false;
}
Loader.instance().setActiveModContainer(mod);
while (itr != null && itr.hasNext())
{
Path f = itr.next();
if (!"json".equals(FilenameUtils.getExtension(f.toString())) || root.relativize(f).toString().startsWith("_"))
continue;
String name = FilenameUtils.removeExtension(root.relativize(f).toString()).replaceAll("\\\\", "/");
ResourceLocation key = new ResourceLocation(ctx.getModId(), name);
IOUtils.closeQuietly(reader);
try
while (itr != null && itr.hasNext())
{
reader = Files.newBufferedReader(f);
JsonObject json = JsonUtils.fromJson(GSON, reader, JsonObject.class);
if (json.has("conditions") && !CraftingHelper.processConditions(JsonUtils.getJsonArray(json, "conditions"), ctx))
continue;
IRecipe recipe = CraftingHelper.getRecipe(json, ctx);
ForgeRegistries.RECIPES.register(recipe.setRegistryName(key));
Boolean cont = processor.apply(root, itr.next());
if (cont == null || !cont.booleanValue())
return false;
}
catch (JsonParseException e)
{
FMLLog.log.error("Parsing error loading recipe {}", key, e);
return false;
}
catch (IOException e)
{
FMLLog.log.error("Couldn't read recipe {} from {}", key, f, e);
return false;
}
}
}
return true;
}
finally
{
IOUtils.closeQuietly(fs);
IOUtils.closeQuietly(reader);
}
}
}