diff options
| author | 2024-01-13 01:12:12 +0100 | |
|---|---|---|
| committer | 2024-01-13 01:12:12 +0100 | |
| commit | dc7613dd4669393a313b270b55cfaaa3ff8c94a3 (patch) | |
| tree | 657c3aa3c185cd9c8820ff4a5a32336f5cf421c6 /src/main/java/lv/enes/mc/eris_alchemy/recipe/SimplifiedRecipe.java | |
| parent | Bump versions (diff) | |
| download | mc-eris-alchemy-dc7613dd4669393a313b270b55cfaaa3ff8c94a3.tar.gz mc-eris-alchemy-dc7613dd4669393a313b270b55cfaaa3ff8c94a3.tar.xz mc-eris-alchemy-dc7613dd4669393a313b270b55cfaaa3ff8c94a3.zip | |
Toposort recipes so it's actually usably fast
Diffstat (limited to 'src/main/java/lv/enes/mc/eris_alchemy/recipe/SimplifiedRecipe.java')
| -rw-r--r-- | src/main/java/lv/enes/mc/eris_alchemy/recipe/SimplifiedRecipe.java | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/recipe/SimplifiedRecipe.java b/src/main/java/lv/enes/mc/eris_alchemy/recipe/SimplifiedRecipe.java new file mode 100644 index 0000000..469ed52 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/recipe/SimplifiedRecipe.java | |||
| @@ -0,0 +1,123 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.recipe; | ||
| 2 | |||
| 3 | import com.google.gson.JsonDeserializationContext; | ||
| 4 | import com.google.gson.JsonDeserializer; | ||
| 5 | import com.google.gson.JsonElement; | ||
| 6 | import com.google.gson.JsonParseException; | ||
| 7 | import jakarta.annotation.Nonnull; | ||
| 8 | import lv.enes.mc.eris_alchemy.utils.IngredientProvider; | ||
| 9 | import lv.enes.mc.eris_alchemy.utils.ItemUtils; | ||
| 10 | import lv.enes.mc.eris_alchemy.utils.RecipeUtils; | ||
| 11 | import net.minecraft.core.RegistryAccess; | ||
| 12 | import net.minecraft.core.registries.BuiltInRegistries; | ||
| 13 | import net.minecraft.resources.ResourceLocation; | ||
| 14 | import net.minecraft.world.item.ItemStack; | ||
| 15 | import net.minecraft.world.item.crafting.Ingredient; | ||
| 16 | import net.minecraft.world.item.crafting.Recipe; | ||
| 17 | import net.minecraft.world.item.crafting.ShapedRecipe; | ||
| 18 | |||
| 19 | import java.lang.reflect.Type; | ||
| 20 | import java.util.Arrays; | ||
| 21 | import java.util.Collection; | ||
| 22 | import java.util.List; | ||
| 23 | import java.util.Objects; | ||
| 24 | import java.util.function.Supplier; | ||
| 25 | import java.util.stream.Stream; | ||
| 26 | |||
| 27 | public record SimplifiedRecipe(ItemStack output, List<ItemStack> remainder, List<Supplier<Ingredient>> input) { | ||
| 28 | public SimplifiedRecipe(Recipe<?> recipe, RegistryAccess registryAccess) { | ||
| 29 | this( | ||
| 30 | RecipeUtils.getOutput(recipe, registryAccess), | ||
| 31 | List.of(), // TODO: | ||
| 32 | RecipeUtils.getIngredients(recipe) | ||
| 33 | .stream() | ||
| 34 | .filter(ingredient -> !ingredient.isEmpty()) | ||
| 35 | .map(x -> (Supplier<Ingredient>) () -> x) | ||
| 36 | .toList() | ||
| 37 | ); | ||
| 38 | } | ||
| 39 | |||
| 40 | public Stream<ResourceLocation> dependencies() { | ||
| 41 | return Stream.concat( | ||
| 42 | input.stream().map(Supplier::get).map(Ingredient::getItems).flatMap(Arrays::stream), | ||
| 43 | remainder.stream() | ||
| 44 | ).map(ItemUtils::getId); | ||
| 45 | } | ||
| 46 | |||
| 47 | public boolean hasDuplication() { | ||
| 48 | var outputId = ItemUtils.getId(output); | ||
| 49 | var outputsInRemainder = remainder.stream() | ||
| 50 | .map(ItemUtils::getId) | ||
| 51 | .anyMatch(id -> Objects.equals(id, outputId)); | ||
| 52 | if (outputsInRemainder) { | ||
| 53 | return true; | ||
| 54 | } | ||
| 55 | |||
| 56 | return input.stream().anyMatch(ingredient -> ingredient.get().test(output)); | ||
| 57 | } | ||
| 58 | |||
| 59 | public boolean isAllowed(BannedRecipe ban) { | ||
| 60 | if (!ban.output().get().test(output())) { | ||
| 61 | return true; | ||
| 62 | } | ||
| 63 | |||
| 64 | return dependencies().noneMatch(dep -> ban.input().get().test(ItemUtils.get(dep).getDefaultInstance())); | ||
| 65 | } | ||
| 66 | |||
| 67 | public boolean isAllowed(Collection<BannedRecipe> bans) { | ||
| 68 | return bans.stream().allMatch(this::isAllowed); | ||
| 69 | } | ||
| 70 | |||
| 71 | public static class Deserializer implements JsonDeserializer<SimplifiedRecipe> { | ||
| 72 | @Nonnull | ||
| 73 | @Override | ||
| 74 | public SimplifiedRecipe deserialize( | ||
| 75 | JsonElement jsonElement, | ||
| 76 | Type type, | ||
| 77 | JsonDeserializationContext jsonDeserializationContext | ||
| 78 | ) throws JsonParseException { | ||
| 79 | if (!jsonElement.isJsonObject()) { | ||
| 80 | throw new JsonParseException("Recipe must be an object"); | ||
| 81 | } | ||
| 82 | var obj = jsonElement.getAsJsonObject(); | ||
| 83 | |||
| 84 | if (obj.get("output") == null || obj.get("input") == null) { | ||
| 85 | throw new JsonParseException("Recipe must have 'output' and 'input' fields"); | ||
| 86 | } | ||
| 87 | |||
| 88 | var output = parseOutputOrRemainder(obj.get("output")); | ||
| 89 | var remainder = parseRemainders(obj.get("remainder")); | ||
| 90 | var input = parseInputs(obj.get("input")); | ||
| 91 | return new SimplifiedRecipe(output, remainder, input); | ||
| 92 | } | ||
| 93 | |||
| 94 | private List<Supplier<Ingredient>> parseInputs(JsonElement el) { | ||
| 95 | if (el.isJsonArray()) { | ||
| 96 | return el.getAsJsonArray().asList().stream().map(IngredientProvider::deserialize).toList(); | ||
| 97 | } | ||
| 98 | |||
| 99 | return List.of(IngredientProvider.deserialize(el)); | ||
| 100 | } | ||
| 101 | |||
| 102 | private ItemStack parseOutputOrRemainder(JsonElement el) { | ||
| 103 | if (el.isJsonObject()) { | ||
| 104 | return ShapedRecipe.itemStackFromJson(el.getAsJsonObject()); | ||
| 105 | } else if (el.isJsonPrimitive() && el.getAsJsonPrimitive().isString()) { | ||
| 106 | var id = new ResourceLocation(el.getAsString()); | ||
| 107 | return BuiltInRegistries.ITEM.get(id).getDefaultInstance(); | ||
| 108 | } else { | ||
| 109 | throw new JsonParseException("Recipe's output or remainder must be an object or a string"); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | private List<ItemStack> parseRemainders(JsonElement el) { | ||
| 114 | if (el == null) { | ||
| 115 | return List.of(); | ||
| 116 | } else if (el.isJsonArray()) { | ||
| 117 | return el.getAsJsonArray().asList().stream().map(this::parseOutputOrRemainder).toList(); | ||
| 118 | } else { | ||
| 119 | return List.of(parseOutputOrRemainder(el)); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | } | ||
| 123 | } | ||