250 lines
8.9 KiB
Java
250 lines
8.9 KiB
Java
package dev.loki.config;
|
||
|
||
import org.bukkit.Bukkit;
|
||
import org.bukkit.Location;
|
||
import org.bukkit.World;
|
||
import org.bukkit.configuration.file.FileConfiguration;
|
||
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
|
||
public class LocationsConfig {
|
||
private final FileConfiguration config;
|
||
|
||
public LocationsConfig(FileConfiguration config) {
|
||
this.config = config;
|
||
setDefaults();
|
||
}
|
||
|
||
private void setDefaults() {
|
||
if (!config.contains("lobby")) {
|
||
config.set("lobby.world", "world");
|
||
config.set("lobby.x", 0.0);
|
||
config.set("lobby.y", 100.0);
|
||
config.set("lobby.z", 0.0);
|
||
config.set("lobby.yaw", 0.0);
|
||
config.set("lobby.pitch", 0.0);
|
||
}
|
||
// Безопасная проверка: contains() может вернуть true для пустого списка,
|
||
// поэтому также проверяем что getList() не null
|
||
if (!config.contains("generators") || config.getList("generators") == null) {
|
||
config.set("generators", new ArrayList<>());
|
||
}
|
||
if (!config.contains("hooks") || config.getList("hooks") == null) {
|
||
config.set("hooks", new ArrayList<>());
|
||
}
|
||
if (!config.contains("windows") || config.getList("windows") == null) {
|
||
config.set("windows", new ArrayList<>());
|
||
}
|
||
if (!config.contains("chests") || config.getList("chests") == null) {
|
||
config.set("chests", new ArrayList<>());
|
||
}
|
||
if (!config.contains("exitgates") || config.getList("exitgates") == null) {
|
||
config.set("exitgates", new ArrayList<>());
|
||
}
|
||
if (!config.contains("killer-spawn") || config.getList("killer-spawn") == null) {
|
||
config.set("killer-spawn", new ArrayList<>());
|
||
}
|
||
if (!config.contains("survivor-spawns") || config.getList("survivor-spawns") == null) {
|
||
config.set("survivor-spawns", new ArrayList<>());
|
||
}
|
||
}
|
||
|
||
public Location getLobby() {
|
||
World world = Bukkit.getWorld(config.getString("lobby.world", "world"));
|
||
if (world == null) return null;
|
||
return new Location(
|
||
world,
|
||
config.getDouble("lobby.x", 0.0),
|
||
config.getDouble("lobby.y", 100.0),
|
||
config.getDouble("lobby.z", 0.0),
|
||
(float) config.getDouble("lobby.yaw", 0.0),
|
||
(float) config.getDouble("lobby.pitch", 0.0)
|
||
);
|
||
}
|
||
|
||
public void setLobby(Location loc) {
|
||
config.set("lobby.world", loc.getWorld().getName());
|
||
config.set("lobby.x", loc.getX());
|
||
config.set("lobby.y", loc.getY());
|
||
config.set("lobby.z", loc.getZ());
|
||
config.set("lobby.yaw", loc.getYaw());
|
||
config.set("lobby.pitch", loc.getPitch());
|
||
}
|
||
|
||
public List<Location> getGenerators() {
|
||
return loadLocationList("generators");
|
||
}
|
||
|
||
public List<Location> getHooks() {
|
||
return loadLocationList("hooks");
|
||
}
|
||
|
||
public List<Location> getWindows() {
|
||
return loadLocationList("windows");
|
||
}
|
||
|
||
public List<Location> getChests() {
|
||
return loadLocationList("chests");
|
||
}
|
||
|
||
public List<Location> getTotems() {
|
||
return loadLocationList("totems");
|
||
}
|
||
|
||
// getExitGates() — определён в addLocation/setGate блоке
|
||
|
||
public List<Location> getKillerSpawns() {
|
||
return loadLocationList("killer-spawn");
|
||
}
|
||
|
||
public Location getKillerSpawn() {
|
||
List<Location> spawns = loadLocationList("killer-spawn");
|
||
return spawns.isEmpty() ? null : spawns.get(0);
|
||
}
|
||
|
||
public List<Location> getSurvivorSpawns() {
|
||
return loadLocationList("survivor-spawns");
|
||
}
|
||
|
||
private List<Location> loadLocationList(String path) {
|
||
List<Location> locations = new ArrayList<>();
|
||
List<String> list = safeGetStringList(path);
|
||
if (list.isEmpty()) return locations;
|
||
|
||
for (String s : list) {
|
||
Location loc = parseLocation(s);
|
||
if (loc != null) locations.add(loc);
|
||
}
|
||
return locations;
|
||
}
|
||
|
||
private Location parseLocation(String str) {
|
||
// Handle both old format (world,x,y,z,yaw,pitch) and new format (world|x|y|z|yaw|pitch)
|
||
// New format uses | as separator to avoid issues with negative coordinates
|
||
String[] parts = str.contains("|") ? str.split("\\|") : str.split(",");
|
||
|
||
if (parts.length < 4) return null;
|
||
World world = Bukkit.getWorld(parts[0].trim());
|
||
if (world == null) {
|
||
// Try to find by first loaded world as fallback
|
||
var loadedWorld = Bukkit.getWorlds().stream().findFirst();
|
||
if (loadedWorld.isEmpty()) return null;
|
||
world = loadedWorld.get();
|
||
}
|
||
try {
|
||
double x = Double.parseDouble(parts[1].trim());
|
||
double y = Double.parseDouble(parts[2].trim());
|
||
double z = Double.parseDouble(parts[3].trim());
|
||
float yaw = parts.length > 4 ? Float.parseFloat(parts[4].trim()) : 0f;
|
||
float pitch = parts.length > 5 ? Float.parseFloat(parts[5].trim()) : 0f;
|
||
return new Location(world, x, y, z, yaw, pitch);
|
||
} catch (NumberFormatException e) {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
public void addLocation(String path, Location loc) {
|
||
List<String> list = safeGetStringList(path);
|
||
list.add(locationToString(loc));
|
||
config.set(path, list);
|
||
}
|
||
|
||
/**
|
||
* Sets a location at a specific index in the list.
|
||
* If the index is beyond the current list size, pads with empty strings.
|
||
*/
|
||
public void setLocationAtIndex(String path, int index, Location loc) {
|
||
List<String> list = safeGetStringList(path);
|
||
while (list.size() <= index) {
|
||
list.add("");
|
||
}
|
||
list.set(index, locationToString(loc));
|
||
config.set(path, list);
|
||
}
|
||
|
||
/** Безопасная загрузка StringList: использует getList с fallback на toString(). */
|
||
private List<String> safeGetStringList(String path) {
|
||
List<String> result = new ArrayList<>();
|
||
List<?> raw = config.getList(path);
|
||
if (raw != null) {
|
||
for (Object obj : raw) {
|
||
if (obj instanceof String s) {
|
||
result.add(s);
|
||
} else if (obj != null) {
|
||
result.add(obj.toString());
|
||
}
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/** Очистить список локаций (используется при загрузке карты). */
|
||
public void clearLocationList(String path) {
|
||
config.set(path, new ArrayList<>());
|
||
}
|
||
public void setSingleLocation(String path, Location loc) {
|
||
List<String> list = new ArrayList<>();
|
||
list.add(locationToString(loc));
|
||
config.set(path, list);
|
||
}
|
||
|
||
/** Устанавливает ворота A или B (хранятся как gate-a / gate-b). */
|
||
public void setGate(String id, Location loc) {
|
||
String key = "gate-" + id.toLowerCase();
|
||
config.set(key, locationToString(loc));
|
||
}
|
||
|
||
public Location getGate(String id) {
|
||
String key = "gate-" + id.toLowerCase();
|
||
String str = config.getString(key);
|
||
return str != null ? parseLocation(str) : null;
|
||
}
|
||
|
||
public List<Location> getExitGates() {
|
||
// Пробуем новый формат gate-a / gate-b
|
||
List<Location> gates = new ArrayList<>();
|
||
Location a = getGate("a");
|
||
Location b = getGate("b");
|
||
if (a != null) gates.add(a);
|
||
if (b != null) gates.add(b);
|
||
// Фолбэк: старый список exitgates
|
||
if (gates.isEmpty()) {
|
||
gates.addAll(loadLocationList("exitgates"));
|
||
}
|
||
return gates;
|
||
}
|
||
|
||
private String locationToString(Location loc) {
|
||
// Use | as separator instead of , to avoid issues with negative coordinates in YAML
|
||
return String.format("%s|%.2f|%.2f|%.2f|%.1f|%.1f",
|
||
loc.getWorld().getName(),
|
||
loc.getX(), loc.getY(), loc.getZ(),
|
||
loc.getYaw(), loc.getPitch());
|
||
}
|
||
|
||
public FileConfiguration getConfig() {
|
||
return config;
|
||
}
|
||
|
||
/**
|
||
* Reload locations from the given FileConfiguration (freshly loaded from disk).
|
||
* This clears any stale in-memory state and re-applies defaults.
|
||
*/
|
||
/** Reload internal FileConfiguration reference (used after config reload from disk). */
|
||
public void reload(FileConfiguration newConfig) {
|
||
// Replace defaults on new config
|
||
if (!newConfig.contains("lobby")) {
|
||
newConfig.set("lobby.world", "world");
|
||
newConfig.set("lobby.x", 0.0);
|
||
newConfig.set("lobby.y", 100.0);
|
||
newConfig.set("lobby.z", 0.0);
|
||
newConfig.set("lobby.yaw", 0.0);
|
||
newConfig.set("lobby.pitch", 0.0);
|
||
}
|
||
// Copy all data from new config to current config
|
||
for (String key : newConfig.getKeys(true)) {
|
||
config.set(key, newConfig.get(key));
|
||
}
|
||
}
|
||
}
|