package com.atsuishio.superbwarfare.data; import com.atsuishio.superbwarfare.Mod; import com.google.gson.Gson; import net.minecraft.server.packs.resources.ResourceManager; import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.neoforge.event.OnDatapackSyncEvent; import net.neoforged.neoforge.event.server.ServerStartedEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.InputStreamReader; import java.util.*; import java.util.function.Consumer; import java.util.stream.Collectors; @EventBusSubscriber(modid = Mod.MODID) public class DataLoader { private static final HashMap> loadedData = new HashMap<>(); private record GeneralData( Class type, DataMap proxyMap, HashMap data, @Nullable Consumer> onReload ) { } public static DataMap createData(String name, Class clazz) { return createData(name, clazz, null); } @SuppressWarnings("unchecked") public static DataMap createData(String name, Class clazz, @Nullable Consumer> onReload) { if (loadedData.containsKey(name)) { return (DataMap) loadedData.get(name).proxyMap; } else { var proxyMap = new DataMap(name); loadedData.put(name, new GeneralData<>(clazz, proxyMap, new HashMap<>(), onReload)); return proxyMap; } } private static void reloadAllData(ResourceManager manager) { loadedData.forEach((name, value) -> { var map = value.data; map.clear(); for (var entry : manager.listResources(name, file -> file.getPath().endsWith(".json")).entrySet()) { var attribute = entry.getValue(); try { Gson gson = new Gson(); var data = (IDBasedData) gson.fromJson(new InputStreamReader(attribute.open()), value.type); String id; if (!data.getId().isEmpty()) { id = data.getId(); } else { var path = entry.getKey().getPath(); id = Mod.MODID + ":" + path.substring(name.length() + 1, path.length() - name.length() - 1); Mod.LOGGER.warn("{} ID for {} is empty, try using {} as id", name, id, path); } map.put(id, data); } catch (Exception e) { Mod.LOGGER.error(e.getMessage()); } } if (value.onReload != null) { value.onReload.accept(map); } }); } @SubscribeEvent(priority = EventPriority.HIGH) public static void serverStarted(ServerStartedEvent event) { reloadAllData(event.getServer().getResourceManager()); } @SubscribeEvent(priority = EventPriority.HIGH) public static void onDataPackSync(OnDatapackSyncEvent event) { reloadAllData(event.getPlayerList().getServer().getResourceManager()); } // read-only custom data map public static class DataMap extends HashMap { private final String name; private DataMap(String name) { this.name = name; } @Override public int size() { if (!loadedData.containsKey(name)) return 0; return loadedData.get(name).data.size(); } @Override public boolean isEmpty() { if (!loadedData.containsKey(name)) return true; return loadedData.get(name).data.isEmpty(); } @Override @SuppressWarnings("unchecked") public T get(Object key) { if (!loadedData.containsKey(name)) return null; return (T) loadedData.get(name).data.get(key); } @Override public T getOrDefault(Object key, T defaultValue) { var value = get(key); return value == null ? defaultValue : value; } @Override public boolean containsKey(Object key) { if (!loadedData.containsKey(name)) return false; return loadedData.get(name).data.containsKey(key); } @Override public T put(String key, T value) { throw new UnsupportedOperationException(); } @Override public void putAll(Map m) { throw new UnsupportedOperationException(); } @Override public T remove(Object key) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); } @Override public boolean containsValue(Object value) { if (!loadedData.containsKey(name)) return false; return loadedData.get(name).data.containsValue(value); } @Override public @NotNull Set keySet() { if (!loadedData.containsKey(name)) return Set.of(); return loadedData.get(name).data.keySet(); } @Override @SuppressWarnings("unchecked") public @NotNull Collection values() { if (!loadedData.containsKey(name)) return Set.of(); return loadedData.get(name).data.values().stream().map(v -> (T) v).toList(); } @Override @SuppressWarnings("unchecked") public @NotNull Set> entrySet() { if (!loadedData.containsKey(name)) return Set.of(); return loadedData.get(name).data.entrySet().stream() .map(e -> new AbstractMap.SimpleImmutableEntry<>(e.getKey(), (T) e.getValue())) .collect(Collectors.toCollection(HashSet::new)); } } }