From 5a87784d71d30e7452a3955e055f368b3096b589 Mon Sep 17 00:00:00 2001 From: Teriuihi Date: Fri, 24 Jan 2025 20:12:27 +0100 Subject: [PATCH] Add JSON configuration support and new team management commands Introduced JSON-based configuration handling for teams using Jackson and validation utilities. Added commands for reloading configurations and creating teams with support for saving and loading team data. Refactored related classes to integrate with the new system. --- build.gradle.kts | 19 ++++ src/main/java/com/alttd/ctf/Main.java | 49 ++++++++- .../alttd/ctf/commands/CommandManager.java | 6 +- .../ctf/commands/subcommands/ChangeTeam.java | 8 +- .../ctf/commands/subcommands/CreateTeam.java | 100 ++++++++++++++++++ .../ctf/commands/subcommands/Reload.java | 37 +++++++ .../java/com/alttd/ctf/config/Messages.java | 4 + .../java/com/alttd/ctf/game/GameManager.java | 4 + .../alttd/ctf/json_config/JacksonConfig.java | 24 +++++ .../ctf/json_config/JsonConfigManager.java | 44 ++++++++ .../alttd/ctf/json_config/ValidationUtil.java | 26 +++++ .../component/ComponentDeserializer.java | 28 +++++ .../component/ComponentSerializer.java | 18 ++++ .../location/LocationDeserializer.java | 35 ++++++ .../location/LocationSerializer.java | 23 ++++ src/main/java/com/alttd/ctf/team/Team.java | 27 +++-- .../java/com/alttd/ctf/team/TeamColor.java | 11 +- 17 files changed, 438 insertions(+), 25 deletions(-) create mode 100644 src/main/java/com/alttd/ctf/commands/subcommands/CreateTeam.java create mode 100644 src/main/java/com/alttd/ctf/commands/subcommands/Reload.java create mode 100644 src/main/java/com/alttd/ctf/json_config/JacksonConfig.java create mode 100644 src/main/java/com/alttd/ctf/json_config/JsonConfigManager.java create mode 100644 src/main/java/com/alttd/ctf/json_config/ValidationUtil.java create mode 100644 src/main/java/com/alttd/ctf/json_config/serializers/component/ComponentDeserializer.java create mode 100644 src/main/java/com/alttd/ctf/json_config/serializers/component/ComponentSerializer.java create mode 100644 src/main/java/com/alttd/ctf/json_config/serializers/location/LocationDeserializer.java create mode 100644 src/main/java/com/alttd/ctf/json_config/serializers/location/LocationSerializer.java diff --git a/build.gradle.kts b/build.gradle.kts index 8e05b47..f68b1d6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,8 +15,27 @@ dependencies { testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") + + // Start JSON config dependencies + // Bean Validation API + implementation("jakarta.validation:jakarta.validation-api:3.0.2") + // Hibernate Validator (implementation) + implementation("org.hibernate:hibernate-validator:8.0.2.Final") + // Validation annotations processing + implementation("org.hibernate:hibernate-validator-annotation-processor:8.0.2.Final") + + // Jackson/Dynamic Beans Integration + implementation("com.fasterxml.jackson.module:jackson-module-parameter-names:2.15.2") + // Jackson for JSON Parsing + implementation("com.fasterxml.jackson.core:jackson-databind:2.15.2") + implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.2") + // End JSON config dependencies } tasks.test { useJUnitPlatform() +} + +tasks.jar { + archiveFileName.set("CaptureTheFlag.jar") } \ No newline at end of file diff --git a/src/main/java/com/alttd/ctf/Main.java b/src/main/java/com/alttd/ctf/Main.java index ccd9e8e..5e3124f 100644 --- a/src/main/java/com/alttd/ctf/Main.java +++ b/src/main/java/com/alttd/ctf/Main.java @@ -2,31 +2,74 @@ package com.alttd.ctf; import com.alttd.ctf.commands.CommandManager; import com.alttd.ctf.config.Config; +import com.alttd.ctf.config.GameConfig; +import com.alttd.ctf.config.Messages; import com.alttd.ctf.events.OnSnowballHit; import com.alttd.ctf.game.GameManager; +import com.alttd.ctf.json_config.JacksonConfig; +import com.alttd.ctf.json_config.JsonConfigManager; +import com.alttd.ctf.team.Team; import lombok.extern.slf4j.Slf4j; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + @Slf4j public class Main extends JavaPlugin { + private GameManager gameManager = null; + @Override public void onEnable() { log.info("Plugin enabled!"); reloadConfigs(); - GameManager gameManager = new GameManager(); + this.gameManager = new GameManager(); + registerTeams(); //Skipped in reloadConfig if gameManager is not created yet CommandManager commandManager = new CommandManager(this, gameManager); - registerEvents(gameManager); + registerEvents(); } public void reloadConfigs() { Config.reload(this); + Messages.reload(this); + GameConfig.reload(this); + if (gameManager != null) { + registerTeams(); + } } - private void registerEvents(GameManager gameManager) { + private void registerEvents() { PluginManager pluginManager = getServer().getPluginManager(); pluginManager.registerEvents(new OnSnowballHit(gameManager), this); } + private void registerTeams() { + JsonConfigManager config = new JsonConfigManager<>(JacksonConfig.configureMapper()); + List teams; + try { + File teamsDirectory = new File(getDataFolder(), "teams"); + if (!teamsDirectory.exists() && !teamsDirectory.mkdirs()) { + log.error("Unable to make teams directory at {} shutting down plugin", teamsDirectory.getAbsolutePath()); + } + teams = config.loadConfigs(Team.class, teamsDirectory); + } catch (IOException e) { + log.error("Unable to load teams, shutting down plugin", e); + getServer().getPluginManager().disablePlugin(this); + return; + } + + teams.stream() + .collect(Collectors.groupingBy(Team::getId, Collectors.counting())) + .forEach((id, count) -> { + if (count > 1) { + log.warn("Duplicate team ID found: {}", id); + } + }); + teams.forEach(gameManager::registerTeam); + } + } \ No newline at end of file diff --git a/src/main/java/com/alttd/ctf/commands/CommandManager.java b/src/main/java/com/alttd/ctf/commands/CommandManager.java index e6c3be7..4877529 100644 --- a/src/main/java/com/alttd/ctf/commands/CommandManager.java +++ b/src/main/java/com/alttd/ctf/commands/CommandManager.java @@ -2,6 +2,8 @@ package com.alttd.ctf.commands; import com.alttd.ctf.Main; import com.alttd.ctf.commands.subcommands.ChangeTeam; +import com.alttd.ctf.commands.subcommands.CreateTeam; +import com.alttd.ctf.commands.subcommands.Reload; import com.alttd.ctf.commands.subcommands.Start; import com.alttd.ctf.config.Messages; import com.alttd.ctf.game.GameManager; @@ -34,7 +36,9 @@ public class CommandManager implements CommandExecutor, TabExecutor { subCommands = Arrays.asList( new ChangeTeam(gameManager), - new Start(gameManager) + new Start(gameManager), + new CreateTeam(main, gameManager), + new Reload(main) ); } diff --git a/src/main/java/com/alttd/ctf/commands/subcommands/ChangeTeam.java b/src/main/java/com/alttd/ctf/commands/subcommands/ChangeTeam.java index 3d02e17..3329b32 100644 --- a/src/main/java/com/alttd/ctf/commands/subcommands/ChangeTeam.java +++ b/src/main/java/com/alttd/ctf/commands/subcommands/ChangeTeam.java @@ -4,6 +4,7 @@ import com.alttd.ctf.commands.SubCommand; import com.alttd.ctf.config.Messages; import com.alttd.ctf.game.GameManager; import com.alttd.ctf.team.Team; +import lombok.AllArgsConstructor; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.bukkit.Bukkit; @@ -13,14 +14,11 @@ import org.bukkit.entity.Player; import java.util.List; import java.util.Optional; +@AllArgsConstructor public class ChangeTeam extends SubCommand { private final GameManager gameManager; - public ChangeTeam(GameManager gameManager) { - this.gameManager = gameManager; - } - @FunctionalInterface private interface ChangeTeamConsumer { int apply(Player player, Team team); @@ -66,7 +64,7 @@ public class ChangeTeam extends SubCommand { return; } gameManager.registerPlayer(team, player); - commandSender.sendRichMessage(" has been placed in.", + commandSender.sendRichMessage(" has been placed in .", TagResolver.resolver( Placeholder.component("player", player.displayName()), Placeholder.component("team", team.getName()))); diff --git a/src/main/java/com/alttd/ctf/commands/subcommands/CreateTeam.java b/src/main/java/com/alttd/ctf/commands/subcommands/CreateTeam.java new file mode 100644 index 0000000..f34534f --- /dev/null +++ b/src/main/java/com/alttd/ctf/commands/subcommands/CreateTeam.java @@ -0,0 +1,100 @@ +package com.alttd.ctf.commands.subcommands; + +import com.alttd.ctf.Main; +import com.alttd.ctf.commands.SubCommand; +import com.alttd.ctf.config.Messages; +import com.alttd.ctf.game.GameManager; +import com.alttd.ctf.json_config.JacksonConfig; +import com.alttd.ctf.json_config.JsonConfigManager; +import com.alttd.ctf.team.Team; +import com.alttd.ctf.team.TeamColor; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.util.List; + +@Slf4j +@AllArgsConstructor +public class CreateTeam extends SubCommand { + + private final Main main; + private final GameManager gameManager; + private final JsonConfigManager jsonConfigManager = new JsonConfigManager<>(JacksonConfig.configureMapper()); + + @FunctionalInterface + private interface CreateTeamConsumer { + int apply(Team team); + } + + @Override + public int onCommand(CommandSender commandSender, String[] args) { + return handle(commandSender, args, team -> { + File teamsDirectory = new File(main.getDataFolder(), "teams"); + try { + jsonConfigManager.saveConfig(team, teamsDirectory, String.valueOf(team.getId())); + } catch (IOException e) { + log.error("Unable to save config teams config with id {}.", team.getId(), e); + commandSender.sendRichMessage("Unable to save team"); + return -1; + } + gameManager.registerTeam(team); + commandSender.sendRichMessage("Created team and registered them.", + Placeholder.component("team", team.getName())); + return 0; + }); + } + + private int handle(CommandSender commandSender, String[] args, CreateTeamConsumer consumer) { + if (args.length != 3) { + return -1; + } + if (!(commandSender instanceof Player player)) { + commandSender.sendRichMessage(Messages.GENERIC.PLAYER_ONLY); + return -1; + } + String name = args[1]; + if (name.length() > 16) { + commandSender.sendRichMessage("name needs to be between 3 and 16 characters"); + return 1; + } + + String color = args[2]; + if (!color.matches("^#[0-9a-fA-F]{6}$")) { + commandSender.sendRichMessage("Invalid hex color, style it like #FF00FF"); + return 2; + } + Color decodedColor = Color.decode(color); + TeamColor teamColor = new TeamColor(decodedColor.getRed(), decodedColor.getGreen(), decodedColor.getBlue(), color); + + int highestId = gameManager.getTeams().stream() + .mapToInt(Team::getId) + .max() + .orElse(0); + Team team = new Team(MiniMessage.miniMessage().deserialize(String.format("%s", color, name)), + highestId + 1, player.getLocation(), player.getLocation(), teamColor); + + return consumer.apply(team); + } + + @Override + public String getName() { + return "createteam"; + } + + @Override + public List getTabComplete(CommandSender commandSender, String[] args) { + return List.of(); + } + + @Override + public String getHelpMessage() { + return Messages.HELP.CREATE_TEAM; + } +} diff --git a/src/main/java/com/alttd/ctf/commands/subcommands/Reload.java b/src/main/java/com/alttd/ctf/commands/subcommands/Reload.java new file mode 100644 index 0000000..672d263 --- /dev/null +++ b/src/main/java/com/alttd/ctf/commands/subcommands/Reload.java @@ -0,0 +1,37 @@ +package com.alttd.ctf.commands.subcommands; + +import com.alttd.ctf.Main; +import com.alttd.ctf.commands.SubCommand; +import com.alttd.ctf.config.Messages; +import lombok.AllArgsConstructor; +import org.bukkit.command.CommandSender; + +import java.util.List; + +@AllArgsConstructor +public class Reload extends SubCommand { + + private final Main main; + + @Override + public int onCommand(CommandSender commandSender, String[] args) { + main.reloadConfig(); + commandSender.sendRichMessage("Reloaded the configuration files"); + return 0; + } + + @Override + public String getName() { + return "reload"; + } + + @Override + public List getTabComplete(CommandSender commandSender, String[] args) { + return List.of(); + } + + @Override + public String getHelpMessage() { + return Messages.HELP.RELOAD; + } +} diff --git a/src/main/java/com/alttd/ctf/config/Messages.java b/src/main/java/com/alttd/ctf/config/Messages.java index e4f7373..d5c2783 100644 --- a/src/main/java/com/alttd/ctf/config/Messages.java +++ b/src/main/java/com/alttd/ctf/config/Messages.java @@ -22,14 +22,18 @@ public class Messages extends AbstractConfig { public static String HELP_MESSAGE_WRAPPER = "Main help:\n"; public static String HELP_MESSAGE = "Show this menu: /ctf help"; + public static String RELOAD = "Reload the configs: /ctf reload"; public static String CHANGE_TEAM = "Change a players team: /ctf changeteam "; + public static String CREATE_TEAM = "Create a team: /ctf createteam "; public static String START = "Start a new game: /ctf start "; @SuppressWarnings("unused") private static void load() { HELP_MESSAGE_WRAPPER = config.getString(prefix, "help-wrapper", HELP_MESSAGE_WRAPPER); HELP_MESSAGE = config.getString(prefix, "help", HELP_MESSAGE); + RELOAD = config.getString(prefix, "reload", RELOAD); CHANGE_TEAM = config.getString(prefix, "change-team", CHANGE_TEAM); + CREATE_TEAM = config.getString(prefix, "create-team", CREATE_TEAM); START = config.getString(prefix, "start", START); } } diff --git a/src/main/java/com/alttd/ctf/game/GameManager.java b/src/main/java/com/alttd/ctf/game/GameManager.java index d3d711e..c6edfa4 100644 --- a/src/main/java/com/alttd/ctf/game/GameManager.java +++ b/src/main/java/com/alttd/ctf/game/GameManager.java @@ -41,6 +41,10 @@ public class GameManager { teams.values().forEach(team -> team.removePlayer(player.getUniqueId())); } + public void registerTeam(Team team) { + teams.put(team.getId(), team); + } + public Collection getTeams() { return teams.values(); } diff --git a/src/main/java/com/alttd/ctf/json_config/JacksonConfig.java b/src/main/java/com/alttd/ctf/json_config/JacksonConfig.java new file mode 100644 index 0000000..f204cdf --- /dev/null +++ b/src/main/java/com/alttd/ctf/json_config/JacksonConfig.java @@ -0,0 +1,24 @@ +package com.alttd.ctf.json_config; + +import com.alttd.ctf.json_config.serializers.component.ComponentSerializer; +import com.alttd.ctf.json_config.serializers.component.ComponentDeserializer; +import com.alttd.ctf.json_config.serializers.location.LocationDeserializer; +import com.alttd.ctf.json_config.serializers.location.LocationSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import net.kyori.adventure.text.Component; +import org.bukkit.Location; + +public class JacksonConfig { + + public static ObjectMapper configureMapper() { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule(); + module.addSerializer(Component.class, new ComponentSerializer()); + module.addDeserializer(Component.class, new ComponentDeserializer()); + module.addSerializer(Location.class, new LocationSerializer()); + module.addDeserializer(Location.class, new LocationDeserializer()); + mapper.registerModule(module); + return mapper; + } +} \ No newline at end of file diff --git a/src/main/java/com/alttd/ctf/json_config/JsonConfigManager.java b/src/main/java/com/alttd/ctf/json_config/JsonConfigManager.java new file mode 100644 index 0000000..6910870 --- /dev/null +++ b/src/main/java/com/alttd/ctf/json_config/JsonConfigManager.java @@ -0,0 +1,44 @@ +package com.alttd.ctf.json_config; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class JsonConfigManager { + + private final ObjectMapper objectMapper; + + public JsonConfigManager(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + public List loadConfigs(Class clazz, File directory) throws IOException { + List configs = new ArrayList<>(); + + if (!directory.exists() || !directory.isDirectory()) { + throw new IllegalArgumentException("Invalid directory path: " + directory.getAbsolutePath()); + } + + File[] files = directory.listFiles((dir, name) -> name.endsWith(".json")); + if (files == null) { + return configs; + } + + for (File file : files) { + T config = objectMapper.readValue(file, clazz); + + ValidationUtil.validate(config); + + configs.add(config); + } + + return configs; + } + + public void saveConfig(T object, File directory, String fileName) throws IOException { + objectMapper.writeValue(new File(directory, fileName + ".json"), object); + } +} diff --git a/src/main/java/com/alttd/ctf/json_config/ValidationUtil.java b/src/main/java/com/alttd/ctf/json_config/ValidationUtil.java new file mode 100644 index 0000000..01f0625 --- /dev/null +++ b/src/main/java/com/alttd/ctf/json_config/ValidationUtil.java @@ -0,0 +1,26 @@ +package com.alttd.ctf.json_config; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import jakarta.validation.ValidatorFactory; + +import java.util.Set; + +public class ValidationUtil { + + private static final ValidatorFactory VALIDATOR_FACTORY = Validation.buildDefaultValidatorFactory(); + private static final Validator VALIDATOR = VALIDATOR_FACTORY.getValidator(); + + public static void validate(T object) { + Set> violations = VALIDATOR.validate(object); + + if (!violations.isEmpty()) { + StringBuilder errorMessage = new StringBuilder("Validation errors:\n"); + for (ConstraintViolation violation : violations) { + errorMessage.append("- ").append(violation.getPropertyPath()).append(": ").append(violation.getMessage()).append("\n"); + } + throw new IllegalArgumentException(errorMessage.toString()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/alttd/ctf/json_config/serializers/component/ComponentDeserializer.java b/src/main/java/com/alttd/ctf/json_config/serializers/component/ComponentDeserializer.java new file mode 100644 index 0000000..99f0e08 --- /dev/null +++ b/src/main/java/com/alttd/ctf/json_config/serializers/component/ComponentDeserializer.java @@ -0,0 +1,28 @@ +package com.alttd.ctf.json_config.serializers.component; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; + +import java.io.IOException; + +public class ComponentDeserializer extends JsonDeserializer { + + @Override + public Component deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + String json = jsonParser.getText(); + try { + return GsonComponentSerializer.gson().deserialize(json); + } catch (Exception e) { + deserializationContext.reportInputMismatch( + Component.class, + "Failed to deserialize Component JSON: %s. Error: %s", + json, e.getMessage() + ); + return null; + } + } + +} diff --git a/src/main/java/com/alttd/ctf/json_config/serializers/component/ComponentSerializer.java b/src/main/java/com/alttd/ctf/json_config/serializers/component/ComponentSerializer.java new file mode 100644 index 0000000..e7eb28e --- /dev/null +++ b/src/main/java/com/alttd/ctf/json_config/serializers/component/ComponentSerializer.java @@ -0,0 +1,18 @@ +package com.alttd.ctf.json_config.serializers.component; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; + +import java.io.IOException; + +public class ComponentSerializer extends JsonSerializer { + + @Override + public void serialize(Component value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + String serialized = GsonComponentSerializer.gson().serialize(value); + gen.writeString(serialized); + } +} diff --git a/src/main/java/com/alttd/ctf/json_config/serializers/location/LocationDeserializer.java b/src/main/java/com/alttd/ctf/json_config/serializers/location/LocationDeserializer.java new file mode 100644 index 0000000..c0527e1 --- /dev/null +++ b/src/main/java/com/alttd/ctf/json_config/serializers/location/LocationDeserializer.java @@ -0,0 +1,35 @@ +package com.alttd.ctf.json_config.serializers.location; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +import java.io.IOException; + +public class LocationDeserializer extends JsonDeserializer { + + @Override + public Location deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + JsonNode node = jsonParser.getCodec().readTree(jsonParser); + try { + World world = Bukkit.getWorld(node.get("world").asText()); + double x = node.get("x").asDouble(); + double y = node.get("y").asDouble(); + double z = node.get("z").asDouble(); + float yaw = (float) node.get("yaw").asDouble(); + float pitch = (float) node.get("pitch").asDouble(); + return new Location(world, x, y, z, yaw, pitch); + } catch (Exception e) { + deserializationContext.reportInputMismatch( + Location.class, + "Failed to deserialize Component JSON: %s. Error: %s", + node.asText(), e.getMessage() + ); + return null; + } + } +} diff --git a/src/main/java/com/alttd/ctf/json_config/serializers/location/LocationSerializer.java b/src/main/java/com/alttd/ctf/json_config/serializers/location/LocationSerializer.java new file mode 100644 index 0000000..3e4396d --- /dev/null +++ b/src/main/java/com/alttd/ctf/json_config/serializers/location/LocationSerializer.java @@ -0,0 +1,23 @@ +package com.alttd.ctf.json_config.serializers.location; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import org.bukkit.Location; + +import java.io.IOException; + +public class LocationSerializer extends JsonSerializer { + + @Override + public void serialize(Location value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeStringField("world", value.getWorld().getName()); + gen.writeNumberField("x", value.getX()); + gen.writeNumberField("y", value.getY()); + gen.writeNumberField("z", value.getZ()); + gen.writeNumberField("yaw", value.getYaw()); + gen.writeNumberField("pitch", value.getPitch()); + gen.writeEndObject(); + } +} diff --git a/src/main/java/com/alttd/ctf/team/Team.java b/src/main/java/com/alttd/ctf/team/Team.java index 9cc085d..7e0c6e2 100644 --- a/src/main/java/com/alttd/ctf/team/Team.java +++ b/src/main/java/com/alttd/ctf/team/Team.java @@ -1,43 +1,40 @@ package com.alttd.ctf.team; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.minimessage.MiniMessage; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.jetbrains.annotations.NotNull; import java.util.*; @Slf4j +@AllArgsConstructor public class Team { private final HashMap players = new HashMap<>(); + @JsonProperty("name") + @NotNull @Getter private Component name; + @JsonProperty("id") @Getter private final int id; + @JsonProperty("spawnLocation") + @NotNull @Getter private Location spawnLocation; + @JsonProperty("worldBorderCenter") + @NotNull @Getter private Location worldBorderCenter; //TODO https://github.com/yannicklamprecht/WorldBorderAPI/blob/main/how-to-use.md - //TODO store team color to be used for kits and chat colors (in rgb?) + @JsonProperty("teamColor") + @NotNull @Getter private TeamColor color; - public Team(int id) { - this.id = id; - reloadTeamData(); - } - - private void reloadTeamData() { - this.color = new TeamColor(255, 0, 0, "#FF0000"); - this.name = MiniMessage.miniMessage().deserialize(String.format("Test Team", color.hex())); - this.spawnLocation = Bukkit.getWorld("world").getSpawnLocation(); - //TODO load team data from config - } - public void addPlayer(UUID uuid) { players.put(uuid, new TeamPlayer(uuid, this)); log.debug("Added player with uuid {} to team with id {}", uuid, id); diff --git a/src/main/java/com/alttd/ctf/team/TeamColor.java b/src/main/java/com/alttd/ctf/team/TeamColor.java index 695c606..f60c24d 100644 --- a/src/main/java/com/alttd/ctf/team/TeamColor.java +++ b/src/main/java/com/alttd/ctf/team/TeamColor.java @@ -1,4 +1,13 @@ package com.alttd.ctf.team; -public record TeamColor(int r, int g, int b, String hex) { +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; + +public record TeamColor( + @JsonProperty("red") @NotNull int r, + @JsonProperty("green") @NotNull int g, + @JsonProperty("blue") @NotNull int b, + @JsonProperty("hex") @NotNull @Pattern(regexp = "^#[A-Fa-f0-9]{6}$") String hex +) { }