From 15901d9e79cdd610b163a6963ce68ebdf98dd031 Mon Sep 17 00:00:00 2001 From: lcy0x1 Date: Wed, 28 Aug 2024 13:02:43 +0800 Subject: [PATCH] varitem --- gradle.properties | 2 +- .../l2core/init/reg/varitem/VarBuilder.java | 20 +++ .../l2core/init/reg/varitem/VarEntry.java | 18 +++ .../l2core/init/reg/varitem/VarHolder.java | 43 +++++ .../l2core/init/reg/varitem/VarItemInit.java | 149 ++++++++++++++++++ .../l2core/init/reg/varitem/package-info.java | 8 + 6 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 src/main/java/dev/xkmc/l2core/init/reg/varitem/VarBuilder.java create mode 100644 src/main/java/dev/xkmc/l2core/init/reg/varitem/VarEntry.java create mode 100644 src/main/java/dev/xkmc/l2core/init/reg/varitem/VarHolder.java create mode 100644 src/main/java/dev/xkmc/l2core/init/reg/varitem/VarItemInit.java create mode 100644 src/main/java/dev/xkmc/l2core/init/reg/varitem/package-info.java diff --git a/gradle.properties b/gradle.properties index cfc921b..bc7e40c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,7 +18,7 @@ loader_version_range=[2,) mod_id=l2core mod_name=L2Core mod_license=LGPL-2.1 -mod_version=3.0.7+25 +mod_version=3.0.7+31 mod_group_id=dev.xkmc mod_authors=lcy0x1 mod_description=Core Library mod for all L2 mods diff --git a/src/main/java/dev/xkmc/l2core/init/reg/varitem/VarBuilder.java b/src/main/java/dev/xkmc/l2core/init/reg/varitem/VarBuilder.java new file mode 100644 index 0000000..0eaaad5 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/init/reg/varitem/VarBuilder.java @@ -0,0 +1,20 @@ +package dev.xkmc.l2core.init.reg.varitem; + +import com.tterrag.registrate.builders.ItemBuilder; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; + +public interface VarBuilder { + + static VarBuilder nop() { + return (r, b) -> b; + } + + ItemBuilder buildImpl(ResourceLocation id, ItemBuilder builder); + + default ItemBuilder build(ResourceLocation id, ItemBuilder builder) { + buildImpl(id, builder); + return builder; + } + +} diff --git a/src/main/java/dev/xkmc/l2core/init/reg/varitem/VarEntry.java b/src/main/java/dev/xkmc/l2core/init/reg/varitem/VarEntry.java new file mode 100644 index 0000000..328816d --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/init/reg/varitem/VarEntry.java @@ -0,0 +1,18 @@ +package dev.xkmc.l2core.init.reg.varitem; + +import com.tterrag.registrate.util.entry.ItemEntry; +import net.minecraft.world.item.Item; +import org.jetbrains.annotations.Contract; +import org.openjdk.nashorn.internal.objects.annotations.Getter; + +import javax.annotation.Nullable; + +public interface VarEntry { + + String id(); + + void callback(ItemEntry item); + + VarBuilder builder(); + +} diff --git a/src/main/java/dev/xkmc/l2core/init/reg/varitem/VarHolder.java b/src/main/java/dev/xkmc/l2core/init/reg/varitem/VarHolder.java new file mode 100644 index 0000000..e2e0344 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/init/reg/varitem/VarHolder.java @@ -0,0 +1,43 @@ +package dev.xkmc.l2core.init.reg.varitem; + +import com.tterrag.registrate.util.entry.ItemEntry; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.ItemLike; +import org.jetbrains.annotations.Nullable; + +public class VarHolder implements VarEntry, ItemLike { + + private final String str; + private final VarBuilder builder; + private ItemEntry item; + + public VarHolder(String str, VarBuilder builder) { + this.str = str; + this.builder = builder; + } + + public ItemEntry item() { + return item; + } + + @Override + public Item asItem() { + return item.asItem(); + } + + @Override + public String id() { + return str; + } + + @Override + public void callback(ItemEntry item) { + this.item = item; + } + + @Override + public VarBuilder builder() { + return builder; + } + +} diff --git a/src/main/java/dev/xkmc/l2core/init/reg/varitem/VarItemInit.java b/src/main/java/dev/xkmc/l2core/init/reg/varitem/VarItemInit.java new file mode 100644 index 0000000..e3d039c --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/init/reg/varitem/VarItemInit.java @@ -0,0 +1,149 @@ +package dev.xkmc.l2core.init.reg.varitem; + +import com.google.gson.*; +import com.mojang.datafixers.util.Pair; +import com.tterrag.registrate.util.OneTimeEventReceiver; +import com.tterrag.registrate.util.entry.ItemEntry; +import dev.xkmc.l2core.init.L2Core; +import dev.xkmc.l2core.init.reg.registrate.L2Registrate; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.neoforged.bus.api.EventPriority; +import net.neoforged.fml.loading.FMLPaths; +import net.neoforged.neoforge.registries.RegisterEvent; +import org.apache.logging.log4j.Level; + +import java.io.FileReader; +import java.io.FileWriter; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; + +public class VarItemInit { + + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().setLenient().create(); + private static final ConcurrentMap> VAR_ITEM_TYPE = new ConcurrentHashMap<>(); + private static final String PATH = "varitem_config"; + + public static VarItemInit setup(L2Registrate reg, ResourceLocation id, Function func, VarBuilder builder) { + var ans = new VarItemInit<>(reg, id, func, builder); + VAR_ITEM_TYPE.put(id, ans); + return ans; + } + + private final L2Registrate reg; + private final ResourceLocation id; + private final Function func; + private final VarBuilder builder; + private final Map> defaults = new LinkedHashMap<>(); + private final List registered = new ArrayList<>(); + private final Map> results = new ConcurrentHashMap<>(); + + private VarItemInit(L2Registrate reg, ResourceLocation id, Function func, VarBuilder builder) { + this.reg = reg; + this.id = id; + this.func = func; + this.builder = builder; + reg.getModEventBus().addListener( EventPriority.HIGH, RegisterEvent.class, this::init); + } + + public synchronized void add(List defaults) { + defaults.forEach(e -> this.defaults.put(e, new SimpleVarEntry<>(e))); + } + + public synchronized VarHolder add(VarHolder e) { + defaults.put(e.id(), e); + return e; + } + + private synchronized void init(RegisterEvent event) { + if (event.getRegistry() != BuiltInRegistries.ITEM) return; + load(); + for (var e : registered) { + var rl = ResourceLocation.fromNamespaceAndPath(reg.getModid(), e); + if (BuiltInRegistries.ITEM.containsKey(rl)) { + L2Core.LOGGER.error("Item ID {} is already used. Registration of varitem type {} skips this ID.", rl, id); + continue; + } + L2Core.LOGGER.debug("Registering {} for varitem type {}", rl, id); + var def = defaults.get(e); + var b = builder.build(rl, reg.item(e, p -> func.apply(rl))); + if (def != null) b = def.builder().build(rl, b); + var item = b.register(); + results.put(e, item); + if (def != null) def.callback(item); + } + } + + private void load() { + String path = PATH + "/" + id.getNamespace() + "-" + id.getPath() + ".json"; + var file = FMLPaths.CONFIGDIR.get().resolve(path).toFile(); + registered.clear(); + try { + var parent = file.getParentFile(); + if (parent.exists()) { + if (!parent.isDirectory()) { + if (parent.delete()) { + parent.mkdirs(); + } + } + } else parent.mkdirs(); + if (!file.exists()) file.createNewFile(); + var reader = new FileReader(file); + var json = JsonParser.parseReader(reader); + reader.close(); + var result = parseFile(json); + List ans = result.getSecond(); + if (result.getFirst()) { + if (ans.isEmpty()) ans = new ArrayList<>(defaults.keySet()); + var writer = new FileWriter(file); + var out = new JsonArray(); + for (var e : ans) { + out.add(e); + } + writer.write(GSON.toJson(out)); + writer.close(); + } + registered.addAll(ans); + } catch (Exception e) { + L2Core.LOGGER.error("Failed to parse config file for varitem type {}. Use defaults instead", id); + L2Core.LOGGER.throwing(Level.ERROR, e); + registered.addAll(defaults.keySet()); + } + } + + private Pair> parseFile(JsonElement elem) { + if (!elem.isJsonArray()) return Pair.of(true, List.of()); + List ans = new ArrayList<>(); + boolean err = false; + for (var e : elem.getAsJsonArray()) { + var rl = e.getAsString(); + if (ResourceLocation.isValidPath(rl)) ans.add(rl); + else { + L2Core.LOGGER.error("Item ID {} for varitem type {} is invalid. Skipped", rl, id); + err = true; + } + } + return Pair.of(err, ans); + } + + private record SimpleVarEntry(String id) implements VarEntry { + + @Override + public void callback(ItemEntry item) { + + } + + @Override + public VarBuilder builder() { + return VarBuilder.nop(); + } + + } + +} diff --git a/src/main/java/dev/xkmc/l2core/init/reg/varitem/package-info.java b/src/main/java/dev/xkmc/l2core/init/reg/varitem/package-info.java new file mode 100644 index 0000000..86bc7be --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/init/reg/varitem/package-info.java @@ -0,0 +1,8 @@ +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault + +package dev.xkmc.l2core.init.reg.varitem; + +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file