From 7fe1f6254fd3e33d9a0367251f09c3089ec0a710 Mon Sep 17 00:00:00 2001 From: LLytho <29131229+LLytho@users.noreply.github.com> Date: Sun, 31 Jul 2022 16:20:42 +0200 Subject: [PATCH] Implement `forge:conditionals` type unify --- .../unified/recipe/RecipeTransformer.java | 80 ++++++++++++++----- .../unified/utils/JsonQuery.java | 64 +++++++-------- .../unified/utils/ReplacementMap.java | 3 + .../com/almostreliable/unified/TestUtils.java | 2 +- 4 files changed, 94 insertions(+), 55 deletions(-) diff --git a/Common/src/main/java/com/almostreliable/unified/recipe/RecipeTransformer.java b/Common/src/main/java/com/almostreliable/unified/recipe/RecipeTransformer.java index 0f4c8fc..030d190 100644 --- a/Common/src/main/java/com/almostreliable/unified/recipe/RecipeTransformer.java +++ b/Common/src/main/java/com/almostreliable/unified/recipe/RecipeTransformer.java @@ -5,15 +5,20 @@ import com.almostreliable.unified.config.DuplicationConfig; import com.almostreliable.unified.config.UnifyConfig; import com.almostreliable.unified.recipe.unifier.RecipeHandlerFactory; import com.almostreliable.unified.utils.JsonCompare; +import com.almostreliable.unified.utils.JsonQuery; import com.almostreliable.unified.utils.ReplacementMap; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import net.minecraft.resources.ResourceLocation; +import javax.annotation.Nullable; import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.stream.Collectors; public class RecipeTransformer { @@ -50,29 +55,67 @@ public class RecipeTransformer { Result result = new Result(); Map> byType = groupRecipesByType(recipes); - byType.forEach((type, recipeLinks) -> { - Set duplicates = new HashSet<>(recipeLinks.size()); - for (RecipeLink curRecipe : recipeLinks) { - unifyRecipe(curRecipe); - if (curRecipe.isUnified()) { - recipes.put(curRecipe.getId(), curRecipe.getUnified()); - if (handleDuplicate(curRecipe, recipeLinks)) { - duplicates.add(curRecipe.getDuplicateLink()); - } - } - result.add(curRecipe); - } - for (RecipeLink.DuplicateLink link : duplicates) { - link.getRecipes().forEach(recipe -> recipes.remove(recipe.getId())); - recipes.put(link.createNewRecipeId(), link.getMaster().getActual()); + ResourceLocation fcLocation = new ResourceLocation("forge:conditional"); + byType.forEach((type, recipeLinks) -> { + if (type.equals(fcLocation)) { + recipeLinks.forEach(recipeLink -> handleForgeConditionals(recipeLink).ifPresent(json -> recipes.put( + recipeLink.getId(), + json))); + } else { + transformRecipes(recipeLinks, recipes::put, recipes::remove); } }); + byType.values().stream().flatMap(Collection::stream).forEach(result::add); AlmostUnified.LOG.warn("Recipe counts afterwards: " + recipes.size()); return result; } + private Optional handleForgeConditionals(RecipeLink recipeLink) { + JsonObject copy = recipeLink.getOriginal().deepCopy(); + + if (copy.get("recipes") instanceof JsonArray recipes) { + for (JsonElement element : recipes) { + JsonQuery + .of(element, "recipe") + .asObject() + .map(jsonObject -> new RecipeLink(recipeLink.getId(), jsonObject)) + .ifPresent(temporaryLink -> { + unifyRecipe(temporaryLink); + if (temporaryLink.isUnified()) { + element.getAsJsonObject().add("recipe", temporaryLink.getUnified()); + } + }); + } + + if (!copy.equals(recipeLink.getOriginal())) { + recipeLink.setUnified(copy); + return Optional.of(copy); + } + } + + return Optional.empty(); + } + + private void transformRecipes(List recipeLinks, BiConsumer onAdd, Consumer onRemove) { + Set duplicates = new HashSet<>(recipeLinks.size()); + for (RecipeLink curRecipe : recipeLinks) { + unifyRecipe(curRecipe); + if (curRecipe.isUnified()) { + onAdd.accept(curRecipe.getId(), curRecipe.getUnified()); + if (handleDuplicate(curRecipe, recipeLinks)) { + duplicates.add(curRecipe.getDuplicateLink()); + } + } + } + + for (RecipeLink.DuplicateLink link : duplicates) { + link.getRecipes().forEach(recipe -> onRemove.accept(recipe.getId())); + onAdd.accept(link.createNewRecipeId(), link.getMaster().getActual()); + } + } + public Map> groupRecipesByType(Map recipes) { return recipes .entrySet() @@ -83,8 +126,7 @@ public class RecipeTransformer { } private boolean includeRecipe(ResourceLocation recipe, JsonElement json) { - return unifyConfig.includeRecipe(recipe) && json.isJsonObject() && - hasValidType(json.getAsJsonObject()); + return unifyConfig.includeRecipe(recipe) && json.isJsonObject() && hasValidType(json.getAsJsonObject()); } private boolean handleDuplicate(RecipeLink curRecipe, List recipes) { @@ -132,9 +174,7 @@ public class RecipeTransformer { recipe.setUnified(result); } } catch (Exception e) { - AlmostUnified.LOG.warn("Error unifying recipe '{}': {}", - recipe.getId(), - e.getMessage()); + AlmostUnified.LOG.warn("Error unifying recipe '{}': {}", recipe.getId(), e.getMessage()); e.printStackTrace(); } } diff --git a/Common/src/main/java/com/almostreliable/unified/utils/JsonQuery.java b/Common/src/main/java/com/almostreliable/unified/utils/JsonQuery.java index fef1243..505e40e 100644 --- a/Common/src/main/java/com/almostreliable/unified/utils/JsonQuery.java +++ b/Common/src/main/java/com/almostreliable/unified/utils/JsonQuery.java @@ -5,14 +5,21 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import org.apache.commons.lang3.StringUtils; +import javax.annotation.Nullable; +import java.util.Optional; + public class JsonQuery { - private final JsonElement element; + @Nullable private final JsonElement element; - JsonQuery(JsonElement element) { + JsonQuery(@Nullable JsonElement element) { this.element = element; } + JsonQuery() { + this.element = null; + } + public static JsonQuery of(JsonElement element) { return new JsonQuery(element); } @@ -31,56 +38,45 @@ public class JsonQuery { } public JsonQuery get(String identifier) { - if (!element.isJsonObject()) { - throw new IllegalArgumentException("Expected JsonObject, got " + element.getClass()); + if (element instanceof JsonObject json) { + JsonElement child = json.get(identifier); + if (child != null) { + return new JsonQuery(child); + } } - JsonElement child = element.getAsJsonObject().get(identifier); - if (child == null) { - return null; - } - - return new JsonQuery(child); + return new JsonQuery(); } public JsonQuery get(int index) { - if (!element.isJsonArray()) { - throw new IllegalArgumentException("Expected JsonArray, got " + element.getClass()); + if (element instanceof JsonArray json && 0 <= index && index < json.size()) { + JsonElement child = json.get(index); + if (child != null) { + return new JsonQuery(child); + } + } - JsonElement child = element.getAsJsonArray().get(index); - if (child == null) { - return null; - } - - return new JsonQuery(child); + return new JsonQuery(); } public JsonQuery get(String identifier, int index) { return get(identifier).get(index); } - public JsonObject asObject() { - return element.getAsJsonObject(); + public Optional asElement() { + return Optional.ofNullable(element); } - public JsonArray asArray() { - return element.getAsJsonArray(); + public Optional asObject() { + return asElement().filter(JsonObject.class::isInstance).map(JsonObject.class::cast); } - public String asString() { - return element.getAsString(); + public Optional asArray() { + return asElement().filter(JsonArray.class::isInstance).map(JsonArray.class::cast); } - public int asInt() { - return element.getAsInt(); - } - - public boolean asBoolean() { - return element.getAsBoolean(); - } - - public float asFloat() { - return element.getAsFloat(); + public Optional asString() { + return asElement().filter(JsonElement::isJsonPrimitive).map(JsonElement::getAsString); } } diff --git a/Common/src/main/java/com/almostreliable/unified/utils/ReplacementMap.java b/Common/src/main/java/com/almostreliable/unified/utils/ReplacementMap.java index bea9735..2af75b7 100644 --- a/Common/src/main/java/com/almostreliable/unified/utils/ReplacementMap.java +++ b/Common/src/main/java/com/almostreliable/unified/utils/ReplacementMap.java @@ -8,6 +8,7 @@ import net.minecraft.world.item.Item; import javax.annotation.Nullable; import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.function.Predicate; @@ -84,6 +85,8 @@ public class ReplacementMap { .getItems(tag) .stream() .filter(itemFilter) + // Helps us to get the clean stone variant first in case of a stone strata tag + .sorted(Comparator.comparingInt(value -> value.toString().length())) .toList(); for (String modPriority : unifyConfig.getModPriorities()) { diff --git a/Common/src/test/java/com/almostreliable/unified/TestUtils.java b/Common/src/test/java/com/almostreliable/unified/TestUtils.java index aa7f36a..c6d103f 100644 --- a/Common/src/test/java/com/almostreliable/unified/TestUtils.java +++ b/Common/src/test/java/com/almostreliable/unified/TestUtils.java @@ -80,7 +80,7 @@ public class TestUtils { ReplacementMap map = new ReplacementMap(TagMapTests.testTagMap(), DEFAULT_UNIFY_CONFIG); RecipeHandlerFactory factory = new RecipeHandlerFactory(); consumer.accept(factory); - return new RecipeTransformer(factory, map, DEFAULT_UNIFY_CONFIG, duplicationConfig); + return new RecipeTransformer(factory, map, DEFAULT_UNIFY_CONFIG, null); } public static JsonObject json(String json) {