diff --git a/src/main/java/com/alttd/hunger_games/Main.java b/src/main/java/com/alttd/hunger_games/Main.java index 1418ff4..eabaed3 100644 --- a/src/main/java/com/alttd/hunger_games/Main.java +++ b/src/main/java/com/alttd/hunger_games/Main.java @@ -3,6 +3,7 @@ package com.alttd.hunger_games; import com.alttd.hunger_games.commands.BaseCommand; import com.alttd.hunger_games.config.Config; import com.alttd.hunger_games.config.Messages; +import com.alttd.hunger_games.services.PlayerService; import com.alttd.hunger_games.services.Round; import com.alttd.hunger_games.services.RoundService; import lombok.extern.slf4j.Slf4j; @@ -12,9 +13,8 @@ import org.bukkit.plugin.java.JavaPlugin; @Slf4j public final class Main extends JavaPlugin { - private BaseCommand command; - private Round round; private RoundService roundService; + private PlayerService playerService; @Override public void onEnable() { @@ -27,8 +27,9 @@ public final class Main extends JavaPlugin { } private void registerServices() { - round = Round.createSingletonInstance(); + Round round = Round.createSingletonInstance(); roundService = new RoundService(round); + playerService = new PlayerService(roundService); } @Override @@ -37,7 +38,7 @@ public final class Main extends JavaPlugin { } private void registerCommands() { - command = new BaseCommand(this, roundService); + BaseCommand command = new BaseCommand(this, roundService, playerService); } private void registerEvents() { diff --git a/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java b/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java index 3a99082..529a75e 100644 --- a/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java +++ b/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java @@ -1,8 +1,10 @@ package com.alttd.hunger_games.commands; import com.alttd.hunger_games.Main; +import com.alttd.hunger_games.commands.subcommands.Register; import com.alttd.hunger_games.commands.subcommands.RoundState; import com.alttd.hunger_games.config.Messages; +import com.alttd.hunger_games.services.PlayerService; import com.alttd.hunger_games.services.RoundService; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -19,7 +21,7 @@ import java.util.stream.Collectors; public class BaseCommand implements CommandExecutor, TabExecutor { private final List subCommands; - public BaseCommand(Main main, RoundService roundService) { + public BaseCommand(Main main, RoundService roundService, PlayerService playerService) { PluginCommand command = main.getCommand("hungergames"); if (command == null) { subCommands = null; @@ -31,8 +33,9 @@ public class BaseCommand implements CommandExecutor, TabExecutor { command.setAliases(List.of("hg")); subCommands = new ArrayList<>(List.of( - new RoundState(roundService) - )); + new RoundState(roundService), + new Register(playerService) + )); } @Override diff --git a/src/main/java/com/alttd/hunger_games/commands/subcommands/Register.java b/src/main/java/com/alttd/hunger_games/commands/subcommands/Register.java new file mode 100644 index 0000000..891a286 --- /dev/null +++ b/src/main/java/com/alttd/hunger_games/commands/subcommands/Register.java @@ -0,0 +1,110 @@ +package com.alttd.hunger_games.commands.subcommands; + +import com.alttd.hunger_games.commands.SubCommand; +import com.alttd.hunger_games.commands.shared_parsers.OnlinePlayerParser; +import com.alttd.hunger_games.config.Messages; +import com.alttd.hunger_games.data_objects.PLAYER_STATE; +import com.alttd.hunger_games.services.PlayerService; +import lombok.extern.slf4j.Slf4j; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Optional; + +@Slf4j +public class Register extends SubCommand { + + private final static OnlinePlayerParser ONLINE_PLAYER_PARSER = new OnlinePlayerParser(); + private final static int PLAYER_ARG = 1; + private final PlayerService playerService; + + public Register(PlayerService playerService) { + this.playerService = playerService; + } + + @Override + public boolean onCommand(CommandSender commandSender, String[] args) { + if (args.length != 2) { + return false; + } + + Optional optionalPlayer = ONLINE_PLAYER_PARSER.parse(commandSender, args[PLAYER_ARG]); + if (optionalPlayer.isEmpty()) { + return true; + } + + Player playerToRegister = optionalPlayer.get(); + Optional optionalPlayerState = playerService.registerPlayer(playerToRegister); + PLAYER_STATE nullablePlayerState = optionalPlayerState.orElse(null); + if (optionalPlayerState.isEmpty()) { + playerToRegister.sendRichMessage(Messages.REGISTER.FAILED_TO_REGISTER_YOU); + } else { + notifyRegisteredPlayer(playerToRegister, nullablePlayerState); + } + + if (commandSender instanceof Player commandPlayer) { + notifyPlayerCommandSender(commandPlayer, nullablePlayerState, playerToRegister); + } + logResult(nullablePlayerState, playerToRegister); + return true; + } + + private void notifyRegisteredPlayer(Player playerToRegister, PLAYER_STATE nullablePlayerState) { + switch (nullablePlayerState) { + case REGISTERED -> playerToRegister.sendRichMessage(Messages.REGISTER.SUCCESSFUL_REGISTER); + case SPECTATING -> playerToRegister.sendRichMessage(Messages.REGISTER.GAME_RUNNING); + } + } + + private void logResult(PLAYER_STATE nullablePlayerState, Player playerToRegister) { + if (nullablePlayerState == null) { + log.info("Failed to register player {}", playerToRegister.getName()); + return; + } + + switch (nullablePlayerState) { + case REGISTERED -> log.info("Registered player {} for the next round", playerToRegister.getName()); + case IN_GAME -> log.info("Player {} is already in a round", playerToRegister.getName()); + case DISCONNECTED -> log.info("Player {} is disconnected (should not be possible)", playerToRegister.getName()); + case SPECTATING -> log.info("Player {} is now spectating the game", playerToRegister.getName()); + } + } + + private static void notifyPlayerCommandSender(Player commandPlayer, @Nullable PLAYER_STATE playerState, Player playerToRegister) { + if (playerState == null) { + commandPlayer.sendRichMessage(Messages.REGISTER.FAILED_TO_REGISTER_PLAYER, + Placeholder.component("player", playerToRegister.name())); + return; + } + + switch (playerState) { + case REGISTERED -> commandPlayer.sendRichMessage(Messages.REGISTER.PLAYER_REGISTERED, + Placeholder.component("player", playerToRegister.name())); + case IN_GAME -> commandPlayer.sendRichMessage(Messages.REGISTER.PLAYER_ALREADY_IN_ROUND, + Placeholder.component("player", playerToRegister.name())); + case DISCONNECTED -> { + //should not be possible + } + case SPECTATING -> commandPlayer.sendRichMessage(Messages.REGISTER.PLAYER_SPECTATING, + Placeholder.component("player", playerToRegister.name())); + } + } + + @Override + public String getName() { + return "register"; + } + + @Override + public List getTabComplete(CommandSender commandSender, String[] args) { + return List.of(); + } + + @Override + public String getHelpMessage() { + return Messages.HELP.REGISTER; + } +} diff --git a/src/main/java/com/alttd/hunger_games/config/Messages.java b/src/main/java/com/alttd/hunger_games/config/Messages.java index 39823ce..6c7489b 100644 --- a/src/main/java/com/alttd/hunger_games/config/Messages.java +++ b/src/main/java/com/alttd/hunger_games/config/Messages.java @@ -69,11 +69,21 @@ public class Messages extends AbstractConfig { public static String FAILED_TO_REGISTER_YOU = "You were unable to join HungerGames because no HungerGames round was found"; public static String FAILED_TO_REGISTER_PLAYER = "Unable to register player "; + public static String PLAYER_REGISTERED = "Registered for the game"; + public static String PLAYER_ALREADY_IN_ROUND = " is already in a round"; + public static String PLAYER_SPECTATING = " is now spectating the game"; + public static String SUCCESSFUL_REGISTER = "Successfully registered you for the upcoming Hunger Games round"; + public static String GAME_RUNNING = "The game is currently running, you will need to spectate the current round"; @SuppressWarnings("unused") private static void load() { FAILED_TO_REGISTER_YOU = config.getString(prefix, "failed", FAILED_TO_REGISTER_YOU); FAILED_TO_REGISTER_PLAYER = config.getString(prefix, "failed-player", FAILED_TO_REGISTER_PLAYER); + PLAYER_REGISTERED = config.getString(prefix, "player-registered", PLAYER_REGISTERED); + PLAYER_ALREADY_IN_ROUND = config.getString(prefix, "player-already-in-game", PLAYER_ALREADY_IN_ROUND); + PLAYER_SPECTATING = config.getString(prefix, "player-spectating", PLAYER_SPECTATING); + SUCCESSFUL_REGISTER = config.getString(prefix, "successful", SUCCESSFUL_REGISTER); + GAME_RUNNING = config.getString(prefix, "game-running", GAME_RUNNING); } } } diff --git a/src/main/java/com/alttd/hunger_games/services/PlayerService.java b/src/main/java/com/alttd/hunger_games/services/PlayerService.java index 45043c0..85f4bcb 100644 --- a/src/main/java/com/alttd/hunger_games/services/PlayerService.java +++ b/src/main/java/com/alttd/hunger_games/services/PlayerService.java @@ -3,9 +3,10 @@ package com.alttd.hunger_games.services; import com.alttd.hunger_games.data_objects.PLAYER_STATE; import com.alttd.hunger_games.data_objects.ROUND_STATE; import lombok.RequiredArgsConstructor; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import java.util.Optional; +import java.util.*; @RequiredArgsConstructor public class PlayerService implements RoundListener { @@ -16,29 +17,70 @@ public class PlayerService implements RoundListener { @Override public void stateChange(ROUND_STATE roundState) { this.roundState = roundState; - //TODO: Implement player state change logic + switch (roundState) { + case PLAYER_REGISTRATION, KILL_PHASE -> { + //Nothing + } + case COUNTDOWN -> { + setNonRegisteredPlayersToSpectator(); + //TODO: teleport players to spawn location + } + case FINALE -> { + //TODO: teleport players to finale location + } + case ENDED -> { + roundService.clear(); + //TODO: teleport everyone to spawn (or spectator?) location + } + } + } + + private void setNonRegisteredPlayersToSpectator() { + Set playerUUIDs = roundService.getPlayers(PLAYER_STATE.REGISTERED); + List playerList = new ArrayList<>(Bukkit.getOnlinePlayers()); + List unregisteredPlayers = playerList.stream().filter(player -> !playerUUIDs.contains(player.getUniqueId())).toList(); + unregisteredPlayers.forEach(player -> roundService.setPlayerState(player.getUniqueId(), PLAYER_STATE.SPECTATING)); } @Override public void roundReset() { - //TODO: Implement player reset logic + //TODO: teleport everyone to spawn (or spectator?) location (from where they can join the game) } public Optional registerPlayer(Player player) { if (roundState == null) { return Optional.empty(); } - switch (roundState) { - case PLAYER_REGISTRATION -> { - } - case COUNTDOWN -> { - } - case KILL_PHASE -> { - } - case FINALE -> { - } - case ENDED -> { - } + Optional optionalPlayerState = determinePlayerState(player.getUniqueId()); + if (optionalPlayerState.isEmpty()) { + return Optional.empty(); } + PLAYER_STATE playerState = optionalPlayerState.get(); + + if (playerState == PLAYER_STATE.SPECTATING) { + //TODO: teleport player to spectator location + } + + roundService.setPlayerState(player.getUniqueId(), playerState); + return optionalPlayerState; + } + + private Optional determinePlayerState(UUID playerUuid) { + if (roundState == null) { + return Optional.empty(); + } + Optional optionalPlayerState = roundService.getPlayerState(playerUuid); + if (optionalPlayerState.isPresent()) { + PLAYER_STATE playerState = optionalPlayerState.get(); + return Optional.of(switch (playerState) { + case DISCONNECTED, SPECTATING -> PLAYER_STATE.SPECTATING; + case IN_GAME -> PLAYER_STATE.IN_GAME; + case REGISTERED -> PLAYER_STATE.REGISTERED; + }); + } + return switch (roundState) { + case PLAYER_REGISTRATION, COUNTDOWN -> Optional.of(PLAYER_STATE.REGISTERED); + case KILL_PHASE, FINALE, ENDED -> Optional.of(PLAYER_STATE.SPECTATING); + }; } } diff --git a/src/main/java/com/alttd/hunger_games/services/RoundService.java b/src/main/java/com/alttd/hunger_games/services/RoundService.java index a2addef..c4f499e 100644 --- a/src/main/java/com/alttd/hunger_games/services/RoundService.java +++ b/src/main/java/com/alttd/hunger_games/services/RoundService.java @@ -5,10 +5,7 @@ import com.alttd.hunger_games.data_objects.ROUND_STATE; import lombok.Getter; import org.bukkit.entity.Player; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; public class RoundService implements RoundListener { @@ -32,8 +29,12 @@ public class RoundService implements RoundListener { players.put(uuid, playerState); } - public PLAYER_STATE getPlayerState(UUID uuid) { - return players.get(uuid); + protected void clear() { + players.clear(); + } + + public Optional getPlayerState(UUID uuid) { + return Optional.ofNullable(players.get(uuid)); } @Override @@ -43,7 +44,7 @@ public class RoundService implements RoundListener { @Override public void roundReset() { - players.clear(); + clear(); roundState = null; } }