Refactor configuration handling and add world border support
Moved FLAG settings from Config to GameConfig for better modularity. Introduced world border configuration with types and sizes for different game phases. Updated related classes to utilize new configuration structure and added error handling to prevent runtime failures.
This commit is contained in:
parent
d7432c9b89
commit
74cf3589c0
|
|
@ -52,8 +52,8 @@ public class Main extends JavaPlugin {
|
|||
flag = new Flag(this, gameManager);
|
||||
new CommandManager(this, gameManager, flag, worldBorderApi);
|
||||
//Ensuring immediate respawn is on in all worlds
|
||||
log.info("Enabling immediate respawn for {}.", Config.FLAG.world);
|
||||
World world = Bukkit.getWorld(Config.FLAG.world);
|
||||
log.info("Enabling immediate respawn for {}.", GameConfig.FLAG.world);
|
||||
World world = Bukkit.getWorld(GameConfig.FLAG.world);
|
||||
if (world != null) {
|
||||
world.setGameRule(GameRule.DO_IMMEDIATE_RESPAWN, true);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -41,21 +41,4 @@ public class Config extends AbstractConfig{
|
|||
}
|
||||
}
|
||||
|
||||
public static class FLAG {
|
||||
private static final String prefix = "flag.";
|
||||
|
||||
public static String world = "world";
|
||||
public static double x = 0;
|
||||
public static double y = 0;
|
||||
public static double z = 0;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static void load() {
|
||||
world = config.getString(prefix, "world", world);
|
||||
x = config.getDouble(prefix, "x", x);
|
||||
y = config.getDouble(prefix, "y", y);
|
||||
z = config.getDouble(prefix, "z", z);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import java.time.Duration;
|
|||
import java.util.HashMap;
|
||||
|
||||
@Slf4j
|
||||
public class GameConfig extends AbstractConfig{
|
||||
public class GameConfig extends AbstractConfig {
|
||||
|
||||
static GameConfig config;
|
||||
|
||||
|
|
@ -45,4 +45,55 @@ public class GameConfig extends AbstractConfig{
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class WORLD_BORDER {
|
||||
private static final String prefix = "world-border.";
|
||||
|
||||
private static final HashMap<GamePhase, WorldBorderSettings> GAME_PHASE_WORLD_BORDER = new HashMap<>();
|
||||
|
||||
public static HashMap<GamePhase, WorldBorderSettings> getGAME_PHASE_WORLD_BORDER() {
|
||||
return new HashMap<>(GAME_PHASE_WORLD_BORDER);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static void load() {
|
||||
GAME_PHASE_WORLD_BORDER.clear();
|
||||
for (GamePhase phase : GamePhase.values()) {
|
||||
String stringType = config.getString(prefix, phase.name().toLowerCase() + ".type", WorldBorderType.PLAYER.name());
|
||||
double size = config.getDouble(prefix, phase.name().toLowerCase() + ".size", 10);
|
||||
|
||||
WorldBorderType worldBorderType;
|
||||
try {
|
||||
worldBorderType = WorldBorderType.valueOf(stringType);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("Invalid world border type [{}] in game phase world border config", stringType);
|
||||
continue;
|
||||
}
|
||||
GAME_PHASE_WORLD_BORDER.put(phase, new WorldBorderSettings(worldBorderType, size));
|
||||
log.debug("Set {} phase world border type to {} blocks", phase.name(), size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class FLAG {
|
||||
private static final String prefix = "flag.";
|
||||
|
||||
public static String world = "world";
|
||||
public static double x = 0;
|
||||
public static double y = 0;
|
||||
public static double z = 0;
|
||||
public static double CAPTURE_RADIUS = 7;
|
||||
public static int WINNING_SCORE = 50;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static void load() {
|
||||
world = config.getString(prefix, "world", world);
|
||||
x = config.getDouble(prefix, "x", x);
|
||||
y = config.getDouble(prefix, "y", y);
|
||||
z = config.getDouble(prefix, "z", z);
|
||||
CAPTURE_RADIUS = config.getDouble(prefix, "capture-radius", CAPTURE_RADIUS);
|
||||
WINNING_SCORE = config.getInt(prefix, "winning-score", WINNING_SCORE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ public class Messages extends AbstractConfig {
|
|||
static Messages config;
|
||||
|
||||
Messages(Main main) {
|
||||
super(main, "config.yml");
|
||||
super(main, "messages.yml");
|
||||
}
|
||||
|
||||
public static void reload(Main main) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
package com.alttd.ctf.config;
|
||||
|
||||
public record WorldBorderSettings(WorldBorderType type, double size) {
|
||||
}
|
||||
6
src/main/java/com/alttd/ctf/config/WorldBorderType.java
Normal file
6
src/main/java/com/alttd/ctf/config/WorldBorderType.java
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
package com.alttd.ctf.config;
|
||||
|
||||
public enum WorldBorderType {
|
||||
FLAG,
|
||||
PLAYER
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.alttd.ctf.events;
|
||||
|
||||
import com.alttd.ctf.Main;
|
||||
import com.alttd.ctf.config.Config;
|
||||
import com.alttd.ctf.game.GameManager;
|
||||
import com.alttd.ctf.game.GamePhase;
|
||||
import com.alttd.ctf.team.TeamPlayer;
|
||||
|
|
@ -54,7 +55,7 @@ public class OnPlayerDeath implements Listener {
|
|||
}
|
||||
TeamPlayer teamPlayer = optionalTeamPlayer.get();
|
||||
event.setRespawnLocation(player.getWorld().getSpawnLocation());
|
||||
Bukkit.getScheduler().runTaskLater(main, () -> teamPlayer.getGameClass().apply(teamPlayer, worldBorderApi, gamePhase.get(), true), 10 * 20);//10 x 20 ticks aka 10 seconds
|
||||
Bukkit.getScheduler().runTaskLater(main, () -> teamPlayer.getGameClass().apply(teamPlayer, worldBorderApi, gamePhase.get(), true), Config.SETTINGS * 20);//10 x 20 ticks aka 10 seconds
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
package com.alttd.ctf.flag;
|
||||
|
||||
import com.alttd.ctf.Main;
|
||||
import com.alttd.ctf.config.Config;
|
||||
import com.alttd.ctf.config.GameConfig;
|
||||
import com.alttd.ctf.game.GameManager;
|
||||
import com.alttd.ctf.team.Team;
|
||||
import com.alttd.ctf.team.TeamColor;
|
||||
import com.alttd.ctf.team.TeamPlayer;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
|
|
@ -21,13 +20,9 @@ import org.bukkit.boss.KeyedBossBar;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
|
|
@ -49,11 +44,11 @@ public class Flag implements Runnable {
|
|||
public Flag(Main main, GameManager gameManager) {
|
||||
this.main = main;
|
||||
this.gameManager = gameManager;
|
||||
World world = Bukkit.getWorld(Config.FLAG.world);
|
||||
World world = Bukkit.getWorld(GameConfig.FLAG.world);
|
||||
if (world == null) {
|
||||
throw new IllegalStateException(String.format("Tried to spawn flag in world [%s] that doesn't exist", Config.FLAG.world));
|
||||
throw new IllegalStateException(String.format("Tried to spawn flag in world [%s] that doesn't exist", GameConfig.FLAG.world));
|
||||
}
|
||||
this.flagLocation = new Location(world, Config.FLAG.x, Config.FLAG.y, Config.FLAG.z);
|
||||
this.flagLocation = new Location(world, GameConfig.FLAG.x, GameConfig.FLAG.y, GameConfig.FLAG.z);
|
||||
}
|
||||
|
||||
private BossBar createBossBar() {
|
||||
|
|
@ -194,7 +189,7 @@ public class Flag implements Runnable {
|
|||
if (max.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (max.get().getValue() < 100) {
|
||||
if (max.get().getValue() < GameConfig.FLAG.WINNING_SCORE) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return gameManager.getTeam(max.get().getKey());
|
||||
|
|
@ -209,7 +204,7 @@ public class Flag implements Runnable {
|
|||
private CompletableFuture<Boolean> updateScoreBasedOnNearbyPlayers() {
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
Bukkit.getScheduler().runTask(main, () -> {
|
||||
Collection<Player> nearbyPlayers = flagLocation.getNearbyPlayers(10);
|
||||
Collection<Player> nearbyPlayers = flagLocation.getNearbyPlayers(GameConfig.FLAG.CAPTURE_RADIUS);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(main, () -> {
|
||||
boolean result = updateScoreBasedOnNearbyPlayers(nearbyPlayers);
|
||||
future.complete(result);
|
||||
|
|
@ -288,7 +283,7 @@ public class Flag implements Runnable {
|
|||
bossBar.setTitle(String.format("Team %s is capturing the flag", PlainTextComponentSerializer.plainText().serialize(team.get().getName())));
|
||||
lastWinningTeamId = highestKey;
|
||||
}
|
||||
bossBar.setProgress(Math.min(100, teamFlagPointCount.get(highestKey)) / 100.0);
|
||||
bossBar.setProgress(Math.min(GameConfig.FLAG.WINNING_SCORE, teamFlagPointCount.get(highestKey)) / (double) GameConfig.FLAG.WINNING_SCORE);
|
||||
bossBar.setVisible(teamFlagPointCount.get(highestKey) > 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,19 +33,24 @@ public class RunningGame implements Runnable {
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
GamePhase nextPhase = GamePhase.values().length < currentPhase.ordinal() ? null : GamePhase.values()[currentPhase.ordinal() + 1];
|
||||
if (phaseStartTime == null) {
|
||||
phaseStartTime = Instant.now();
|
||||
nextPhaseActions(null, currentPhase, nextPhase);
|
||||
}
|
||||
try {
|
||||
GamePhase nextPhase = GamePhase.values().length < currentPhase.ordinal() ? null : GamePhase.values()[currentPhase.ordinal() + 1];
|
||||
if (phaseStartTime == null) {
|
||||
phaseStartTime = Instant.now();
|
||||
nextPhaseActions(null, currentPhase, nextPhase);
|
||||
}
|
||||
|
||||
if (Duration.between(phaseStartTime, Instant.now()).compareTo(phaseDurations.get(currentPhase)) >= 0) {
|
||||
GamePhase previousPhase = currentPhase;
|
||||
currentPhase = GamePhase.values()[currentPhase.ordinal() + 1];
|
||||
nextPhaseActions(previousPhase, currentPhase, nextPhase);
|
||||
phaseStartTime = Instant.now();
|
||||
} else if (nextPhase != null) {
|
||||
broadcastNextPhaseStartTime(currentPhase, nextPhase);
|
||||
if (Duration.between(phaseStartTime, Instant.now()).compareTo(phaseDurations.get(currentPhase)) >= 0) {
|
||||
GamePhase previousPhase = currentPhase;
|
||||
currentPhase = GamePhase.values()[currentPhase.ordinal() + 1];
|
||||
nextPhaseActions(previousPhase, currentPhase, nextPhase);
|
||||
phaseStartTime = Instant.now();
|
||||
} else if (nextPhase != null) {
|
||||
broadcastNextPhaseStartTime(currentPhase, nextPhase);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Unexpected error in running game", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.alttd.ctf.game.phases;
|
||||
|
||||
import com.alttd.ctf.config.Config;
|
||||
import com.alttd.ctf.config.GameConfig;
|
||||
import com.alttd.ctf.flag.Flag;
|
||||
import com.alttd.ctf.game.GamePhase;
|
||||
import com.alttd.ctf.game.GamePhaseExecutor;
|
||||
|
|
@ -32,7 +32,7 @@ public class EndedPhase implements GamePhaseExecutor {
|
|||
HashMap<Team, Integer> wins = flag.getWins();
|
||||
Bukkit.broadcast(Component.join(JoinConfiguration.separator(Component.newline()), getWinnerMessages(wins)));
|
||||
new Thread(() -> {
|
||||
World world = Bukkit.getWorld(Config.FLAG.world);
|
||||
World world = Bukkit.getWorld(GameConfig.FLAG.world);
|
||||
if (world == null) {
|
||||
log.error("Invalid flag world defined");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#Sat Feb 08 21:33:29 CET 2025
|
||||
buildNumber=29
|
||||
#Sat Feb 08 21:57:04 CET 2025
|
||||
buildNumber=30
|
||||
version=0.1
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user