Add DynamicRegionRepository#loadRegions

Add DynamicRegionRepository#loadRegionData
Add DynamicRegionRepository#saveRegion
Add DynamicRegionRepository#deleteRegion
This commit is contained in:
2026-03-01 15:04:35 +01:00
parent 327ea9351a
commit 5795476e23
7 changed files with 350 additions and 125 deletions
@@ -19,38 +19,23 @@
package de.steamwar.bausystem.region;
import com.google.gson.JsonIOException;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.region.dynamic.DynamicRegion;
import de.steamwar.bausystem.region.dynamic.DynamicRegionRepository;
import de.steamwar.bausystem.region.dynamic.RegionConstructorData;
import de.steamwar.bausystem.region.dynamic.Tile;
import de.steamwar.bausystem.region.dynamic.global.GlobalRegion;
import lombok.NonNull;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DynamicRegionSystem implements RegionSystem {
public static final File REGION_DATA_FOLDER = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "steamwar_regions");
public static final String META_FILE_NAME = "meta.json";
static {
REGION_DATA_FOLDER.mkdirs();
}
public static DynamicRegionSystem INSTANCE;
private static final Map<Long, Region> regionCache = new LinkedHashMap<>(16, 0.75f, true) {
@@ -74,8 +59,8 @@ public class DynamicRegionSystem implements RegionSystem {
regionTypeMap.getOrDefault(region.getType(), Collections.emptySet()).remove(region);
}
private static Map<Class<? extends DynamicRegion>, RegionConstructorData> constructorDataMap = new HashMap<>();
private static Map<String, Class<? extends DynamicRegion>> identifierDataMap = new HashMap<>();
public static Map<Class<? extends DynamicRegion>, RegionConstructorData> constructorDataMap = new HashMap<>();
public static Map<String, Class<? extends DynamicRegion>> identifierDataMap = new HashMap<>();
@Override
public void load() {
@@ -98,107 +83,7 @@ public class DynamicRegionSystem implements RegionSystem {
.stream()
.collect(Collectors.toUnmodifiableMap(entry -> entry.getValue().identifier(), Map.Entry::getKey));
// Loading all saved regions from the files
File[] regions = REGION_DATA_FOLDER.listFiles();
for (File region : regions) {
UUID regionUUID;
try {
regionUUID = UUID.fromString(region.getName());
} catch (IllegalArgumentException e) {
LOGGER.log(Level.WARNING, "Failed to resolve region id: " + region.getName());
continue;
}
if (regionUUID == GLOBAL_REGION_ID) {
continue;
}
File metaFile = new File(region, META_FILE_NAME);
if (!metaFile.exists() || !metaFile.isFile()) {
LOGGER.log(Level.WARNING, "Failed to resolve " + region.getName());
continue;
}
JsonObject metaData;
try {
metaData = JsonParser.parseReader(new FileReader(metaFile)).getAsJsonObject();
} catch (JsonIOException e) {
LOGGER.log(Level.SEVERE, "Failed to read region metadata file (unknown)");
continue;
} catch (JsonSyntaxException | IllegalStateException e) {
LOGGER.log(Level.SEVERE, "Failed to read region metadata file (invalid json)");
continue;
} catch (FileNotFoundException e) {
LOGGER.log(Level.SEVERE, "Failed to read region metadata file (not found)");
continue;
}
int tileX;
int tileZ;
String identifier;
try {
tileX = metaData.getAsJsonPrimitive("tile_x").getAsInt();
tileZ = metaData.getAsJsonPrimitive("tile_z").getAsInt();
identifier = metaData.getAsJsonPrimitive("region_identifier").getAsString();
} catch (ClassCastException | NumberFormatException e) {
LOGGER.log(Level.SEVERE, "Failed to read region metadata file (invalid json)");
continue;
}
Class<? extends DynamicRegion> regionClass = identifierDataMap.get(identifier);
if (regionClass == null) {
LOGGER.log(Level.SEVERE, "Failed to read region metadata file (region no longer exists)");
continue;
}
RegionConstructorData constructorData = constructorDataMap.get(regionClass);
Optional<Tile> optionalTile = Tile.fromTile(tileX, tileZ);
if (optionalTile.isEmpty()) {
LOGGER.log(Level.SEVERE, "Failed to read region metadata file (tile is no longer in bounds)");
continue;
}
Tile tile = optionalTile.get();
Location minTileLocation = tile.getMinLocation();
Constructor<? extends DynamicRegion> regionConstructor;
try {
regionConstructor = regionClass.getConstructor(UUID.class, int.class, int.class);
} catch (NoSuchMethodException e) {
LOGGER.log(Level.SEVERE, "Failed to read region metadata file (region constructor not found)");
continue;
}
Class<? extends RegionData> regionDataClass = constructorData.regionDataClass();
Constructor<? extends RegionData> regionDataConstructor = null;
for (Constructor<?> constructor : regionDataClass.getConstructors()) {
if (constructor.getParameters().length != 1) continue;
Parameter parameter = constructor.getParameters()[0];
if (parameter.getType().isAssignableFrom(regionClass)) {
regionDataConstructor = (Constructor<? extends RegionData>) constructor;
break;
}
}
if (regionDataConstructor == null) {
LOGGER.log(Level.SEVERE, "Failed to read region metadata file (region data constructor not found)");
continue;
}
DynamicRegion dynamicRegion;
try {
dynamicRegion = regionConstructor.newInstance(regionUUID, minTileLocation.getBlockX(), minTileLocation.getBlockZ());
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
LOGGER.log(Level.SEVERE, "Failed to read region metadata file (invalid data)");
continue;
}
RegionData regionData;
try {
regionData = regionDataConstructor.newInstance(dynamicRegion);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
LOGGER.log(Level.SEVERE, "Failed to instantiate region data (invalid data)");
continue;
}
dynamicRegion.setRegionData(regionData);
}
DynamicRegionRepository.loadRegions();
}
@Override