forked from SteamWar/SteamWar
Add Region loading to DynamicRegionSystem
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package de.steamwar.bausystem.region;
|
package de.steamwar.bausystem.region;
|
||||||
|
|
||||||
|
import de.steamwar.bausystem.BauSystem;
|
||||||
import de.steamwar.core.Core;
|
import de.steamwar.core.Core;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@@ -27,10 +28,13 @@ import javax.annotation.CheckReturnValue;
|
|||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public interface RegionSystem {
|
public interface RegionSystem {
|
||||||
|
|
||||||
|
Logger LOGGER = BauSystem.getInstance().getLogger();
|
||||||
|
|
||||||
UUID GLOBAL_REGION_ID = new UUID(0, 0);
|
UUID GLOBAL_REGION_ID = new UUID(0, 0);
|
||||||
|
|
||||||
RegionSystem INSTANCE = init();
|
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;
|
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.BauSystem;
|
||||||
import de.steamwar.bausystem.region.dynamic.DynamicRegion;
|
import de.steamwar.bausystem.region.dynamic.DynamicRegion;
|
||||||
import de.steamwar.bausystem.region.dynamic.RegionConstructorData;
|
import de.steamwar.bausystem.region.dynamic.RegionConstructorData;
|
||||||
import de.steamwar.bausystem.region.dynamic.Tile;
|
import de.steamwar.bausystem.region.dynamic.Tile;
|
||||||
import de.steamwar.bausystem.region.dynamic.global.GlobalRegion;
|
import de.steamwar.bausystem.region.dynamic.global.GlobalRegion;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.*;
|
||||||
import java.io.InputStreamReader;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Parameter;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class DynamicRegionSystem implements RegionSystem {
|
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;
|
public static DynamicRegionSystem INSTANCE;
|
||||||
|
|
||||||
private static final Map<Long, Region> regionCache = new LinkedHashMap<>(16, 0.75f, true) {
|
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);
|
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
|
@Override
|
||||||
public void load() {
|
public void load() {
|
||||||
INSTANCE = this;
|
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()
|
.lines()
|
||||||
.map(s -> {
|
.map(s -> {
|
||||||
try {
|
try {
|
||||||
@@ -70,11 +91,114 @@ public class DynamicRegionSystem implements RegionSystem {
|
|||||||
throw new SecurityException(e.getMessage(), e);
|
throw new SecurityException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.forEach(clazz -> {
|
.filter(DynamicRegion.class::isAssignableFrom)
|
||||||
RegionConstructorData regionConstructorData = clazz.getAnnotation(RegionConstructorData.class);
|
.map(clazz -> (Class<? extends DynamicRegion>) clazz)
|
||||||
if (regionConstructorData == null) return;
|
.collect(Collectors.toUnmodifiableMap(Function.identity(), clazz -> clazz.getAnnotation(RegionConstructorData.class)));
|
||||||
// TODO: Save regionConstructorData together with clazz
|
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
|
@Override
|
||||||
|
|||||||
+1
@@ -31,6 +31,7 @@ import java.lang.annotation.Target;
|
|||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
public @interface RegionConstructorData {
|
public @interface RegionConstructorData {
|
||||||
|
String identifier();
|
||||||
int widthX();
|
int widthX();
|
||||||
int widthZ();
|
int widthZ();
|
||||||
boolean placeable() default true;
|
boolean placeable() default true;
|
||||||
|
|||||||
Reference in New Issue
Block a user