package com.alttd.hunger_games.services; import com.alttd.hunger_games.config.Messages; import com.alttd.hunger_games.data_objects.DESTINATION; import com.alttd.hunger_games.data_objects.PLAYER_STATE; import com.alttd.hunger_games.data_objects.ROUND_STATE; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import java.util.*; public class PlayerService implements RoundListener { private static PlayerService instance = null; private final RoundService roundService; private final PlayerTeleporterService playerTeleporterService; private ROUND_STATE roundState; public PlayerService(Round round, RoundService roundService, PlayerTeleporterService playerTeleporterService) { this.roundService = roundService; this.playerTeleporterService = playerTeleporterService; this.roundState = round.register(this); } public static PlayerService createSingletonInstance(Round round, RoundService roundService, PlayerTeleporterService playerTeleporterService) { if (instance != null) { throw new IllegalStateException("PlayerService is already initialized."); } instance = new PlayerService(round, roundService, playerTeleporterService); return instance; } @Override public void stateChange(ROUND_STATE roundState) { this.roundState = roundState; switch (roundState) { case PLAYER_REGISTRATION, KILL_PHASE, SAFE_PHASE -> { //Nothing } case COUNTDOWN -> { setNonRegisteredPlayersToSpectator(); Set players = roundService.getPlayers(PLAYER_STATE.REGISTERED); Bukkit.getOnlinePlayers().stream() .filter(player -> players.contains(player.getUniqueId())) .forEach(player -> playerTeleporterService.teleportPlayer(player, DESTINATION.START_AREA)); } case FINALE -> { Set players = roundService.getPlayers(PLAYER_STATE.REGISTERED); Bukkit.getOnlinePlayers().stream() .filter(player -> players.contains(player.getUniqueId())) .forEach(player -> playerTeleporterService.teleportPlayer(player, DESTINATION.FINALE_AREA)); } case ENDED -> { roundService.clear(); Bukkit.getOnlinePlayers().forEach(player -> playerTeleporterService.teleportPlayer(player, DESTINATION.START_AREA)); } } } 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)); } public Optional registerPlayer(Player player) { if (roundState == null) { return Optional.empty(); } Optional optionalPlayerState = determinePlayerState(player.getUniqueId()); if (optionalPlayerState.isEmpty()) { return Optional.empty(); } PLAYER_STATE playerState = optionalPlayerState.get(); if (playerState == PLAYER_STATE.SPECTATING) { playerTeleporterService.teleportPlayer(player, DESTINATION.SPECTATOR_AREA); } roundService.setPlayerState(player.getUniqueId(), playerState); return optionalPlayerState; } public void handleDisconnect(Player player) { UUID uuid = player.getUniqueId(); roundService.setPlayerState(uuid, PLAYER_STATE.DISCONNECTED); } public void handleJoin(Player player) { UUID uuid = player.getUniqueId(); Optional state = roundService.getPlayerState(uuid); if (state.isEmpty()) { return; } if (state.get() != PLAYER_STATE.DISCONNECTED) { return; } roundService.setPlayerState(uuid, PLAYER_STATE.SPECTATING); player.sendRichMessage(Messages.RECONNECT.FORFEITED); } public void handlePlayerDeath(Player player) { UUID uuid = player.getUniqueId(); roundService.setPlayerState(uuid, PLAYER_STATE.SPECTATING); int remaining = roundService.getPlayers(PLAYER_STATE.REGISTERED).size(); Bukkit.broadcast(MiniMessage.miniMessage().deserialize(Messages.GAME.PLAYER_DEATH, Placeholder.component("player", player.name()), Placeholder.unparsed("remaining", String.valueOf(remaining)))); } public void handlePlayerRespawn(Player player) { roundService.getPlayerState(player.getUniqueId()) .filter(state -> state == PLAYER_STATE.SPECTATING) .ifPresent(state -> playerTeleporterService.teleportPlayer(player, DESTINATION.SPECTATOR_AREA)); } 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 REGISTERED -> PLAYER_STATE.REGISTERED; }); } return switch (roundState) { case PLAYER_REGISTRATION, COUNTDOWN -> Optional.of(PLAYER_STATE.REGISTERED); case KILL_PHASE, FINALE, ENDED, SAFE_PHASE -> Optional.of(PLAYER_STATE.SPECTATING); }; } }