mdbd/src/main/java/dev/loki/config/LocationsConfig.java
2026-06-10 23:00:12 +02:00

250 lines
8.9 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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));
}
}
}