Add WorldGuard auto-region creation and split ConfigLoader

- Add WorldGuardConfig with template-based naming ({mine_name}_{random_4}, etc.)
- Add WorldGuardRegionService for creating/updating/deleting WG regions
- Add WorldGuardConfigLoader for parsing WG config from YAML
- Add configurable flags, owners, members for WG regions
- Update MineConfig to include worldGuard section
- Update Mines.java to create/delete WG regions on mine create/delete
- Update MineFileManager to load WG defaults from defaults.yml
- Split ConfigLoader into specialized loaders:
  - BlockConfigLoader, RegionConfigLoader, ResetConfigLoader
  - RewardConfigLoader, TeleportConfigLoader, UIConfigLoader
- Reduce ConfigLoader from 427 lines to 151 lines
- Update defaults.yml with WorldGuard configuration section
This commit is contained in:
loki5512344 2026-05-31 22:39:01 +02:00
parent 75d785147d
commit 3ba6f303f8
15 changed files with 1126 additions and 318 deletions

View file

@ -1,47 +1,38 @@
package dev.loki.lomines.data.config;
import dev.loki.lomines.data.config.block.BlockConfig;
import dev.loki.lomines.data.config.block.BlockKey;
import dev.loki.lomines.data.config.block.FillMode;
import dev.loki.lomines.data.config.region.RegionConfig;
import dev.loki.lomines.data.config.reset.ResetConfig;
import dev.loki.lomines.data.config.reward.RewardConfig;
import dev.loki.lomines.data.config.reward.RewardConfig.RewardEntry;
import dev.loki.lomines.data.config.reward.RewardConfig.RewardEntry.ItemReward;
import dev.loki.lomines.data.config.teleport.TeleportConfig;
import dev.loki.lomines.data.config.ui.UIConfig;
import dev.loki.lomines.util.location.Cuboid;
import dev.loki.lomines.util.location.LocationParser;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import dev.loki.lomines.data.config.loader.*;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.*;
import java.util.List;
/**
* Clean config loader for section-based configuration.
* Supports YAML inheritance from defaults.
* Delegates to specialized loaders for each section.
*/
public final class ConfigLoader {
private final Path dataFolder;
private YamlConfiguration defaults;
// Section loaders
private RegionConfigLoader regionLoader;
private BlockConfigLoader blockLoader;
private ResetConfigLoader resetLoader;
private RewardConfigLoader rewardLoader;
private TeleportConfigLoader teleportLoader;
private UIConfigLoader uiLoader;
private WorldGuardConfigLoader worldGuardLoader;
public ConfigLoader(Path dataFolder) {
this.dataFolder = dataFolder;
loadDefaults();
initLoaders();
}
/**
* Load or create defaults.yml.
*/
private void loadDefaults() {
Path defaultsPath = dataFolder.resolve("mines").resolve("_defaults.yml");
defaults = new YamlConfiguration();
@ -49,7 +40,6 @@ public final class ConfigLoader {
if (Files.exists(defaultsPath)) {
defaults = YamlConfiguration.loadConfiguration(defaultsPath.toFile());
} else {
// Create defaults with sensible values
setDefaults(defaults);
try {
Files.createDirectories(defaultsPath.getParent());
@ -73,8 +63,19 @@ public final class ConfigLoader {
yaml.set("ui.timer-format", "mm:ss");
yaml.set("teleport.enabled", false);
yaml.set("rewards", List.of());
worldGuardLoader.setDefaults(yaml);
}
private void initLoaders() {
regionLoader = new RegionConfigLoader();
blockLoader = new BlockConfigLoader();
resetLoader = new ResetConfigLoader(defaults);
rewardLoader = new RewardConfigLoader();
teleportLoader = new TeleportConfigLoader();
uiLoader = new UIConfigLoader(defaults);
worldGuardLoader = new WorldGuardConfigLoader(defaults);
}
/**
@ -88,18 +89,17 @@ public final class ConfigLoader {
}
YamlConfiguration yaml = YamlConfiguration.loadConfiguration(configPath.toFile());
// Merge with defaults (YAML inheritance)
mergeDefaults(yaml);
try {
return MineConfig.builder(mineName)
.region(parseRegion(yaml))
.blocks(parseBlocks(yaml))
.reset(parseReset(yaml))
.rewards(parseRewards(yaml))
.teleport(parseTeleport(yaml))
.ui(parseUI(yaml))
.region(regionLoader.parse(yaml))
.blocks(blockLoader.parse(yaml))
.reset(resetLoader.parse(yaml))
.rewards(rewardLoader.parse(yaml))
.teleport(teleportLoader.parse(yaml))
.ui(uiLoader.parse(yaml))
.worldGuard(worldGuardLoader.parse(yaml))
.build();
} catch (Exception e) {
throw new ConfigLoadException("Failed to load mine '" + mineName + "': " + e.getMessage(), e);
@ -111,26 +111,15 @@ public final class ConfigLoader {
*/
public void save(MineConfig config) throws ConfigLoadException {
Path configPath = dataFolder.resolve("mines").resolve(config.name() + ".yml");
YamlConfiguration yaml = new YamlConfiguration();
// Save regions
saveRegion(yaml, config.region());
// Save blocks
saveBlocks(yaml, config.blocks());
// Save reset
saveReset(yaml, config.reset());
// Save rewards
saveRewards(yaml, config.rewards());
// Save teleport
saveTeleport(yaml, config.teleport());
// Save UI
saveUI(yaml, config.ui());
regionLoader.save(yaml, config.region());
blockLoader.save(yaml, config.blocks());
resetLoader.save(yaml, config.reset());
rewardLoader.save(yaml, config.rewards());
teleportLoader.save(yaml, config.teleport());
uiLoader.save(yaml, config.ui());
worldGuardLoader.save(yaml, config.worldGuard());
try {
Files.createDirectories(configPath.getParent());
@ -140,272 +129,7 @@ public final class ConfigLoader {
}
}
// --- Parsers ---
private RegionConfig parseRegion(YamlConfiguration yaml) {
List<Location> selections = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
String key = "region.selection." + i;
if (yaml.contains(key)) {
String locStr = yaml.getString(key);
if (locStr != null && !locStr.isBlank()) {
selections.add(parseLocation(locStr));
}
}
}
if (selections.isEmpty()) {
// Legacy fallback
for (int i = 1; i <= 10; i++) {
String key = "selection." + i;
if (yaml.contains(key)) {
String locStr = yaml.getString(key);
if (locStr != null && !locStr.isBlank()) {
selections.add(parseLocation(locStr));
}
}
}
}
if (selections.size() < 2) {
throw new IllegalArgumentException("Mine must have at least 2 selection points (1 region)");
}
return RegionConfig.fromSelections(selections);
}
private BlockConfig parseBlocks(YamlConfiguration yaml) {
ConfigurationSection contents = yaml.getConfigurationSection("blocks.contents");
if (contents == null) {
contents = yaml.getConfigurationSection("contents"); // Legacy fallback
}
if (contents == null) {
throw new IllegalArgumentException("Missing 'blocks.contents' section");
}
Map<BlockKey, Double> weights = new HashMap<>();
for (String key : contents.getKeys(false)) {
double weight = contents.getDouble(key);
if (weight <= 0) continue;
weights.put(BlockKey.deserialize(key), weight);
}
FillMode fillMode = FillMode.valueOf(
yaml.getString("blocks.fill-mode", "CUBOID").toUpperCase()
);
// Parse mask config if applicable
BlockConfig.MaskConfig mask = null;
if (fillMode == FillMode.MASK) {
String markerStr = yaml.getString("blocks.mask.marker", "pink_concrete");
BlockKey marker = BlockKey.deserialize(markerStr);
Map<String, Boolean> positions = new HashMap<>();
List<String> posList = yaml.getStringList("blocks.mask.positions");
for (String pos : posList) {
positions.put(pos, true);
}
mask = new BlockConfig.MaskConfig(marker, positions);
}
return new BlockConfig(weights, fillMode, mask);
}
private ResetConfig parseReset(YamlConfiguration yaml) {
String intervalStr = yaml.getString("reset.interval", defaults.getString("reset.interval", "5m"));
return ResetConfig.builder()
.interval(intervalStr)
.percentTrigger(yaml.getDouble("reset.percent-trigger", defaults.getDouble("reset.percent-trigger", 10.0)))
.percentEnabled(yaml.getBoolean("reset.percent-enabled", defaults.getBoolean("reset.percent-enabled", false)))
.commands(yaml.getStringList("reset.commands"))
.broadcastMessage(yaml.getString("reset.broadcast", ""))
.build();
}
private RewardConfig parseRewards(YamlConfiguration yaml) {
List<RewardEntry> entries = new ArrayList<>();
List<Map<?, ?>> rewardList = yaml.getMapList("rewards");
if (rewardList.isEmpty()) {
rewardList = yaml.getMapList("random-rewards"); // Legacy fallback
}
for (Map<?, ?> map : rewardList) {
entries.add(parseRewardEntry(map));
}
return new RewardConfig(entries);
}
private RewardEntry parseRewardEntry(Map<?, ?> map) {
double chance = ((Number) map.getOrDefault("chance", 0)).doubleValue();
List<BlockKey> blocks = new ArrayList<>();
List<?> blockList = (List<?>) map.get("blocks");
if (blockList != null) {
for (Object b : blockList) {
blocks.add(BlockKey.deserialize(b.toString()));
}
}
List<ItemReward> items = new ArrayList<>();
List<?> itemList = (List<?>) map.get("items");
if (itemList != null) {
for (Object i : itemList) {
@SuppressWarnings("unchecked")
Map<String, Object> itemMap = (Map<String, Object>) i;
items.add(parseItemReward(itemMap));
}
}
List<String> commands = (List<String>) map.getOrDefault("commands", List.of());
boolean preventDrops = (Boolean) map.getOrDefault("prevent-drops", false);
return new RewardEntry(blocks, chance, items, commands, preventDrops);
}
private ItemReward parseItemReward(Map<String, Object> map) {
String typeStr = (String) map.get("type");
Material material = Material.matchMaterial(typeStr);
if (material == null) {
material = Material.STONE;
}
int amount = ((Number) map.getOrDefault("amount", 1)).intValue();
String name = (String) map.get("name");
@SuppressWarnings("unchecked")
List<String> lore = (List<String>) map.getOrDefault("lore", List.of());
return new ItemReward(material, amount, name, lore);
}
private TeleportConfig parseTeleport(YamlConfiguration yaml) {
boolean enabled = yaml.getBoolean("teleport.enabled", false);
if (!enabled) {
return TeleportConfig.disabled();
}
String locStr = yaml.getString("teleport.location");
if (locStr == null) {
return TeleportConfig.disabled();
}
return TeleportConfig.at(parseLocation(locStr));
}
private UIConfig parseUI(YamlConfiguration yaml) {
boolean actionBarEnabled = yaml.getBoolean("ui.actionbar.enabled",
defaults.getBoolean("ui.actionbar.enabled", true));
return new UIConfig(
actionBarEnabled,
yaml.getString("ui.actionbar.format", UIConfig.DEFAULT_ACTIONBAR_FORMAT),
yaml.getDouble("ui.actionbar.range", 50.0),
yaml.getString("ui.timer-format", UIConfig.DEFAULT_TIMER_FORMAT)
);
}
// --- Savers ---
private void saveRegion(YamlConfiguration yaml, RegionConfig region) {
int i = 1;
for (Cuboid cuboid : region.regions()) {
yaml.set("region.selection." + i, LocationParser.format(cuboid.getMin()));
i++;
yaml.set("region.selection." + i, LocationParser.format(cuboid.getMax()));
i++;
}
}
private void saveBlocks(YamlConfiguration yaml, BlockConfig blocks) {
for (var entry : blocks.weights().entrySet()) {
yaml.set("blocks.contents." + entry.getKey().serialize(), entry.getValue());
}
yaml.set("blocks.fill-mode", blocks.fillMode().name().toLowerCase());
if (blocks.fillMode() == FillMode.MASK && blocks.mask() != null) {
yaml.set("blocks.mask.marker", blocks.mask().marker().serialize());
yaml.set("blocks.mask.positions", new ArrayList<>(blocks.mask().positions().keySet()));
}
}
private void saveReset(YamlConfiguration yaml, ResetConfig reset) {
yaml.set("reset.interval", reset.intervalDisplay());
yaml.set("reset.percent-trigger", reset.percentTrigger());
yaml.set("reset.percent-enabled", reset.percentEnabled());
yaml.set("reset.commands", reset.commands());
yaml.set("reset.broadcast", reset.broadcastMessage());
}
private void saveRewards(YamlConfiguration yaml, RewardConfig rewards) {
List<Map<String, Object>> list = new ArrayList<>();
for (RewardEntry entry : rewards.entries()) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("chance", entry.chance());
map.put("blocks", entry.blocks().stream().map(BlockKey::serialize).toList());
List<Map<String, Object>> items = new ArrayList<>();
for (ItemReward item : entry.items()) {
Map<String, Object> itemMap = new LinkedHashMap<>();
itemMap.put("type", item.material().name().toLowerCase());
itemMap.put("amount", item.amount());
if (item.displayName() != null) {
itemMap.put("name", item.displayName());
}
if (!item.lore().isEmpty()) {
itemMap.put("lore", item.lore());
}
items.add(itemMap);
}
map.put("items", items);
map.put("commands", entry.commands());
map.put("prevent-drops", entry.preventVanillaDrops());
list.add(map);
}
yaml.set("rewards", list);
}
private void saveTeleport(YamlConfiguration yaml, TeleportConfig teleport) {
yaml.set("teleport.enabled", teleport.enabled());
teleport.getLocation().ifPresent(loc ->
yaml.set("teleport.location", LocationParser.format(loc)));
}
private void saveUI(YamlConfiguration yaml, UIConfig ui) {
yaml.set("ui.actionbar.enabled", ui.actionBarEnabled());
yaml.set("ui.actionbar.format", ui.actionBarFormat());
yaml.set("ui.actionbar.range", ui.actionBarRange());
yaml.set("ui.timer-format", ui.timerFormat());
}
// --- Helpers ---
private Location parseLocation(String str) {
String[] parts = str.split(";");
if (parts.length < 4) {
throw new IllegalArgumentException("Invalid location format: " + str);
}
World world = Bukkit.getWorld(parts[0]);
if (world == null) {
throw new IllegalArgumentException("Unknown world: " + parts[0]);
}
double x = Double.parseDouble(parts[1]);
double y = Double.parseDouble(parts[2]);
double z = Double.parseDouble(parts[3]);
float yaw = parts.length > 4 ? Float.parseFloat(parts[4]) : 0;
float pitch = parts.length > 5 ? Float.parseFloat(parts[5]) : 0;
return new Location(world, x, y, z, yaw, pitch);
}
private void mergeDefaults(YamlConfiguration yaml) {
// Simple shallow merge - could be enhanced for deep merging
for (String key : defaults.getKeys(true)) {
if (!yaml.contains(key)) {
yaml.set(key, defaults.get(key));

View file

@ -6,6 +6,7 @@ import dev.loki.lomines.data.config.reset.ResetConfig;
import dev.loki.lomines.data.config.reward.RewardConfig;
import dev.loki.lomines.data.config.teleport.TeleportConfig;
import dev.loki.lomines.data.config.ui.UIConfig;
import dev.loki.lomines.integration.worldguard.WorldGuardConfig;
import java.util.Objects;
@ -20,7 +21,8 @@ public record MineConfig(
ResetConfig reset,
RewardConfig rewards,
TeleportConfig teleport,
UIConfig ui
UIConfig ui,
WorldGuardConfig worldGuard
) {
public MineConfig {
@ -36,6 +38,7 @@ public record MineConfig(
Objects.requireNonNull(rewards, "Reward config cannot be null");
Objects.requireNonNull(teleport, "Teleport config cannot be null");
Objects.requireNonNull(ui, "UI config cannot be null");
// worldGuard can be null (disabled by default)
}
/**
@ -70,7 +73,8 @@ public record MineConfig(
ResetConfig.defaults(),
RewardConfig.empty(),
TeleportConfig.disabled(),
UIConfig.defaults()
UIConfig.defaults(),
WorldGuardConfig.disabled()
);
}
@ -84,6 +88,7 @@ public record MineConfig(
private RewardConfig rewards = RewardConfig.empty();
private TeleportConfig teleport = TeleportConfig.disabled();
private UIConfig ui = UIConfig.defaults();
private WorldGuardConfig worldGuard = WorldGuardConfig.disabled();
private Builder(String name) {
this.name = name;
@ -119,8 +124,13 @@ public record MineConfig(
return this;
}
public Builder worldGuard(WorldGuardConfig worldGuard) {
this.worldGuard = worldGuard;
return this;
}
public MineConfig build() {
return new MineConfig(name, region, blocks, reset, rewards, teleport, ui);
return new MineConfig(name, region, blocks, reset, rewards, teleport, ui, worldGuard);
}
}
}

View file

@ -0,0 +1,75 @@
package dev.loki.lomines.data.config.loader;
import dev.loki.lomines.data.config.block.BlockConfig;
import dev.loki.lomines.data.config.block.BlockKey;
import dev.loki.lomines.data.config.block.FillMode;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Loader for blocks configuration section.
*/
public final class BlockConfigLoader {
/**
* Parses block configuration from YAML.
*/
public BlockConfig parse(YamlConfiguration yaml) {
ConfigurationSection contents = yaml.getConfigurationSection("blocks.contents");
if (contents == null) {
contents = yaml.getConfigurationSection("contents"); // Legacy fallback
}
if (contents == null) {
throw new IllegalArgumentException("Missing 'blocks.contents' section");
}
Map<BlockKey, Double> weights = new HashMap<>();
for (String key : contents.getKeys(false)) {
double weight = contents.getDouble(key);
if (weight <= 0) continue;
weights.put(BlockKey.deserialize(key), weight);
}
FillMode fillMode = FillMode.valueOf(
yaml.getString("blocks.fill-mode", "CUBOID").toUpperCase()
);
// Parse mask config if applicable
BlockConfig.MaskConfig mask = null;
if (fillMode == FillMode.MASK) {
String markerStr = yaml.getString("blocks.mask.marker", "pink_concrete");
BlockKey marker = BlockKey.deserialize(markerStr);
Map<String, Boolean> positions = new HashMap<>();
List<String> posList = yaml.getStringList("blocks.mask.positions");
for (String pos : posList) {
positions.put(pos, true);
}
mask = new BlockConfig.MaskConfig(marker, positions);
}
return new BlockConfig(weights, fillMode, mask);
}
/**
* Saves block configuration to YAML.
*/
public void save(YamlConfiguration yaml, BlockConfig blocks) {
for (var entry : blocks.weights().entrySet()) {
yaml.set("blocks.contents." + entry.getKey().serialize(), entry.getValue());
}
yaml.set("blocks.fill-mode", blocks.fillMode().name().toLowerCase());
if (blocks.fillMode() == FillMode.MASK && blocks.mask() != null) {
yaml.set("blocks.mask.marker", blocks.mask().marker().serialize());
yaml.set("blocks.mask.positions", new ArrayList<>(blocks.mask().positions().keySet()));
}
}
}

View file

@ -0,0 +1,87 @@
package dev.loki.lomines.data.config.loader;
import dev.loki.lomines.data.config.region.RegionConfig;
import dev.loki.lomines.util.location.LocationParser;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.file.YamlConfiguration;
import java.util.ArrayList;
import java.util.List;
/**
* Loader for region configuration section.
*/
public final class RegionConfigLoader {
/**
* Parses region configuration from YAML.
*/
public RegionConfig parse(YamlConfiguration yaml) {
List<Location> selections = new ArrayList<>();
// Try new format first
for (int i = 1; i <= 10; i++) {
String key = "region.selection." + i;
if (yaml.contains(key)) {
String locStr = yaml.getString(key);
if (locStr != null && !locStr.isBlank()) {
selections.add(parseLocation(locStr));
}
}
}
// Legacy fallback
if (selections.isEmpty()) {
for (int i = 1; i <= 10; i++) {
String key = "selection." + i;
if (yaml.contains(key)) {
String locStr = yaml.getString(key);
if (locStr != null && !locStr.isBlank()) {
selections.add(parseLocation(locStr));
}
}
}
}
if (selections.size() < 2) {
throw new IllegalArgumentException("Mine must have at least 2 selection points (1 region)");
}
return RegionConfig.fromSelections(selections);
}
/**
* Saves region configuration to YAML.
*/
public void save(YamlConfiguration yaml, RegionConfig region) {
int i = 1;
for (var cuboid : region.regions()) {
yaml.set("region.selection." + i, LocationParser.format(cuboid.getMin()));
i++;
yaml.set("region.selection." + i, LocationParser.format(cuboid.getMax()));
i++;
}
}
private Location parseLocation(String str) {
String[] parts = str.split(";");
if (parts.length < 4) {
throw new IllegalArgumentException("Invalid location format: " + str);
}
World world = Bukkit.getWorld(parts[0]);
if (world == null) {
throw new IllegalArgumentException("Unknown world: " + parts[0]);
}
double x = Double.parseDouble(parts[1]);
double y = Double.parseDouble(parts[2]);
double z = Double.parseDouble(parts[3]);
float yaw = parts.length > 4 ? Float.parseFloat(parts[4]) : 0;
float pitch = parts.length > 5 ? Float.parseFloat(parts[5]) : 0;
return new Location(world, x, y, z, yaw, pitch);
}
}

View file

@ -0,0 +1,47 @@
package dev.loki.lomines.data.config.loader;
import dev.loki.lomines.data.config.reset.ResetConfig;
import org.bukkit.configuration.file.YamlConfiguration;
import java.util.List;
/**
* Loader for reset configuration section.
*/
public final class ResetConfigLoader {
private final YamlConfiguration defaults;
public ResetConfigLoader(YamlConfiguration defaults) {
this.defaults = defaults;
}
/**
* Parses reset configuration from YAML.
*/
public ResetConfig parse(YamlConfiguration yaml) {
String intervalStr = yaml.getString("reset.interval",
defaults.getString("reset.interval", "5m"));
return ResetConfig.builder()
.interval(intervalStr)
.percentTrigger(yaml.getDouble("reset.percent-trigger",
defaults.getDouble("reset.percent-trigger", 10.0)))
.percentEnabled(yaml.getBoolean("reset.percent-enabled",
defaults.getBoolean("reset.percent-enabled", false)))
.commands(yaml.getStringList("reset.commands"))
.broadcastMessage(yaml.getString("reset.broadcast", ""))
.build();
}
/**
* Saves reset configuration to YAML.
*/
public void save(YamlConfiguration yaml, ResetConfig reset) {
yaml.set("reset.interval", reset.intervalDisplay());
yaml.set("reset.percent-trigger", reset.percentTrigger());
yaml.set("reset.percent-enabled", reset.percentEnabled());
yaml.set("reset.commands", reset.commands());
yaml.set("reset.broadcast", reset.broadcastMessage());
}
}

View file

@ -0,0 +1,111 @@
package dev.loki.lomines.data.config.loader;
import dev.loki.lomines.data.config.block.BlockKey;
import dev.loki.lomines.data.config.reward.RewardConfig;
import dev.loki.lomines.data.config.reward.RewardConfig.RewardEntry;
import dev.loki.lomines.data.config.reward.RewardConfig.RewardEntry.ItemReward;
import org.bukkit.Material;
import org.bukkit.configuration.file.YamlConfiguration;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Loader for rewards configuration section.
*/
public final class RewardConfigLoader {
/**
* Parses rewards from YAML configuration.
*/
public RewardConfig parse(YamlConfiguration yaml) {
List<RewardEntry> entries = new ArrayList<>();
List<Map<?, ?>> rewardList = yaml.getMapList("rewards");
if (rewardList.isEmpty()) {
rewardList = yaml.getMapList("random-rewards"); // Legacy fallback
}
for (Map<?, ?> map : rewardList) {
entries.add(parseRewardEntry(map));
}
return new RewardConfig(entries);
}
private RewardEntry parseRewardEntry(Map<?, ?> map) {
double chance = ((Number) map.getOrDefault("chance", 0)).doubleValue();
List<BlockKey> blocks = new ArrayList<>();
List<?> blockList = (List<?>) map.get("blocks");
if (blockList != null) {
for (Object b : blockList) {
blocks.add(BlockKey.deserialize(b.toString()));
}
}
List<ItemReward> items = new ArrayList<>();
List<?> itemList = (List<?>) map.get("items");
if (itemList != null) {
for (Object i : itemList) {
@SuppressWarnings("unchecked")
Map<String, Object> itemMap = (Map<String, Object>) i;
items.add(parseItemReward(itemMap));
}
}
@SuppressWarnings("unchecked")
List<String> commands = (List<String>) map.getOrDefault("commands", List.of());
boolean preventDrops = (Boolean) map.getOrDefault("prevent-drops", false);
return new RewardEntry(blocks, chance, items, commands, preventDrops);
}
private ItemReward parseItemReward(Map<String, Object> map) {
String typeStr = (String) map.get("type");
Material material = Material.matchMaterial(typeStr);
if (material == null) {
material = Material.STONE;
}
int amount = ((Number) map.getOrDefault("amount", 1)).intValue();
String name = (String) map.get("name");
@SuppressWarnings("unchecked")
List<String> lore = (List<String>) map.getOrDefault("lore", List.of());
return new ItemReward(material, amount, name, lore);
}
/**
* Saves rewards to YAML configuration.
*/
public void save(YamlConfiguration yaml, RewardConfig rewards) {
List<Map<String, Object>> list = new ArrayList<>();
for (RewardEntry entry : rewards.entries()) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("chance", entry.chance());
map.put("blocks", entry.blocks().stream().map(BlockKey::serialize).toList());
List<Map<String, Object>> items = new ArrayList<>();
for (ItemReward item : entry.items()) {
Map<String, Object> itemMap = new LinkedHashMap<>();
itemMap.put("type", item.material().name().toLowerCase());
itemMap.put("amount", item.amount());
if (item.displayName() != null) {
itemMap.put("name", item.displayName());
}
if (!item.lore().isEmpty()) {
itemMap.put("lore", item.lore());
}
items.add(itemMap);
}
map.put("items", items);
map.put("commands", entry.commands());
map.put("prevent-drops", entry.preventVanillaDrops());
list.add(map);
}
yaml.set("rewards", list);
}
}

View file

@ -0,0 +1,60 @@
package dev.loki.lomines.data.config.loader;
import dev.loki.lomines.data.config.teleport.TeleportConfig;
import dev.loki.lomines.util.location.LocationParser;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.file.YamlConfiguration;
/**
* Loader for teleport configuration section.
*/
public final class TeleportConfigLoader {
/**
* Parses teleport configuration from YAML.
*/
public TeleportConfig parse(YamlConfiguration yaml) {
boolean enabled = yaml.getBoolean("teleport.enabled", false);
if (!enabled) {
return TeleportConfig.disabled();
}
String locStr = yaml.getString("teleport.location");
if (locStr == null || locStr.isBlank()) {
return TeleportConfig.disabled();
}
return TeleportConfig.at(parseLocation(locStr));
}
/**
* Saves teleport configuration to YAML.
*/
public void save(YamlConfiguration yaml, TeleportConfig teleport) {
yaml.set("teleport.enabled", teleport.enabled());
teleport.getLocation().ifPresent(loc ->
yaml.set("teleport.location", LocationParser.format(loc)));
}
private Location parseLocation(String str) {
String[] parts = str.split(";");
if (parts.length < 4) {
throw new IllegalArgumentException("Invalid location format: " + str);
}
World world = Bukkit.getWorld(parts[0]);
if (world == null) {
throw new IllegalArgumentException("Unknown world: " + parts[0]);
}
double x = Double.parseDouble(parts[1]);
double y = Double.parseDouble(parts[2]);
double z = Double.parseDouble(parts[3]);
float yaw = parts.length > 4 ? Float.parseFloat(parts[4]) : 0;
float pitch = parts.length > 5 ? Float.parseFloat(parts[5]) : 0;
return new Location(world, x, y, z, yaw, pitch);
}
}

View file

@ -0,0 +1,41 @@
package dev.loki.lomines.data.config.loader;
import dev.loki.lomines.data.config.ui.UIConfig;
import org.bukkit.configuration.file.YamlConfiguration;
/**
* Loader for UI configuration section.
*/
public final class UIConfigLoader {
private final YamlConfiguration defaults;
public UIConfigLoader(YamlConfiguration defaults) {
this.defaults = defaults;
}
/**
* Parses UI configuration from YAML.
*/
public UIConfig parse(YamlConfiguration yaml) {
boolean actionBarEnabled = yaml.getBoolean("ui.actionbar.enabled",
defaults.getBoolean("ui.actionbar.enabled", true));
return new UIConfig(
actionBarEnabled,
yaml.getString("ui.actionbar.format", UIConfig.DEFAULT_ACTIONBAR_FORMAT),
yaml.getDouble("ui.actionbar.range", 50.0),
yaml.getString("ui.timer-format", UIConfig.DEFAULT_TIMER_FORMAT)
);
}
/**
* Saves UI configuration to YAML.
*/
public void save(YamlConfiguration yaml, UIConfig ui) {
yaml.set("ui.actionbar.enabled", ui.actionBarEnabled());
yaml.set("ui.actionbar.format", ui.actionBarFormat());
yaml.set("ui.actionbar.range", ui.actionBarRange());
yaml.set("ui.timer-format", ui.timerFormat());
}
}

View file

@ -0,0 +1,104 @@
package dev.loki.lomines.data.config.loader;
import dev.loki.lomines.data.config.ConfigLoader;
import dev.loki.lomines.integration.worldguard.WorldGuardConfig;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Loader for WorldGuard configuration section.
*/
public final class WorldGuardConfigLoader {
private final YamlConfiguration defaults;
public WorldGuardConfigLoader(YamlConfiguration defaults) {
this.defaults = defaults;
}
/**
* Parses WorldGuard configuration from YAML.
*/
public WorldGuardConfig parse(YamlConfiguration yaml) {
ConfigurationSection wgSection = yaml.getConfigurationSection("worldguard");
if (wgSection == null) {
// Check defaults
boolean defaultEnabled = defaults.getBoolean("worldguard.enabled", false);
if (!defaultEnabled) {
return WorldGuardConfig.disabled();
}
}
boolean enabled = yaml.getBoolean("worldguard.enabled",
defaults.getBoolean("worldguard.enabled", false));
if (!enabled) {
return WorldGuardConfig.disabled();
}
String template = yaml.getString("worldguard.region-template",
defaults.getString("worldguard.region-template", "{mine_name}_{random_4}"));
List<String> owners = yaml.getStringList("worldguard.owners");
if (owners.isEmpty()) {
owners = defaults.getStringList("worldguard.owners");
}
List<String> members = yaml.getStringList("worldguard.members");
if (members.isEmpty()) {
members = defaults.getStringList("worldguard.members");
}
List<String> flags = yaml.getStringList("worldguard.flags");
if (flags.isEmpty()) {
flags = defaults.getStringList("worldguard.flags");
}
if (flags.isEmpty()) {
flags = List.of("passthrough=deny", "build=allow");
}
boolean protect = yaml.getBoolean("worldguard.protect-on-create",
defaults.getBoolean("worldguard.protect-on-create", true));
return WorldGuardConfig.builder()
.enabled(true)
.template(template)
.owners(owners)
.members(members)
.flags(flags)
.protectOnCreate(protect)
.build();
}
/**
* Saves WorldGuard configuration to YAML.
*/
public void save(YamlConfiguration yaml, WorldGuardConfig config) {
yaml.set("worldguard.enabled", config.enabled());
if (config.enabled()) {
yaml.set("worldguard.region-template", config.regionNameTemplate());
yaml.set("worldguard.owners", config.owners());
yaml.set("worldguard.members", config.members());
yaml.set("worldguard.flags", config.flags());
yaml.set("worldguard.protect-on-create", config.protectOnCreate());
}
}
/**
* Sets default values for WorldGuard configuration.
*/
public void setDefaults(YamlConfiguration yaml) {
yaml.set("worldguard.enabled", false);
yaml.set("worldguard.region-template", "{mine_name}_{random_4}");
yaml.set("worldguard.owners", List.of());
yaml.set("worldguard.members", List.of());
yaml.set("worldguard.flags", List.of("passthrough=deny", "build=allow"));
yaml.set("worldguard.protect-on-create", true);
}
}