From dc7613dd4669393a313b270b55cfaaa3ff8c94a3 Mon Sep 17 00:00:00 2001 From: Uko Kokņevičs Date: Sat, 13 Jan 2024 01:12:12 +0100 Subject: Toposort recipes so it's actually usably fast --- .../lv/enes/mc/eris_alchemy/utils/ConsList.java | 103 +++++++++++++++++++++ .../mc/eris_alchemy/utils/IngredientProvider.java | 44 +++++++++ .../lv/enes/mc/eris_alchemy/utils/ItemUtils.java | 5 + .../eris_alchemy/utils/OptionalDoubleSummer.java | 47 ++++++++++ .../java/lv/enes/mc/eris_alchemy/utils/Ref.java | 14 +++ 5 files changed, 213 insertions(+) create mode 100644 src/main/java/lv/enes/mc/eris_alchemy/utils/ConsList.java create mode 100644 src/main/java/lv/enes/mc/eris_alchemy/utils/IngredientProvider.java create mode 100644 src/main/java/lv/enes/mc/eris_alchemy/utils/OptionalDoubleSummer.java create mode 100644 src/main/java/lv/enes/mc/eris_alchemy/utils/Ref.java (limited to 'src/main/java/lv/enes/mc/eris_alchemy/utils') diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/ConsList.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/ConsList.java new file mode 100644 index 0000000..bbab8a6 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/ConsList.java @@ -0,0 +1,103 @@ +package lv.enes.mc.eris_alchemy.utils; + +import jakarta.annotation.Nonnull; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Supplier; +import java.util.stream.Stream; + +public sealed abstract class ConsList { + public static ConsList cons(E car, ConsList cdr) { + return new Cons<>(car, cdr); + } + + public static ConsList nil() { + return Nil.of(); + } + + @Nonnull + public abstract Optional car(); + + @Nonnull + public abstract ConsList cdr(); + + public boolean contains(E elem) { + return stream().anyMatch(x -> Objects.equals(x, elem)); + } + + public Stream stream() { + var car = car(); + if (car.isEmpty()) { + return Stream.empty(); + } + + return Stream.>>of( + () -> Stream.of(car.get()), + () -> cdr().stream() + ) + .flatMap(Supplier::get); + } + + @Override + public String toString() { + if (car().isEmpty()) { + return "[]"; + } + + var sb = new StringBuilder("["); + sb.append(car().get()); + stream().skip(1) + .forEach(x -> { + sb.append(" -> "); + sb.append(x); + }); + sb.append("]"); + return sb.toString(); + } + + private static final class Cons extends ConsList { + private final E car; + private final ConsList cdr; + + public Cons(E car, ConsList cdr) { + this.car = car; + this.cdr = cdr; + } + + @Nonnull + @Override + public Optional car() { + return Optional.of(car); + } + + @Nonnull + @Override + public ConsList cdr() { + return cdr; + } + } + + private static final class Nil extends ConsList { + private static final Nil INSTANCE = new Nil<>(); + + @SuppressWarnings("unchecked") + public static Nil of() { + return (Nil)INSTANCE; + } + + private Nil(){} + + @Nonnull + @Override + public Optional car() { + return Optional.empty(); + } + + @Nonnull + @Override + public ConsList cdr() { + return Nil.of(); + } + } +} diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/IngredientProvider.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/IngredientProvider.java new file mode 100644 index 0000000..e859114 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/IngredientProvider.java @@ -0,0 +1,44 @@ +package lv.enes.mc.eris_alchemy.utils; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.ShapedRecipe; + +import java.lang.reflect.Type; +import java.util.function.Supplier; + +public class IngredientProvider implements JsonDeserializer> { + public static Supplier deserialize(JsonElement el) { + if (el.isJsonObject()) { + return () -> Ingredient.of(ShapedRecipe.itemStackFromJson(el.getAsJsonObject())); + } else if (el.isJsonPrimitive() && el.getAsJsonPrimitive().isString()) { + return deserialize(el.getAsString().strip()); + } else { + throw new JsonParseException("Every ingredient should be an object or a string"); + } + } + + public static Supplier deserialize(String str) { + if (str.startsWith("#")) { + var tag = TagKey.create(Registries.ITEM, new ResourceLocation(str.substring(1).strip())); + return () -> Ingredient.of(tag); + } else { + return () -> Ingredient.of(ItemUtils.get(new ResourceLocation(str))); + } + } + + @Override + public Supplier deserialize( + JsonElement el, + Type t, + JsonDeserializationContext c + ) { + return IngredientProvider.deserialize(el); + } +} diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/ItemUtils.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/ItemUtils.java index 4414d06..7ac7358 100644 --- a/src/main/java/lv/enes/mc/eris_alchemy/utils/ItemUtils.java +++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/ItemUtils.java @@ -3,10 +3,15 @@ package lv.enes.mc.eris_alchemy.utils; import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ItemLike; public final class ItemUtils { + public static Item get(ResourceLocation id) { + return BuiltInRegistries.ITEM.get(id); + } + public static ResourceLocation getId(Holder holder) { return getId(holder.value()); } diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/OptionalDoubleSummer.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/OptionalDoubleSummer.java new file mode 100644 index 0000000..04b6ca8 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/OptionalDoubleSummer.java @@ -0,0 +1,47 @@ +package lv.enes.mc.eris_alchemy.utils; + +import java.util.OptionalDouble; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collector; + +public class OptionalDoubleSummer implements Collector, OptionalDouble> { + @Override + public Supplier> supplier() { + return () -> new Ref<>(OptionalDouble.of(0)); + } + + @Override + public BiConsumer, OptionalDouble> accumulator() { + return (ref, od) -> { + if (ref.getValue().isPresent()) { + if (od.isPresent()) { + ref.setValue(OptionalDouble.of(ref.getValue().getAsDouble() + od.getAsDouble())); + } else { + ref.setValue(OptionalDouble.empty()); + } + } + }; + } + + @Override + public BinaryOperator> combiner() { + return (ref1, ref2) -> { + accumulator().accept(ref1, ref2.getValue()); + return ref1; + }; + } + + @Override + public Function, OptionalDouble> finisher() { + return Ref::getValue; + } + + @Override + public Set characteristics() { + return Set.of(Characteristics.UNORDERED); + } +} diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/Ref.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/Ref.java new file mode 100644 index 0000000..dc2624a --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/Ref.java @@ -0,0 +1,14 @@ +package lv.enes.mc.eris_alchemy.utils; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class Ref { + private T value; + + public Ref(T value) { + this.value = value; + } +} -- cgit v1.2.3