chore: unify checkstyle, fix violations, cleanup bin/

This commit is contained in:
loki5512344 2026-07-12 00:59:11 +02:00
parent 1d8c0ca483
commit a0c1ab8ca1
Signed by: boba
GPG key ID: 253067914055423B
156 changed files with 5222 additions and 4348 deletions

View file

@ -8,24 +8,18 @@ import dev.loki.lomines.data.config.loader.region.WorldGuardConfigLoader;
import dev.loki.lomines.data.config.loader.reward.RewardConfigLoader;
import dev.loki.lomines.data.config.loader.system.ResetConfigLoader;
import dev.loki.lomines.data.config.loader.system.UIConfigLoader;
import dev.loki.lomines.data.config.model.MineConfig;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
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;
private final DefaultsMerger defaultsMerger;
// Section loaders
private RegionConfigLoader regionLoader;
private BlockConfigLoader blockLoader;
private ResetConfigLoader resetLoader;
@ -37,69 +31,29 @@ public final class ConfigLoader {
public ConfigLoader(Path dataFolder) {
this.dataFolder = dataFolder;
loadDefaults();
this.defaultsMerger = new DefaultsMerger(dataFolder);
initLoaders();
}
private void loadDefaults() {
Path defaultsPath = dataFolder.resolve("mines").resolve("_defaults.yml");
defaults = new YamlConfiguration();
if (Files.exists(defaultsPath)) {
defaults = YamlConfiguration.loadConfiguration(defaultsPath.toFile());
} else {
setDefaults(defaults);
try {
Files.createDirectories(defaultsPath.getParent());
defaults.save(defaultsPath.toFile());
} catch (IOException e) {
// Ignore, use in-memory defaults
}
}
}
private void setDefaults(YamlConfiguration yaml) {
yaml.set("reset.interval", "5m");
yaml.set("reset.percent-trigger", 10.0);
yaml.set("reset.percent-enabled", false);
yaml.set("reset.commands", List.of());
yaml.set("reset.broadcast", "");
yaml.set("ui.actionbar.enabled", true);
yaml.set("ui.actionbar.format", "<green>{mine}</green> <gray>{percent}%</gray> <dark_gray>({time})");
yaml.set("ui.actionbar.range", 50.0);
yaml.set("ui.timer-format", "mm:ss");
yaml.set("teleport.enabled", false);
yaml.set("rewards", List.of());
worldGuardLoader.setDefaults(yaml);
playerSpawnLoader.setDefaults(yaml);
}
private void initLoaders() {
regionLoader = new RegionConfigLoader();
blockLoader = new BlockConfigLoader();
resetLoader = new ResetConfigLoader(defaults);
resetLoader = new ResetConfigLoader(defaultsMerger.getDefaults());
rewardLoader = new RewardConfigLoader();
teleportLoader = new TeleportConfigLoader();
uiLoader = new UIConfigLoader(defaults);
worldGuardLoader = new WorldGuardConfigLoader(defaults);
uiLoader = new UIConfigLoader(defaultsMerger.getDefaults());
worldGuardLoader = new WorldGuardConfigLoader(defaultsMerger.getDefaults());
playerSpawnLoader = new PlayerSpawnConfigLoader();
}
/**
* Load a mine configuration from file.
*/
public MineConfig load(String mineName) throws ConfigLoadException {
Path configPath = dataFolder.resolve("mines").resolve(mineName + ".yml");
if (!Files.exists(configPath)) {
if (!Files.exists(dataFolder.resolve("mines").resolve(mineName + ".yml"))) {
throw new ConfigLoadException("Mine not found: " + mineName);
}
Path configPath = dataFolder.resolve("mines").resolve(mineName + ".yml");
YamlConfiguration yaml = YamlConfiguration.loadConfiguration(configPath.toFile());
mergeDefaults(yaml);
defaultsMerger.mergeDefaults(yaml);
try {
return MineConfig.builder(mineName)
@ -117,11 +71,7 @@ public final class ConfigLoader {
}
}
/**
* Save a mine configuration to file.
*/
public void save(MineConfig config) throws ConfigLoadException {
Path configPath = dataFolder.resolve("mines").resolve(config.name() + ".yml");
YamlConfiguration yaml = new YamlConfiguration();
regionLoader.save(yaml, config.region());
@ -134,6 +84,7 @@ public final class ConfigLoader {
playerSpawnLoader.save(yaml, config.playerSpawn());
try {
Path configPath = dataFolder.resolve("mines").resolve(config.name() + ".yml");
Files.createDirectories(configPath.getParent());
yaml.save(configPath.toFile());
} catch (IOException e) {
@ -141,17 +92,6 @@ public final class ConfigLoader {
}
}
private void mergeDefaults(YamlConfiguration yaml) {
for (String key : defaults.getKeys(true)) {
if (!yaml.contains(key)) {
yaml.set(key, defaults.get(key));
}
}
}
/**
* Exception for config loading errors.
*/
public static class ConfigLoadException extends Exception {
public ConfigLoadException(String message) {
super(message);

View file

@ -0,0 +1,71 @@
package dev.loki.lomines.data.config;
import dev.loki.lomines.data.config.loader.region.WorldGuardConfigLoader;
import dev.loki.lomines.data.config.loader.entity.PlayerSpawnConfigLoader;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public final class DefaultsMerger {
private final Path dataFolder;
private YamlConfiguration defaults;
public DefaultsMerger(Path dataFolder) {
this.dataFolder = dataFolder;
loadDefaults();
}
public YamlConfiguration getDefaults() {
return defaults;
}
private void loadDefaults() {
Path defaultsPath = dataFolder.resolve("mines").resolve("_defaults.yml");
defaults = new YamlConfiguration();
if (Files.exists(defaultsPath)) {
defaults = YamlConfiguration.loadConfiguration(defaultsPath.toFile());
} else {
setDefaults(defaults);
try {
Files.createDirectories(defaultsPath.getParent());
defaults.save(defaultsPath.toFile());
} catch (IOException e) {
// Ignore, use in-memory defaults
}
}
}
private void setDefaults(YamlConfiguration yaml) {
yaml.set("reset.interval", "5m");
yaml.set("reset.percent-trigger", 10.0);
yaml.set("reset.percent-enabled", false);
yaml.set("reset.commands", List.of());
yaml.set("reset.broadcast", "");
yaml.set("ui.actionbar.enabled", true);
yaml.set("ui.actionbar.format", "<green>{mine}</green> <gray>{percent}%</gray> <dark_gray>({time})");
yaml.set("ui.actionbar.range", 50.0);
yaml.set("ui.timer-format", "mm:ss");
yaml.set("teleport.enabled", false);
yaml.set("rewards", List.of());
WorldGuardConfigLoader wgLoader = new WorldGuardConfigLoader(new YamlConfiguration());
wgLoader.setDefaults(yaml);
PlayerSpawnConfigLoader psLoader = new PlayerSpawnConfigLoader();
psLoader.setDefaults(yaml);
}
public void mergeDefaults(YamlConfiguration yaml) {
for (String key : defaults.getKeys(true)) {
if (!yaml.contains(key)) {
yaml.set(key, defaults.get(key));
}
}
}
}

View file

@ -32,7 +32,9 @@ public final class BlockConfigLoader {
Map<BlockKey, Double> weights = new HashMap<>();
for (String key : contents.getKeys(false)) {
double weight = contents.getDouble(key);
if (weight <= 0) continue;
if (weight <= 0) {
continue;
}
weights.put(BlockKey.deserialize(key), weight);
}

View file

@ -66,7 +66,9 @@ public final class RegionConfigLoader {
break;
}
}
if (!hasMore) break;
if (!hasMore) {
break;
}
}
}
}

View file

@ -1,6 +1,6 @@
package dev.loki.lomines.data.config.loader.region;
import dev.loki.lomines.integration.worldguard.WorldGuardConfig;
import dev.loki.lomines.integration.worldguard.config.WorldGuardConfig;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
@ -38,9 +38,6 @@ public final class WorldGuardConfigLoader {
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");
@ -63,9 +60,12 @@ public final class WorldGuardConfigLoader {
boolean protect = yaml.getBoolean("worldguard.protect-on-create",
defaults.getBoolean("worldguard.protect-on-create", true));
String tmpl = yaml.getString("worldguard.region-template",
defaults.getString("worldguard.region-template", "{mine_name}_{random_4}"));
return WorldGuardConfig.builder()
.enabled(true)
.template(template)
.template(tmpl)
.owners(owners)
.members(members)
.flags(flags)

View file

@ -36,9 +36,6 @@ public final class RewardConfigLoader {
}
private RewardEntry parseRewardEntry(Map<?, ?> map) {
Object chanceObj = map.get("chance");
double chance = chanceObj instanceof Number n ? n.doubleValue() : 0.0;
List<BlockKey> blocks = new ArrayList<>();
List<?> blockList = (List<?>) map.get("blocks");
if (blockList != null) {
@ -69,6 +66,8 @@ public final class RewardConfigLoader {
Object preventDropsObj = map.get("prevent-drops");
boolean preventDrops = preventDropsObj instanceof Boolean b && b;
Object chanceObj = map.get("chance");
double chance = chanceObj instanceof Number n ? n.doubleValue() : 0.0;
return new RewardEntry(blocks, chance, items, commands, preventDrops);
}

View file

@ -0,0 +1,64 @@
package dev.loki.lomines.data.config.model;
import dev.loki.lomines.data.config.block.BlockConfig;
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.spawn.PlayerSpawnConfig;
import dev.loki.lomines.data.config.teleport.TeleportConfig;
import dev.loki.lomines.data.config.ui.UIConfig;
import dev.loki.lomines.integration.worldguard.config.WorldGuardConfig;
import org.bukkit.Location;
import java.util.Objects;
import java.util.Optional;
public record MineConfig(
String name,
RegionConfig region,
BlockConfig blocks,
ResetConfig reset,
RewardConfig rewards,
TeleportConfig teleport,
UIConfig ui,
WorldGuardConfig worldGuard,
PlayerSpawnConfig playerSpawn
) {
public MineConfig {
Objects.requireNonNull(name, "Mine name cannot be null");
if (name.isBlank()) {
throw new IllegalArgumentException("Mine name cannot be blank");
}
name = name.toLowerCase().trim();
Objects.requireNonNull(region, "Region config cannot be null");
Objects.requireNonNull(blocks, "Block config cannot be null");
Objects.requireNonNull(reset, "Reset config cannot be null");
Objects.requireNonNull(rewards, "Reward config cannot be null");
Objects.requireNonNull(teleport, "Teleport config cannot be null");
Objects.requireNonNull(ui, "UI config cannot be null");
if (playerSpawn == null) {
playerSpawn = PlayerSpawnConfig.disabled();
}
}
public static MineConfigDefaults.Builder builder(String name) {
return new MineConfigDefaults.Builder(name);
}
public int volume() {
return region.totalVolume();
}
public String worldName() {
return region.worldName();
}
public Optional<Location> getSpawnForStuckPlayer() {
return playerSpawn.enabled()
? playerSpawn.getLocation()
: teleport.getLocation();
}
}

View file

@ -1,4 +1,4 @@
package dev.loki.lomines.data.config;
package dev.loki.lomines.data.config.model;
import dev.loki.lomines.data.config.block.BlockConfig;
import dev.loki.lomines.data.config.region.RegionConfig;
@ -7,58 +7,13 @@ import dev.loki.lomines.data.config.reward.RewardConfig;
import dev.loki.lomines.data.config.spawn.PlayerSpawnConfig;
import dev.loki.lomines.data.config.teleport.TeleportConfig;
import dev.loki.lomines.data.config.ui.UIConfig;
import dev.loki.lomines.integration.worldguard.WorldGuardConfig;
import dev.loki.lomines.integration.worldguard.config.WorldGuardConfig;
import org.bukkit.Location;
public final class MineConfigDefaults {
import java.util.Objects;
import java.util.Optional;
/**
* Clean, type-safe, section-based mine configuration.
* Proper separation of concerns: each section handles one aspect.
*/
public record MineConfig(
String name,
RegionConfig region,
BlockConfig blocks,
ResetConfig reset,
RewardConfig rewards,
TeleportConfig teleport,
UIConfig ui,
WorldGuardConfig worldGuard,
PlayerSpawnConfig playerSpawn
) {
public MineConfig {
Objects.requireNonNull(name, "Mine name cannot be null");
if (name.isBlank()) {
throw new IllegalArgumentException("Mine name cannot be blank");
}
name = name.toLowerCase().trim();
Objects.requireNonNull(region, "Region config cannot be null");
Objects.requireNonNull(blocks, "Block config cannot be null");
Objects.requireNonNull(reset, "Reset config cannot be null");
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 and playerSpawn can be null (disabled by default)
if (playerSpawn == null) {
playerSpawn = PlayerSpawnConfig.disabled();
}
private MineConfigDefaults() {
}
/**
* Creates builder for fluent construction.
*/
public static Builder builder(String name) {
return new Builder(name);
}
/**
* Creates config with sensible defaults.
*/
public static MineConfig defaults(String name, RegionConfig region, BlockConfig blocks) {
return new MineConfig(
name,
@ -73,32 +28,6 @@ public record MineConfig(
);
}
/**
* Total volume of the mine (for progress calculation).
*/
public int volume() {
return region.totalVolume();
}
/**
* World name where the mine is located.
*/
public String worldName() {
return region.worldName();
}
/**
* Returns the spawn location for stuck players.
* If playerSpawn is not set, falls back to teleport location.
*/
public Optional<Location> getSpawnForStuckPlayer() {
return playerSpawn.enabled()
? playerSpawn.getLocation()
: teleport.getLocation();
}
// --- Builder ---
public static class Builder {
private final String name;
private RegionConfig region;
@ -110,7 +39,7 @@ public record MineConfig(
private WorldGuardConfig worldGuard = WorldGuardConfig.disabled();
private PlayerSpawnConfig playerSpawn = PlayerSpawnConfig.disabled();
private Builder(String name) {
public Builder(String name) {
this.name = name;
}

View file

@ -1,6 +1,6 @@
package dev.loki.lomines.data.config.region;
import dev.loki.lomines.util.location.Cuboid;
import dev.loki.lomines.util.location.geo.Cuboid;
import org.bukkit.Location;
import java.util.Collections;

View file

@ -3,9 +3,6 @@ package dev.loki.lomines.data.config.reset;
import java.time.Duration;
import java.util.List;
/**
* Configuration for mine reset behavior.
*/
public record ResetConfig(
Duration interval,
double percentTrigger,
@ -14,34 +11,16 @@ public record ResetConfig(
String broadcastMessage
) {
public static final Duration DEFAULT_INTERVAL = Duration.ofMinutes(5);
public static final double DEFAULT_PERCENT_TRIGGER = 10.0;
public ResetConfig {
// Normalize and validate interval
if (interval == null || interval.isZero() || interval.isNegative()) {
interval = DEFAULT_INTERVAL;
}
// Ensure interval is reasonable (1 second to 24 hours)
if (interval.getSeconds() < 1) {
interval = Duration.ofSeconds(1);
} else if (interval.getSeconds() > 86400) {
interval = Duration.ofHours(24);
}
// Validate percent trigger
if (percentTrigger < 0 || percentTrigger > 100) {
percentTrigger = DEFAULT_PERCENT_TRIGGER;
}
interval = ResetConfigValidator.validateInterval(interval);
percentTrigger = ResetConfigValidator.validatePercentTrigger(percentTrigger);
commands = commands != null ? List.copyOf(commands) : List.of();
broadcastMessage = broadcastMessage != null ? broadcastMessage : "";
}
/**
* Default config: 5 minutes, 10% trigger disabled.
*/
public static final Duration DEFAULT_INTERVAL = ResetConfigValidator.DEFAULT_INTERVAL;
public static final double DEFAULT_PERCENT_TRIGGER = ResetConfigValidator.DEFAULT_PERCENT_TRIGGER;
public static ResetConfig defaults() {
return new ResetConfig(
DEFAULT_INTERVAL,
@ -52,23 +31,14 @@ public record ResetConfig(
);
}
/**
* Builder for fluent construction.
*/
public static Builder builder() {
return new Builder();
}
/**
* Interval in ticks (20 ticks = 1 second).
*/
public long intervalTicks() {
return interval.getSeconds() * 20;
}
/**
* Human-readable interval string.
*/
public String intervalDisplay() {
long seconds = interval.getSeconds();
if (seconds < 60) {
@ -80,9 +50,6 @@ public record ResetConfig(
}
}
/**
* Whether reset should trigger based on percent mined.
*/
public boolean isPercentTriggerEnabled() {
return percentEnabled && percentTrigger > 0;
}
@ -94,38 +61,18 @@ public record ResetConfig(
private List<String> commands = List.of();
private String broadcastMessage = "";
private static Duration parseDuration(String s) {
s = s.trim().toLowerCase();
try {
if (s.endsWith("s")) {
return Duration.ofSeconds(Long.parseLong(s.substring(0, s.length() - 1)));
} else if (s.endsWith("m")) {
return Duration.ofMinutes(Long.parseLong(s.substring(0, s.length() - 1)));
} else if (s.endsWith("h")) {
return Duration.ofHours(Long.parseLong(s.substring(0, s.length() - 1)));
} else if (s.endsWith("d")) {
return Duration.ofDays(Long.parseLong(s.substring(0, s.length() - 1)));
} else {
// Assume seconds if no suffix
return Duration.ofSeconds(Long.parseLong(s));
}
} catch (NumberFormatException e) {
return DEFAULT_INTERVAL;
}
}
public Builder interval(Duration interval) {
this.interval = interval;
return this;
}
public Builder intervalTicks(long ticks) {
this.interval = Duration.ofSeconds(ticks / 20);
public Builder interval(String humanReadable) {
this.interval = ResetConfigValidator.parseDuration(humanReadable);
return this;
}
public Builder interval(String humanReadable) {
this.interval = parseDuration(humanReadable);
public Builder intervalTicks(long ticks) {
this.interval = Duration.ofSeconds(ticks / 20);
return this;
}

View file

@ -0,0 +1,50 @@
package dev.loki.lomines.data.config.reset;
import java.time.Duration;
public final class ResetConfigValidator {
public static final Duration DEFAULT_INTERVAL = Duration.ofMinutes(5);
public static final double DEFAULT_PERCENT_TRIGGER = 10.0;
private ResetConfigValidator() {
}
public static Duration validateInterval(Duration interval) {
if (interval == null || interval.isZero() || interval.isNegative()) {
interval = DEFAULT_INTERVAL;
}
if (interval.getSeconds() < 1) {
interval = Duration.ofSeconds(1);
} else if (interval.getSeconds() > 86400) {
interval = Duration.ofHours(24);
}
return interval;
}
public static double validatePercentTrigger(double percentTrigger) {
if (percentTrigger < 0 || percentTrigger > 100) {
return DEFAULT_PERCENT_TRIGGER;
}
return percentTrigger;
}
public static Duration parseDuration(String s) {
s = s.trim().toLowerCase();
try {
if (s.endsWith("s")) {
return Duration.ofSeconds(Long.parseLong(s.substring(0, s.length() - 1)));
} else if (s.endsWith("m")) {
return Duration.ofMinutes(Long.parseLong(s.substring(0, s.length() - 1)));
} else if (s.endsWith("h")) {
return Duration.ofHours(Long.parseLong(s.substring(0, s.length() - 1)));
} else if (s.endsWith("d")) {
return Duration.ofDays(Long.parseLong(s.substring(0, s.length() - 1)));
} else {
return Duration.ofSeconds(Long.parseLong(s));
}
} catch (NumberFormatException e) {
return DEFAULT_INTERVAL;
}
}
}

View file

@ -1,8 +1,10 @@
package dev.loki.lomines.data.config.ui;
import dev.loki.lomines.util.format.ColorUtils;
import dev.loki.lomines.util.format.color.ColorUtils;
import net.kyori.adventure.text.Component;
import java.util.Locale;
/**
* Configuration for UI elements (action bar, messages).
*/
@ -16,6 +18,7 @@ public record UIConfig(
public static final String DEFAULT_ACTIONBAR_FORMAT = "<green>{mine}</green> <gray>{percent}%</gray> <dark_gray>({time})";
public static final String DEFAULT_TIMER_FORMAT = "mm:ss";
public UIConfig {
hologram = hologram != null ? hologram : HologramConfig.disabled();
actionBarFormat = actionBarFormat != null && !actionBarFormat.isBlank()
@ -49,7 +52,7 @@ public record UIConfig(
public Component formatActionBar(String mineName, double percent, String timeStr, int blocks, int total) {
String parsed = actionBarFormat
.replace("{mine}", mineName)
.replace("{percent}", String.format("%.1f", percent))
.replace("{percent}", String.format(Locale.US, "%.1f", percent))
.replace("{time}", timeStr)
.replace("{blocks}", String.valueOf(blocks))
.replace("{total}", String.valueOf(total));