@@ -19,6 +19,7 @@
|
||||
|
||||
package de.steamwar.bausystem.region;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.core.Core;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.Location;
|
||||
@@ -27,10 +28,13 @@ import javax.annotation.CheckReturnValue;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface RegionSystem {
|
||||
|
||||
Logger LOGGER = BauSystem.getInstance().getLogger();
|
||||
|
||||
UUID GLOBAL_REGION_ID = new UUID(0, 0);
|
||||
|
||||
RegionSystem INSTANCE = init();
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"TNT": "DENY",
|
||||
"FREEZE": "INACTIVE"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"region_identifier": "SpawnRegion",
|
||||
"tile_x": 0,
|
||||
"tile_z": 0
|
||||
}
|
||||
+132
-8
@@ -19,21 +19,38 @@
|
||||
|
||||
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.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.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
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) {
|
||||
@@ -57,11 +74,15 @@ 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<>();
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
INSTANCE = this;
|
||||
|
||||
new BufferedReader(new InputStreamReader(BauSystem.getInstance().getClass().getResourceAsStream("/META-INF/annotations/de.steamwar.bausystem.region.dynamic.RegionConstructorData")))
|
||||
// Loading all Region Constructor Data that are defined inside the Code
|
||||
constructorDataMap = new BufferedReader(new InputStreamReader(BauSystem.getInstance().getClass().getResourceAsStream("/META-INF/annotations/de.steamwar.bausystem.region.dynamic.RegionConstructorData")))
|
||||
.lines()
|
||||
.map(s -> {
|
||||
try {
|
||||
@@ -70,11 +91,114 @@ public class DynamicRegionSystem implements RegionSystem {
|
||||
throw new SecurityException(e.getMessage(), e);
|
||||
}
|
||||
})
|
||||
.forEach(clazz -> {
|
||||
RegionConstructorData regionConstructorData = clazz.getAnnotation(RegionConstructorData.class);
|
||||
if (regionConstructorData == null) return;
|
||||
// TODO: Save regionConstructorData together with clazz
|
||||
});
|
||||
.filter(DynamicRegion.class::isAssignableFrom)
|
||||
.map(clazz -> (Class<? extends DynamicRegion>) clazz)
|
||||
.collect(Collectors.toUnmodifiableMap(Function.identity(), clazz -> clazz.getAnnotation(RegionConstructorData.class)));
|
||||
identifierDataMap = constructorDataMap.entrySet()
|
||||
.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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
@@ -31,6 +31,7 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface RegionConstructorData {
|
||||
String identifier();
|
||||
int widthX();
|
||||
int widthZ();
|
||||
boolean placeable() default true;
|
||||
|
||||
Reference in New Issue
Block a user