config
This commit is contained in:
@@ -18,7 +18,7 @@ loader_version_range=[2,)
|
|||||||
mod_id=l2core
|
mod_id=l2core
|
||||||
mod_name=L2Core
|
mod_name=L2Core
|
||||||
mod_license=LGPL-2.1
|
mod_license=LGPL-2.1
|
||||||
mod_version=3.0.2
|
mod_version=3.0.3-pre0
|
||||||
mod_group_id=dev.xkmc
|
mod_group_id=dev.xkmc
|
||||||
mod_authors=lcy0x1
|
mod_authors=lcy0x1
|
||||||
mod_description=Core Library mod for all L2 mods
|
mod_description=Core Library mod for all L2 mods
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package dev.xkmc.l2core.events;
|
package dev.xkmc.l2core.events;
|
||||||
|
|
||||||
import dev.xkmc.l2core.init.L2Core;
|
import dev.xkmc.l2core.init.L2Core;
|
||||||
|
import dev.xkmc.l2core.serial.config.PacketHandlerWithConfig;
|
||||||
import net.neoforged.bus.api.SubscribeEvent;
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
import net.neoforged.fml.common.EventBusSubscriber;
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
|
import net.neoforged.neoforge.event.AddReloadListenerEvent;
|
||||||
|
import net.neoforged.neoforge.event.OnDatapackSyncEvent;
|
||||||
import net.neoforged.neoforge.event.tick.ServerTickEvent;
|
import net.neoforged.neoforge.event.tick.ServerTickEvent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -12,6 +15,15 @@ import java.util.function.BooleanSupplier;
|
|||||||
@EventBusSubscriber(modid = L2Core.MODID, bus = EventBusSubscriber.Bus.GAME)
|
@EventBusSubscriber(modid = L2Core.MODID, bus = EventBusSubscriber.Bus.GAME)
|
||||||
public class SchedulerHandler {
|
public class SchedulerHandler {
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void addReloadListeners(AddReloadListenerEvent event) {
|
||||||
|
PacketHandlerWithConfig.addReloadListeners(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onDatapackSync(OnDatapackSyncEvent event) {
|
||||||
|
PacketHandlerWithConfig.onDatapackSync(event);
|
||||||
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void serverTick(ServerTickEvent.Post event) {
|
public static void serverTick(ServerTickEvent.Post event) {
|
||||||
|
|||||||
64
src/main/java/dev/xkmc/l2core/serial/config/BaseConfig.java
Normal file
64
src/main/java/dev/xkmc/l2core/serial/config/BaseConfig.java
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
import dev.xkmc.l2serial.serialization.marker.SerialClass;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@SerialClass
|
||||||
|
public class BaseConfig {
|
||||||
|
|
||||||
|
protected ResourceLocation id;
|
||||||
|
|
||||||
|
public ResourceLocation getID() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called by Config Merger after it's merged
|
||||||
|
*/
|
||||||
|
protected void postMerge() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, C> HashSet<T> collectSet(List<C> list, Function<C, Set<T>> getter) {
|
||||||
|
return list.stream().reduce(new HashSet<T>(), (a, c) -> {
|
||||||
|
a.addAll(getter.apply(c));
|
||||||
|
return a;
|
||||||
|
}, (a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, C> ArrayList<T> collectList(List<C> list, Function<C, List<T>> getter) {
|
||||||
|
return list.stream().reduce(new ArrayList<>(), (a, c) -> {
|
||||||
|
a.addAll(getter.apply(c));
|
||||||
|
return a;
|
||||||
|
}, (a, b) -> {
|
||||||
|
a.addAll(b);
|
||||||
|
return a;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, C, K> HashMap<K, T> collectMap(List<C> list, Function<C, Map<K, T>> getter, Supplier<T> gen, BiConsumer<T, T> merger) {
|
||||||
|
return list.stream().reduce(new HashMap<>(), (a, c) -> {
|
||||||
|
getter.apply(c).forEach((k, v) -> merger.accept(a.computeIfAbsent(k, e -> gen.get()), v));
|
||||||
|
return a;
|
||||||
|
}, (a, b) -> {
|
||||||
|
b.forEach((k, v) -> merger.accept(a.computeIfAbsent(k, e -> gen.get()), v));
|
||||||
|
return a;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <C, K, T> HashMap<K, T> overrideMap(List<C> list, Function<C, HashMap<K, T>> getter) {
|
||||||
|
HashMap<K, T> ans = new HashMap<>();
|
||||||
|
for (C c : list) {
|
||||||
|
ans.putAll(getter.apply(c));
|
||||||
|
}
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class BaseConfigType<T extends BaseConfig> {
|
||||||
|
|
||||||
|
public final Class<T> cls;
|
||||||
|
public final String id;
|
||||||
|
public final PacketHandlerWithConfig parent;
|
||||||
|
|
||||||
|
final Map<ResourceLocation, T> configs = new HashMap<>();
|
||||||
|
|
||||||
|
protected BaseConfigType(PacketHandlerWithConfig parent, String id, Class<T> cls) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.id = id;
|
||||||
|
this.cls = cls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void beforeReload() {
|
||||||
|
configs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterReload() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
public enum CollectType {
|
||||||
|
OVERWRITE, COLLECT, MAP_COLLECT, MAP_OVERWRITE
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.FIELD;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Target(FIELD)
|
||||||
|
public @interface ConfigCollect {
|
||||||
|
|
||||||
|
CollectType value();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import dev.xkmc.l2serial.serialization.codec.JsonCodec;
|
||||||
|
import net.minecraft.core.HolderLookup;
|
||||||
|
import net.minecraft.data.CachedOutput;
|
||||||
|
import net.minecraft.data.DataGenerator;
|
||||||
|
import net.minecraft.data.DataProvider;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public abstract class ConfigDataProvider implements DataProvider {
|
||||||
|
|
||||||
|
private final DataGenerator generator;
|
||||||
|
private final HolderLookup.Provider pvd;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
|
||||||
|
private final Map<String, ConfigEntry<?>> map = new HashMap<>();
|
||||||
|
|
||||||
|
public ConfigDataProvider(DataGenerator generator, HolderLookup.Provider pvd, String name) {
|
||||||
|
this.generator = generator;
|
||||||
|
this.pvd = pvd;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void add(Collector map);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<?> run(CachedOutput cache) {
|
||||||
|
Path folder = generator.getPackOutput().getOutputFolder();
|
||||||
|
add(new Collector(map));
|
||||||
|
List<CompletableFuture<?>> list = new ArrayList<>();
|
||||||
|
map.forEach((k, v) -> {
|
||||||
|
JsonElement elem = v.serialize(pvd);
|
||||||
|
if (elem != null) {
|
||||||
|
Path path = folder.resolve(k + ".json");
|
||||||
|
list.add(DataProvider.saveStable(cache, elem, path));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return CompletableFuture.allOf(list.toArray(CompletableFuture[]::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Collector(Map<String, ConfigEntry<?>> map) {
|
||||||
|
|
||||||
|
public <T extends BaseConfig> void add(ConfigTypeEntry<T> type, ResourceLocation id, T config) {
|
||||||
|
map.put(type.asPath(id), new ConfigEntry<>(type, id, config));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public record ConfigEntry<T extends BaseConfig>(ConfigTypeEntry<T> type, ResourceLocation id, T config) {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public JsonElement serialize(HolderLookup.Provider pvd) {
|
||||||
|
return new JsonCodec(pvd).toJson(config, type.cls());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface ConfigLoadOnStart {
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
import dev.xkmc.l2serial.serialization.type_cache.ClassCache;
|
||||||
|
import dev.xkmc.l2serial.serialization.type_cache.FieldCache;
|
||||||
|
import dev.xkmc.l2serial.serialization.type_cache.TypeInfo;
|
||||||
|
import dev.xkmc.l2serial.util.Wrappers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
public class ConfigMerger<T extends BaseConfig> {
|
||||||
|
|
||||||
|
private final ClassCache cache;
|
||||||
|
|
||||||
|
public ConfigMerger(Class<T> cls) {
|
||||||
|
this.cache = ClassCache.get(cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T merge(List<T> list) throws Exception {
|
||||||
|
T ans = (T) cache.create();
|
||||||
|
for (FieldCache field : cache.getFields()) {
|
||||||
|
ConfigCollect collect = field.getAnnotation(ConfigCollect.class);
|
||||||
|
if (collect == null) continue;
|
||||||
|
switch (collect.value()) {
|
||||||
|
case OVERWRITE -> {
|
||||||
|
int n = list.size();
|
||||||
|
if (n > 0) {
|
||||||
|
field.set(ans, field.get(list.get(n - 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case COLLECT -> {
|
||||||
|
TypeInfo info = field.toType();
|
||||||
|
assert Collection.class.isAssignableFrom(info.getAsClass());
|
||||||
|
Collection val = (Collection) info.toCache().create();
|
||||||
|
for (T t : list) {
|
||||||
|
val.addAll((Collection) field.get(t));
|
||||||
|
}
|
||||||
|
field.set(ans, val);
|
||||||
|
}
|
||||||
|
case MAP_COLLECT -> {
|
||||||
|
TypeInfo info = field.toType();
|
||||||
|
TypeInfo sub = info.getGenericType(1);
|
||||||
|
assert Map.class.isAssignableFrom(info.getAsClass());
|
||||||
|
Map val = (Map) info.toCache().create();
|
||||||
|
|
||||||
|
if (Collection.class.isAssignableFrom(sub.getAsClass())) {
|
||||||
|
for (T t : list) {
|
||||||
|
Map map = (Map) field.get(t);
|
||||||
|
for (Object e : map.entrySet()) {
|
||||||
|
Map.Entry ent = (Map.Entry) e;
|
||||||
|
Collection col;
|
||||||
|
if (val.containsKey(ent.getKey())) {
|
||||||
|
col = (Collection) val.get(ent.getKey());
|
||||||
|
} else {
|
||||||
|
val.put(ent.getKey(), col = (Collection) sub.toCache().create());
|
||||||
|
}
|
||||||
|
col.addAll((Collection) ent.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (Map.class.isAssignableFrom(sub.getAsClass())) {
|
||||||
|
for (T t : list) {
|
||||||
|
Map map = (Map) field.get(t);
|
||||||
|
for (Object e : map.entrySet()) {
|
||||||
|
Map.Entry ent = (Map.Entry) e;
|
||||||
|
Map col;
|
||||||
|
if (val.containsKey(ent.getKey())) {
|
||||||
|
col = (Map) val.get(ent.getKey());
|
||||||
|
} else {
|
||||||
|
val.put(ent.getKey(), col = (Map) sub.toCache().create());
|
||||||
|
}
|
||||||
|
col.putAll((Map) ent.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
field.set(ans, val);
|
||||||
|
}
|
||||||
|
case MAP_OVERWRITE -> {
|
||||||
|
TypeInfo info = field.toType();
|
||||||
|
assert Map.class.isAssignableFrom(info.getAsClass());
|
||||||
|
Map val = (Map) info.toCache().create();
|
||||||
|
for (T t : list) {
|
||||||
|
val.putAll((Map) field.get(t));
|
||||||
|
}
|
||||||
|
field.set(ans, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ans.postMerge();
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T apply(Collection<T> s) {
|
||||||
|
return Wrappers.get(() -> this.merge(new ArrayList<>(s)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
import dev.xkmc.l2serial.util.Wrappers;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public record ConfigTypeEntry<T extends BaseConfig>(PacketHandlerWithConfig channel, String name, Class<T> cls) {
|
||||||
|
|
||||||
|
public ConfigTypeEntry(PacketHandlerWithConfig channel, String name, Class<T> cls) {
|
||||||
|
this.channel = channel;
|
||||||
|
this.name = name;
|
||||||
|
this.cls = cls;
|
||||||
|
channel.addCachedConfig(name, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String asPath(ResourceLocation rl) {
|
||||||
|
return "data/" + rl.getNamespace() + "/" + channel.config_path + "/" + name + "/" + rl.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getMerged() {
|
||||||
|
MergedConfigType<T> type = Wrappers.cast(channel.types.get(name));
|
||||||
|
return type.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<T> getAll() {
|
||||||
|
MergedConfigType<T> type = Wrappers.cast(channel.types.get(name));
|
||||||
|
return type.configs.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getEntry(ResourceLocation id) {
|
||||||
|
MergedConfigType<T> type = Wrappers.cast(channel.types.get(name));
|
||||||
|
return type.configs.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
public class MergedConfigType<T extends BaseConfig> extends BaseConfigType<T> {
|
||||||
|
|
||||||
|
private T result;
|
||||||
|
|
||||||
|
MergedConfigType(PacketHandlerWithConfig parent, String id, Class<T> cls) {
|
||||||
|
super(parent, id, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
T load() {
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = new ConfigMerger<>(cls).apply(configs.values());
|
||||||
|
result.id = ResourceLocation.fromNamespaceAndPath(parent.modid, id);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterReload() {
|
||||||
|
result = null;
|
||||||
|
if (cls.isAnnotationPresent(ConfigLoadOnStart.class)) {
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import dev.xkmc.l2core.init.L2Core;
|
||||||
|
import dev.xkmc.l2serial.network.PacketHandler;
|
||||||
|
import dev.xkmc.l2serial.serialization.codec.JsonCodec;
|
||||||
|
import dev.xkmc.l2serial.util.Wrappers;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.packs.resources.ResourceManager;
|
||||||
|
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener;
|
||||||
|
import net.minecraft.util.profiling.ProfilerFiller;
|
||||||
|
import net.neoforged.fml.ModList;
|
||||||
|
import net.neoforged.neoforge.event.AddReloadListenerEvent;
|
||||||
|
import net.neoforged.neoforge.event.OnDatapackSyncEvent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class PacketHandlerWithConfig extends PacketHandler {
|
||||||
|
|
||||||
|
static final Map<String, PacketHandlerWithConfig> INTERNAL = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public static void onDatapackSync(OnDatapackSyncEvent event) {
|
||||||
|
for (PacketHandlerWithConfig handler : INTERNAL.values()) {
|
||||||
|
SyncPacket packet = new SyncPacket(handler.modid, handler.configs);
|
||||||
|
if (event.getPlayer() == null) L2Core.PACKET_HANDLER.toAllClient(packet);
|
||||||
|
else L2Core.PACKET_HANDLER.toClientPlayer(packet, event.getPlayer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addReloadListeners(AddReloadListenerEvent event) {
|
||||||
|
for (PacketHandlerWithConfig handler : INTERNAL.values()) {
|
||||||
|
if (handler.listener != null)
|
||||||
|
event.addListener(handler.listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<ConfigInstance> configs = new ArrayList<>();
|
||||||
|
|
||||||
|
public final String config_path;
|
||||||
|
|
||||||
|
final ConfigReloadListener listener;
|
||||||
|
final List<Runnable> listener_before = new ArrayList<>();
|
||||||
|
final List<Runnable> listener_after = new ArrayList<>();
|
||||||
|
final Map<String, BaseConfigType<?>> types = new HashMap<>();
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public PacketHandlerWithConfig(String id, int version, Function<PacketHandler, PacketConfiguration<?>>... values) {
|
||||||
|
super(id, version, values);
|
||||||
|
INTERNAL.put(id, this);
|
||||||
|
config_path = id + "_config";
|
||||||
|
listener = new ConfigReloadListener(config_path);
|
||||||
|
listener_before.add(configs::clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addBeforeReloadListener(Runnable runnable) {
|
||||||
|
listener_before.add(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAfterReloadListener(Runnable runnable) {
|
||||||
|
listener_after.add(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BaseConfig> void addConfig(String id, Class<T> loader) {
|
||||||
|
BaseConfigType<T> c = new BaseConfigType<>(this, id, loader);
|
||||||
|
types.put(id, c);
|
||||||
|
addBeforeReloadListener(c::beforeReload);
|
||||||
|
addAfterReloadListener(c::afterReload);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BaseConfig> void addCachedConfig(String id, Class<T> loader) {
|
||||||
|
MergedConfigType<T> c = new MergedConfigType<>(this, id, loader);
|
||||||
|
types.put(id, c);
|
||||||
|
addBeforeReloadListener(c::beforeReload);
|
||||||
|
addAfterReloadListener(c::afterReload);
|
||||||
|
}
|
||||||
|
|
||||||
|
<T extends BaseConfig> T getCachedConfig(String id) {
|
||||||
|
MergedConfigType<T> type = Wrappers.cast(types.get(id));
|
||||||
|
return type.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConfigReloadListener extends SimpleJsonResourceReloadListener {
|
||||||
|
|
||||||
|
public ConfigReloadListener(String path) {
|
||||||
|
super(new Gson(), path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void apply(Map<ResourceLocation, JsonElement> map, ResourceManager manager, ProfilerFiller filler) {
|
||||||
|
listener_before.forEach(Runnable::run);
|
||||||
|
map.forEach((k, v) -> {
|
||||||
|
if (!k.getNamespace().startsWith("_")) {
|
||||||
|
if (!ModList.get().isLoaded(k.getNamespace())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String id = k.getPath().split("/")[0];
|
||||||
|
if (types.containsKey(id)) {
|
||||||
|
String name = k.getPath().substring(id.length() + 1);
|
||||||
|
ResourceLocation nk = k.withPath(name);
|
||||||
|
addJson(types.get(id), nk, v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
listener_after.forEach(Runnable::run);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends BaseConfig> void addJson(BaseConfigType<T> type, ResourceLocation k, JsonElement v) {
|
||||||
|
T config = new JsonCodec(getRegistryLookup()).from(v, type.cls, null);
|
||||||
|
if (config != null) {
|
||||||
|
addConfig(type, k, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends BaseConfig> void addConfig(BaseConfigType<T> type, ResourceLocation k, T config) {
|
||||||
|
config.id = k;
|
||||||
|
type.configs.put(k, config);
|
||||||
|
configs.add(new ConfigInstance(type.id, k, config));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on client side only
|
||||||
|
*/
|
||||||
|
public void apply(ArrayList<ConfigInstance> list) {
|
||||||
|
listener_before.forEach(Runnable::run);
|
||||||
|
for (var e : list) {
|
||||||
|
addConfig(types.get(e.name), e.id(), Wrappers.cast(e.config));
|
||||||
|
}
|
||||||
|
listener_after.forEach(Runnable::run);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record ConfigInstance(String name, ResourceLocation id, BaseConfig config) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import dev.xkmc.l2serial.serialization.codec.JsonCodec;
|
||||||
|
import net.minecraft.core.HolderLookup;
|
||||||
|
import net.minecraft.data.CachedOutput;
|
||||||
|
import net.minecraft.data.DataGenerator;
|
||||||
|
import net.minecraft.data.DataProvider;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
public abstract class RecordDataProvider implements DataProvider {
|
||||||
|
private final DataGenerator generator;
|
||||||
|
private final HolderLookup.Provider pvd;
|
||||||
|
private final String name;
|
||||||
|
private final Map<String, Record> map = new HashMap<>();
|
||||||
|
|
||||||
|
public RecordDataProvider(DataGenerator generator, HolderLookup.Provider pvd, String name) {
|
||||||
|
this.generator = generator;
|
||||||
|
this.pvd = pvd;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void add(BiConsumer<String, Record> map);
|
||||||
|
|
||||||
|
public CompletableFuture<?> run(CachedOutput cache) {
|
||||||
|
Path folder = this.generator.getPackOutput().getOutputFolder();
|
||||||
|
this.add(this.map::put);
|
||||||
|
List<CompletableFuture<?>> list = new ArrayList<>();
|
||||||
|
this.map.forEach((k, v) -> {
|
||||||
|
JsonElement elem = new JsonCodec(pvd).toJson(v);
|
||||||
|
if (elem != null) {
|
||||||
|
Path path = folder.resolve("data/" + k + ".json");
|
||||||
|
list.add(DataProvider.saveStable(cache, elem, path));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
return CompletableFuture.allOf(list.toArray(CompletableFuture[]::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
19
src/main/java/dev/xkmc/l2core/serial/config/SyncPacket.java
Normal file
19
src/main/java/dev/xkmc/l2core/serial/config/SyncPacket.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
import dev.xkmc.l2serial.network.SerialPacketBase;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public record SyncPacket(String id, ArrayList<PacketHandlerWithConfig.ConfigInstance> map)
|
||||||
|
implements SerialPacketBase<SyncPacket> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(Player player) {
|
||||||
|
if (map != null) {
|
||||||
|
var handler = PacketHandlerWithConfig.INTERNAL.get(id);
|
||||||
|
handler.listener.apply(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
|
||||||
|
package dev.xkmc.l2core.serial.config;
|
||||||
|
|
||||||
|
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||||
|
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
Reference in New Issue
Block a user