diff --git a/src/main/java/com/hermanoid/nerd/NEI_NERD_Config.java b/src/main/java/com/hermanoid/nerd/NEI_NERD_Config.java index 5a0c8a1..5459e8c 100644 --- a/src/main/java/com/hermanoid/nerd/NEI_NERD_Config.java +++ b/src/main/java/com/hermanoid/nerd/NEI_NERD_Config.java @@ -1,10 +1,14 @@ package com.hermanoid.nerd; +import com.hermanoid.nerd.info_extractors.GTDefaultRecipeInfoExtractor; + import codechicken.nei.api.API; import codechicken.nei.api.IConfigureNEI; -import com.hermanoid.nerd.info_extractors.GTDefaultRecipeInfoExtractor; +// This class is automatically discovered by a system in NotEnoughItems +@SuppressWarnings("unused") public class NEI_NERD_Config implements IConfigureNEI { + @Override public void loadConfig() { RecipeDumper recipeDumper = new RecipeDumper("tools.dump.recipes"); diff --git a/src/main/java/com/hermanoid/nerd/RecipeDumper.java b/src/main/java/com/hermanoid/nerd/RecipeDumper.java index 3530376..c1b9b1a 100644 --- a/src/main/java/com/hermanoid/nerd/RecipeDumper.java +++ b/src/main/java/com/hermanoid/nerd/RecipeDumper.java @@ -48,13 +48,12 @@ public RecipeDumper(String name) { public int totalQueries = -1; public int dumpedQueries = -1; private boolean dumpActive = false; - private Timer timer = new Timer(); + private final Timer timer = new Timer(); private final Multimap recipeInfoExtractors = HashMultimap.create(); - public void registerRecipeInfoExtractor(IRecipeInfoExtractor extractor){ - for(String id : extractor.getCompatibleHandlers()) - recipeInfoExtractors.put(id, extractor); + public void registerRecipeInfoExtractor(IRecipeInfoExtractor extractor) { + for (String id : extractor.getCompatibleHandlers()) recipeInfoExtractors.put(id, extractor); } @Override @@ -87,19 +86,20 @@ private JsonArray stacksToJsonArray(List stacks) { return arr; } - private static class QueryResult{ + private static class QueryResult { + public ItemStack targetStack; public List handlers; } - private QueryResult performQuery(ItemStack targetStack){ + private QueryResult performQuery(ItemStack targetStack) { QueryResult result = new QueryResult(); result.targetStack = targetStack; result.handlers = GuiCraftingRecipe.getCraftingHandlers("item", targetStack); return result; } - private JsonObject extractJsonRecipeData(QueryResult queryResult){ + private JsonObject extractJsonRecipeData(QueryResult queryResult) { // Gather item details (don't grab everything... you can dump items if you want more details) // These columns will be repeated many times in the output, so don't write more than needed. @@ -128,8 +128,8 @@ private JsonObject extractJsonRecipeData(QueryResult queryResult){ if (handler.getResultStack(recipeIndex) != null) { recipeDump.add("out_item", stackToDetailedJson(handler.getResultStack(recipeIndex).item)); } - if(recipeInfoExtractors.containsKey(handlerId)){ - for(IRecipeInfoExtractor extractor : recipeInfoExtractors.get(handlerId)){ + if (recipeInfoExtractors.containsKey(handlerId)) { + for (IRecipeInfoExtractor extractor : recipeInfoExtractors.get(handlerId)) { recipeDump.add(extractor.getSlug(), extractor.extractInfo(handler, recipeIndex)); } } @@ -145,12 +145,10 @@ private JsonObject extractJsonRecipeData(QueryResult queryResult){ public Stream getQueryDumps(List items) { // Parallelization doesn't help a *lot* but it is like a 2x speedup so I'll take it return items.parallelStream() - .map(this::performQuery) - .map(this::extractJsonRecipeData); + .map(this::performQuery) + .map(this::extractJsonRecipeData); } - - @Override public String renderName() { return translateN(name); @@ -174,17 +172,19 @@ public String modeButtonText() { @Override public Iterable dump(int mode) { // A little crunchy, I'll admit - throw new NotImplementedException("Recipe Dumper overrides the base DataDumper's dumping functionality in dumpTo(file)! dump() should never be called."); + throw new NotImplementedException( + "Recipe Dumper overrides the base DataDumper's dumping functionality in dumpTo(file)! dump() should never be called."); } @Override - public void dumpTo(File file) throws IOException { - if (getMode() != 1) { throw new RuntimeException("RecipeDumper received an unexpected mode! There should only be one mode: JSON");} + public void dumpTo(File file) { + if (getMode() != 1) { + throw new RuntimeException("RecipeDumper received an unexpected mode! There should only be one mode: JSON"); + } dumpJson(file); } - private void doDumpJson(File file){ - final String[] header = header(); + private void doDumpJson(File file) { final FileWriter writer; final JsonWriter jsonWriter; final Gson gson = new Gson(); @@ -198,13 +198,14 @@ private void doDumpJson(File file){ jsonWriter.beginObject(); jsonWriter.setIndent(" "); - jsonWriter.name("version").value(version); + jsonWriter.name("version") + .value(version); - jsonWriter.name("queries").beginArray(); + jsonWriter.name("queries") + .beginArray(); Object lock = new Object(); - getQueryDumps(items).forEach(obj -> - { - synchronized (lock){ + getQueryDumps(items).forEach(obj -> { + synchronized (lock) { gson.toJson(obj, jsonWriter); dumpedQueries++; } @@ -223,25 +224,21 @@ private void doDumpJson(File file){ } // If you don't wanna hold all this crap in memory at once, you're going to have to work for it. - public void dumpJson(File file) throws IOException { - if(dumpActive){ - NEIClientUtils.printChatMessage(new ChatComponentTranslation( - "nei.options.tools.dump.recipes.duplicate" - )); + public void dumpJson(File file) { + if (dumpActive) { + NEIClientUtils.printChatMessage(new ChatComponentTranslation("nei.options.tools.dump.recipes.duplicate")); return; } dumpActive = true; TimerTask progressTask = getProgressTask(); - Thread workerThread = new Thread(()-> { - try{ + Thread workerThread = new Thread(() -> { + try { doDumpJson(file); - }finally{ + } finally { dumpActive = false; progressTask.cancel(); } - NEIClientUtils.printChatMessage(new ChatComponentTranslation( - "nei.options.tools.dump.recipes.complete" - )); + NEIClientUtils.printChatMessage(new ChatComponentTranslation("nei.options.tools.dump.recipes.complete")); }); workerThread.start(); } @@ -249,14 +246,15 @@ public void dumpJson(File file) throws IOException { @NotNull private TimerTask getProgressTask() { TimerTask progressTask = new TimerTask() { + @Override public void run() { - NEIClientUtils.printChatMessage(new ChatComponentTranslation( - "nei.options.tools.dump.recipes.progress", - dumpedQueries, - totalQueries, - (float)dumpedQueries/totalQueries*100 - )); + NEIClientUtils.printChatMessage( + new ChatComponentTranslation( + "nei.options.tools.dump.recipes.progress", + dumpedQueries, + totalQueries, + (float) dumpedQueries / totalQueries * 100)); } }; timer.schedule(progressTask, 0, progressInterval); diff --git a/src/main/java/com/hermanoid/nerd/info_extractors/GTDefaultRecipeInfoExtractor.java b/src/main/java/com/hermanoid/nerd/info_extractors/GTDefaultRecipeInfoExtractor.java index 5133edf..2fe9263 100644 --- a/src/main/java/com/hermanoid/nerd/info_extractors/GTDefaultRecipeInfoExtractor.java +++ b/src/main/java/com/hermanoid/nerd/info_extractors/GTDefaultRecipeInfoExtractor.java @@ -2,7 +2,14 @@ import codechicken.nei.recipe.ICraftingHandler; import codechicken.nei.util.NBTJson; -import com.google.gson.*; +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializer; +import com.google.gson.JsonSerializationContext; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import gregtech.api.enums.Materials; import gregtech.api.util.GT_Recipe; @@ -19,39 +26,43 @@ import java.util.Set; public class GTDefaultRecipeInfoExtractor implements IRecipeInfoExtractor { + private static class GTRecipeExclusionStrategy implements ExclusionStrategy { - private final static Set badFields = new HashSet(Arrays.asList( - // Unnecessary/bulky info - "recipeCategory", - "stackTraces", - "owners", - // Rely on other dumping logic for inputs and outputs; - // auto-dumping Minecraft ItemStacks causes recursion into some nasty places - // I could make an adapter, but the generic NEI inputs/outputs logic covers these items no problemo - "mInputs", - "mOutputs", - // FluidStack things - // Icons are very large, not wise to have stored every time we dump an item - "stillIconResourceLocation", - "flowingIconResourceLocation", - "stillIcon", - "flowingIcon", - // There's a recursive fluid definition here - "registeredFluid", - // The automatic serializer doesn't like the rarity enum, I dunno why - "rarity", - // I don't think a fluid's corresponding block is useful, and it causes breaky recursion - "block", - // Some recipes are GT_Recipe_WithAlt, which have more evil ItemStacks we can't serialize. - "mOreDictAlt" - - )); - List badTypes = Arrays.asList( - GT_NEI_DefaultHandler.class, - ItemStack.class, - FluidStack.class, - Materials.class // Pops up in metadata (contains lots of images and such) - ); + + private final static Set badFields = new HashSet<>( + Arrays.asList( + // Unnecessary/bulky info + "recipeCategory", + "stackTraces", + "owners", + // Rely on other dumping logic for inputs and outputs; + // auto-dumping Minecraft ItemStacks causes recursion into some nasty places + // I could make an adapter, but the generic NEI inputs/outputs logic covers these items no problemo + "mInputs", + "mOutputs", + // FluidStack things + // Icons are very large, not wise to have stored every time we dump an item + "stillIconResourceLocation", + "flowingIconResourceLocation", + "stillIcon", + "flowingIcon", + // There's a recursive fluid definition here + "registeredFluid", + // The automatic serializer doesn't like the rarity enum, I dunno why + "rarity", + // I don't think a fluid's corresponding block is useful, and it causes breaky recursion + "block", + // Some recipes are GT_Recipe_WithAlt, which have more evil ItemStacks we can't serialize. + "mOreDictAlt" + + )); + List badTypes = Arrays + .asList(GT_NEI_DefaultHandler.class, ItemStack.class, FluidStack.class, Materials.class // Pops up in + // metadata + // (contains lots of + // images and such) + ); + @Override public boolean shouldSkipField(FieldAttributes f) { @@ -64,38 +75,46 @@ public boolean shouldSkipClass(Class clazz) { } } - private class FluidStackSerializer implements JsonSerializer{ - private static final Type fluidType = new TypeToken(){}.getType(); + private class FluidStackSerializer implements JsonSerializer { + + private static final Type fluidType = new TypeToken() {}.getType(); + @Override public JsonElement serialize(FluidStack src, Type typeOfSrc, JsonSerializationContext context) { // Fluids have some goofy unserializable things, similar to ItemStacks JsonObject root = new JsonObject(); root.addProperty("amount", src.amount); - if(src.tag != null){ + if (src.tag != null) { root.add("tag", NBTJson.toJsonObject(src.tag)); } // Some fluids (like water) are defined using anonymous types // I think that specifying the type for GT_Fluids would throw away information, // but for non-GT_Fluids, we'll need to un-anonymize this beeswax. - JsonObject fluid = null; - if(src.getFluid().getClass().equals(GT_Fluid.class)){ + JsonObject fluid; + if (src.getFluid() + .getClass() + .equals(GT_Fluid.class)) { fluid = (JsonObject) gson.toJsonTree(src.getFluid()); - }else{ + } else { fluid = (JsonObject) gson.toJsonTree(src.getFluid(), fluidType); } // Manually serialize rarity bc wierdness - fluid.addProperty("rarity", src.getFluid().getRarity().toString()); + fluid.addProperty( + "rarity", + src.getFluid() + .getRarity() + .toString()); // Slap on some info that's only available via method calls fluid.addProperty("id", src.getFluidID()); root.add("fluid", fluid); - return root; } } - private Gson gson; - public GTDefaultRecipeInfoExtractor(){ + private final Gson gson; + + public GTDefaultRecipeInfoExtractor() { gson = new GsonBuilder() // We might be only doing serializations, but GSON will still create // a type adapter and get stuck in nasty recursion/type access land @@ -109,10 +128,11 @@ public GTDefaultRecipeInfoExtractor(){ @Override public JsonElement extractInfo(ICraftingHandler handler, int recipeIndex) { GT_NEI_DefaultHandler gthandler = (GT_NEI_DefaultHandler) handler; - GT_Recipe recipe = gthandler.getCache().get(recipeIndex).mRecipe; - try{ + GT_Recipe recipe = gthandler.getCache() + .get(recipeIndex).mRecipe; + try { return gson.toJsonTree(recipe); - }catch(Exception e){ + } catch (Exception e) { System.out.println("O poop"); return null; } @@ -120,7 +140,7 @@ public JsonElement extractInfo(ICraftingHandler handler, int recipeIndex) { @Override public String[] getCompatibleHandlers() { - return new String[]{ "gregtech.nei.GT_NEI_DefaultHandler" }; + return new String[] { "gregtech.nei.GT_NEI_DefaultHandler" }; } @Override @@ -128,5 +148,4 @@ public String getSlug() { return "greg_data"; } - } diff --git a/src/main/java/com/hermanoid/nerd/info_extractors/IRecipeInfoExtractor.java b/src/main/java/com/hermanoid/nerd/info_extractors/IRecipeInfoExtractor.java index 39b41a5..10eee9f 100644 --- a/src/main/java/com/hermanoid/nerd/info_extractors/IRecipeInfoExtractor.java +++ b/src/main/java/com/hermanoid/nerd/info_extractors/IRecipeInfoExtractor.java @@ -1,12 +1,14 @@ package com.hermanoid.nerd.info_extractors; -import codechicken.nei.recipe.ICraftingHandler; import com.google.gson.JsonElement; +import codechicken.nei.recipe.ICraftingHandler; + public interface IRecipeInfoExtractor { - public JsonElement extractInfo(ICraftingHandler handler, int recipeIndex); - public String[] getCompatibleHandlers(); + JsonElement extractInfo(ICraftingHandler handler, int recipeIndex); + + String[] getCompatibleHandlers(); - public String getSlug(); + String getSlug(); }