重写数据包加载

This commit is contained in:
Light_Quanta 2025-07-01 03:37:45 +08:00
parent afdb50c1d7
commit cbc71d062a
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
11 changed files with 218 additions and 134 deletions

View file

@ -12,6 +12,7 @@ import com.atsuishio.superbwarfare.component.ModDataComponents;
import com.atsuishio.superbwarfare.config.ClientConfig; import com.atsuishio.superbwarfare.config.ClientConfig;
import com.atsuishio.superbwarfare.config.CommonConfig; import com.atsuishio.superbwarfare.config.CommonConfig;
import com.atsuishio.superbwarfare.config.ServerConfig; import com.atsuishio.superbwarfare.config.ServerConfig;
import com.atsuishio.superbwarfare.data.CustomData;
import com.atsuishio.superbwarfare.init.*; import com.atsuishio.superbwarfare.init.*;
import com.atsuishio.superbwarfare.network.NetworkRegistry; import com.atsuishio.superbwarfare.network.NetworkRegistry;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -86,6 +87,8 @@ public class Mod {
} }
NeoForge.EVENT_BUS.register(this); NeoForge.EVENT_BUS.register(this);
CustomData.load();
} }
public static ResourceLocation loc(String path) { public static ResourceLocation loc(String path) {

View file

@ -0,0 +1,19 @@
package com.atsuishio.superbwarfare.data;
import com.atsuishio.superbwarfare.data.gun.DefaultGunData;
import com.atsuishio.superbwarfare.data.gun.GunData;
import com.atsuishio.superbwarfare.data.gun.ProjectileInfo;
import com.atsuishio.superbwarfare.data.vehicle.DefaultVehicleData;
import com.atsuishio.superbwarfare.data.vehicle.VehicleData;
import java.util.HashMap;
public class CustomData {
public static final HashMap<String, ProjectileInfo> LAUNCHABLE_ENTITY = DataLoader.createData("launchable", ProjectileInfo.class);
public static final HashMap<String, DefaultVehicleData> VEHICLE = DataLoader.createData("vehicles", DefaultVehicleData.class, map -> VehicleData.dataCache.invalidateAll());
public static final HashMap<String, DefaultGunData> GUN = DataLoader.createData("guns", DefaultGunData.class, map -> GunData.dataCache.invalidateAll());
// 务必在Mod加载时调用该方法确保上面的静态数据加载成功
public static void load() {
}
}

View file

@ -0,0 +1,161 @@
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.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
@EventBusSubscriber(modid = Mod.MODID)
public class DataLoader {
private static final HashMap<String, GeneralData<?>> loadedData = new HashMap<>();
private record GeneralData<T extends IDBasedData>(
Class<?> type, DataMap<T> proxyMap,
HashMap<String, Object> data,
@Nullable Consumer<Map<String, Object>> onReload
) {
}
public static <T extends IDBasedData> HashMap<String, T> createData(String name, Class<T> clazz) {
return createData(name, clazz, null);
}
@SuppressWarnings("unchecked")
public static <T extends IDBasedData> DataMap<T> createData(String name, Class<T> clazz, @Nullable Consumer<Map<String, Object>> onReload) {
if (loadedData.containsKey(name)) {
return (DataMap<T>) loadedData.get(name).proxyMap;
} else {
var proxyMap = new DataMap<T>(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<T extends IDBasedData> extends HashMap<String, T> {
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<? extends String, ? extends T> 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<String> keySet() {
if (!loadedData.containsKey(name)) return Set.of();
return loadedData.get(name).data.keySet();
}
}
}

View file

@ -0,0 +1,5 @@
package com.atsuishio.superbwarfare.data;
public interface IDBasedData {
String getId();
}

View file

@ -1,15 +1,21 @@
package com.atsuishio.superbwarfare.data.gun; package com.atsuishio.superbwarfare.data.gun;
import com.atsuishio.superbwarfare.annotation.ServerOnly; import com.atsuishio.superbwarfare.annotation.ServerOnly;
import com.atsuishio.superbwarfare.data.IDBasedData;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
public class DefaultGunData { public class DefaultGunData implements IDBasedData {
@SerializedName("ID") @SerializedName("ID")
public String id = ""; public String id = "";
@Override
public String getId() {
return this.id;
}
@SerializedName("RecoilX") @SerializedName("RecoilX")
public double recoilX; public double recoilX;
@SerializedName("RecoilY") @SerializedName("RecoilY")

View file

@ -1,13 +1,19 @@
package com.atsuishio.superbwarfare.data.gun; package com.atsuishio.superbwarfare.data.gun;
import com.atsuishio.superbwarfare.data.IDBasedData;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
public class ProjectileInfo { public class ProjectileInfo implements IDBasedData {
@SerializedName("Type") @SerializedName("Type")
public String type = "superbwarfare:projectile"; public String type = "superbwarfare:projectile";
@SerializedName("Data") @SerializedName("Data")
public JsonObject data; public JsonObject data;
@Override
public String getId() {
return type;
}
} }

View file

@ -1,51 +1,24 @@
package com.atsuishio.superbwarfare.data.launchable; package com.atsuishio.superbwarfare.data.launchable;
import com.atsuishio.superbwarfare.Mod; import com.atsuishio.superbwarfare.data.CustomData;
import com.atsuishio.superbwarfare.data.gun.ProjectileInfo; import com.atsuishio.superbwarfare.data.gun.ProjectileInfo;
import com.google.gson.Gson;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraft.nbt.*; import net.minecraft.nbt.*;
import net.minecraft.server.packs.resources.ResourceManager;
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.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
@EventBusSubscriber(modid = Mod.MODID)
public class LaunchableEntityTool { public class LaunchableEntityTool {
public static HashMap<String, JsonObject> launchableEntitiesData = new HashMap<>(); public static Map<String, ProjectileInfo> launchableEntitiesData = CustomData.LAUNCHABLE_ENTITY;
/**
* 初始化数据从data中读取数据json文件
*/
public static void initJsonData(ResourceManager manager) {
launchableEntitiesData.clear();
for (var entry : manager.listResources("launchable", file -> file.getPath().endsWith(".json")).entrySet()) {
var attribute = entry.getValue();
try {
Gson gson = new Gson();
var data = gson.fromJson(new InputStreamReader(attribute.open()), JsonObject.class);
launchableEntitiesData.put(data.get("Type").getAsString(), data.get("Data").getAsJsonObject());
} catch (Exception e) {
Mod.LOGGER.error(e.getMessage());
}
}
}
public static @Nullable CompoundTag getModifiedTag(ProjectileInfo projectileInfo, ShootData data) { public static @Nullable CompoundTag getModifiedTag(ProjectileInfo projectileInfo, ShootData data) {
JsonObject launchableData; JsonObject launchableData;
if (projectileInfo.data != null) { if (projectileInfo.data != null) {
launchableData = projectileInfo.data; launchableData = projectileInfo.data;
} else if (launchableEntitiesData.containsKey(projectileInfo.type)) { } else if (launchableEntitiesData.containsKey(projectileInfo.type)) {
launchableData = launchableEntitiesData.get(projectileInfo.type); launchableData = launchableEntitiesData.get(projectileInfo.type).data;
} else { } else {
return null; return null;
} }
@ -104,14 +77,4 @@ public class LaunchableEntityTool {
default -> StringTag.valueOf(value); default -> StringTag.valueOf(value);
}; };
} }
@SubscribeEvent
public static void serverStarted(ServerStartedEvent event) {
initJsonData(event.getServer().getResourceManager());
}
@SubscribeEvent
public static void onDataPackSync(OnDatapackSyncEvent event) {
initJsonData(event.getPlayerList().getServer().getResourceManager());
}
} }

View file

@ -2,15 +2,21 @@ package com.atsuishio.superbwarfare.data.vehicle;
import com.atsuishio.superbwarfare.annotation.ServerOnly; import com.atsuishio.superbwarfare.annotation.ServerOnly;
import com.atsuishio.superbwarfare.config.server.VehicleConfig; import com.atsuishio.superbwarfare.config.server.VehicleConfig;
import com.atsuishio.superbwarfare.data.IDBasedData;
import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModify; import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModify;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import java.util.List; import java.util.List;
public class DefaultVehicleData { public class DefaultVehicleData implements IDBasedData {
@SerializedName("ID") @SerializedName("ID")
public String id = ""; public String id = "";
@Override
public String getId() {
return this.id;
}
@SerializedName("MaxHealth") @SerializedName("MaxHealth")
public float maxHealth = 50; public float maxHealth = 50;

View file

@ -1,55 +1,21 @@
package com.atsuishio.superbwarfare.data.vehicle; package com.atsuishio.superbwarfare.data.vehicle;
import com.atsuishio.superbwarfare.Mod; import com.atsuishio.superbwarfare.Mod;
import com.atsuishio.superbwarfare.data.CustomData;
import com.atsuishio.superbwarfare.network.message.receive.VehiclesDataMessage; import com.atsuishio.superbwarfare.network.message.receive.VehiclesDataMessage;
import com.google.gson.Gson;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.packs.resources.ResourceManager;
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.OnDatapackSyncEvent; import net.neoforged.neoforge.event.OnDatapackSyncEvent;
import net.neoforged.neoforge.event.entity.player.PlayerEvent; import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.event.server.ServerStartedEvent;
import net.neoforged.neoforge.network.PacketDistributor; import net.neoforged.neoforge.network.PacketDistributor;
import java.io.InputStreamReader;
import java.util.HashMap; import java.util.HashMap;
@EventBusSubscriber(modid = Mod.MODID) @EventBusSubscriber(modid = Mod.MODID)
public class VehicleDataTool { public class VehicleDataTool {
public static HashMap<String, DefaultVehicleData> vehicleData = new HashMap<>();
public static final String VEHICLE_DATA_FOLDER = "vehicles"; public static HashMap<String, DefaultVehicleData> vehicleData = CustomData.VEHICLE;
public static void initJsonData(ResourceManager manager) {
vehicleData.clear();
VehicleData.dataCache.invalidateAll();
for (var entry : manager.listResources(VEHICLE_DATA_FOLDER, file -> file.getPath().endsWith(".json")).entrySet()) {
var attribute = entry.getValue();
try {
Gson gson = new Gson();
var data = gson.fromJson(new InputStreamReader(attribute.open()), DefaultVehicleData.class);
String id;
if (!data.id.isEmpty()) {
id = data.id;
} else {
var path = entry.getKey().getPath();
id = Mod.MODID + ":" + path.substring(VEHICLE_DATA_FOLDER.length() + 1, path.length() - VEHICLE_DATA_FOLDER.length() - 1);
Mod.LOGGER.warn("Vehicle ID for {} is empty, try using {} as id", id, path);
data.id = id;
}
if (!vehicleData.containsKey(id)) {
vehicleData.put(id, data);
}
} catch (Exception e) {
Mod.LOGGER.error(e.getMessage());
}
}
}
@SubscribeEvent @SubscribeEvent
public static void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) { public static void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) {
@ -63,15 +29,9 @@ public class VehicleDataTool {
} }
} }
@SubscribeEvent
public static void serverStarted(ServerStartedEvent event) {
initJsonData(event.getServer().getResourceManager());
}
@SubscribeEvent @SubscribeEvent
public static void onDataPackSync(OnDatapackSyncEvent event) { public static void onDataPackSync(OnDatapackSyncEvent event) {
var server = event.getPlayerList().getServer(); var server = event.getPlayerList().getServer();
initJsonData(server.getResourceManager());
var message = VehiclesDataMessage.create(); var message = VehiclesDataMessage.create();
for (var player : event.getRelevantPlayers().toList()) { for (var player : event.getRelevantPlayers().toList()) {

View file

@ -654,7 +654,7 @@ public abstract class GunItem extends Item implements CustomRendererItem, GeoIte
} else if (LaunchableEntityTool.launchableEntitiesData.containsKey(projectileType)) { } else if (LaunchableEntityTool.launchableEntitiesData.containsKey(projectileType)) {
var newInfo = new ProjectileInfo(); var newInfo = new ProjectileInfo();
newInfo.data = LaunchableEntityTool.launchableEntitiesData.get(projectileType); newInfo.data = LaunchableEntityTool.launchableEntitiesData.get(projectileType).data;
newInfo.type = projectileType; newInfo.type = projectileType;
var tag = LaunchableEntityTool.getModifiedTag( var tag = LaunchableEntityTool.getModifiedTag(

View file

@ -1,64 +1,25 @@
package com.atsuishio.superbwarfare.tools; package com.atsuishio.superbwarfare.tools;
import com.atsuishio.superbwarfare.Mod; import com.atsuishio.superbwarfare.Mod;
import com.atsuishio.superbwarfare.data.CustomData;
import com.atsuishio.superbwarfare.data.gun.DefaultGunData; import com.atsuishio.superbwarfare.data.gun.DefaultGunData;
import com.atsuishio.superbwarfare.data.gun.GunData;
import com.atsuishio.superbwarfare.network.message.receive.GunsDataMessage; import com.atsuishio.superbwarfare.network.message.receive.GunsDataMessage;
import com.google.gson.Gson;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.packs.resources.ResourceManager;
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.OnDatapackSyncEvent; import net.neoforged.neoforge.event.OnDatapackSyncEvent;
import net.neoforged.neoforge.event.entity.player.PlayerEvent; import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.event.server.ServerStartedEvent;
import net.neoforged.neoforge.network.PacketDistributor; import net.neoforged.neoforge.network.PacketDistributor;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.InputStreamReader;
import java.util.HashMap; import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
@EventBusSubscriber(modid = Mod.MODID) @EventBusSubscriber(modid = Mod.MODID)
public class GunsTool { public class GunsTool {
public static HashMap<String, DefaultGunData> gunsData = new HashMap<>(); public static HashMap<String, DefaultGunData> gunsData = CustomData.GUN;
public static final String GUN_DATA_FOLDER = "guns";
/**
* 初始化数据从data中读取数据json文件
*/
public static void initJsonData(ResourceManager manager) {
gunsData.clear();
GunData.dataCache.invalidateAll();
for (var entry : manager.listResources(GUN_DATA_FOLDER, file -> file.getPath().endsWith(".json")).entrySet()) {
var attribute = entry.getValue();
try {
Gson gson = new Gson();
var data = gson.fromJson(new InputStreamReader(attribute.open()), DefaultGunData.class);
String id;
if (!data.id.trim().isEmpty()) {
id = data.id;
} else {
var path = entry.getKey().getPath();
id = Mod.MODID + ":" + path.substring(GUN_DATA_FOLDER.length() + 1, path.length() - GUN_DATA_FOLDER.length() - 1);
Mod.LOGGER.warn("Gun ID for {} is empty, try using {} as id", path, id);
data.id = id;
}
if (!gunsData.containsKey(id)) {
gunsData.put(id, data);
}
} catch (Exception e) {
Mod.LOGGER.error(e.getMessage());
}
}
}
@SubscribeEvent @SubscribeEvent
public static void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) { public static void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) {
@ -72,15 +33,9 @@ public class GunsTool {
} }
} }
@SubscribeEvent
public static void serverStarted(ServerStartedEvent event) {
initJsonData(event.getServer().getResourceManager());
}
@SubscribeEvent @SubscribeEvent
public static void onDataPackSync(OnDatapackSyncEvent event) { public static void onDataPackSync(OnDatapackSyncEvent event) {
var server = event.getPlayerList().getServer(); var server = event.getPlayerList().getServer();
initJsonData(server.getResourceManager());
var message = GunsDataMessage.create(); var message = GunsDataMessage.create();
for (var player : event.getRelevantPlayers().toList()) { for (var player : event.getRelevantPlayers().toList()) {