2026-05-23 22:13:25 +00:00
|
|
|
package com.alttd.hunger_games.services;
|
|
|
|
|
|
2026-06-15 19:00:43 +00:00
|
|
|
import com.alttd.hunger_games.Main;
|
2026-06-15 21:17:47 +00:00
|
|
|
import com.alttd.hunger_games.config.Messages;
|
2026-06-27 20:02:05 +00:00
|
|
|
import com.alttd.hunger_games.data_objects.DESTINATION;
|
2026-06-27 20:17:50 +00:00
|
|
|
import com.alttd.hunger_games.data_objects.GameStage;
|
2026-05-23 22:13:25 +00:00
|
|
|
import com.alttd.hunger_games.data_objects.PLAYER_STATE;
|
|
|
|
|
import com.alttd.hunger_games.data_objects.ROUND_STATE;
|
2026-06-15 19:00:43 +00:00
|
|
|
import com.alttd.hunger_games.event_listeners.PlayerMovementListener;
|
2026-06-27 20:32:43 +00:00
|
|
|
import com.alttd.hunger_games.utils.WorldBorderUtil;
|
2026-05-23 22:13:25 +00:00
|
|
|
import lombok.Getter;
|
2026-06-27 20:02:05 +00:00
|
|
|
import lombok.Setter;
|
2026-06-15 21:17:47 +00:00
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import net.kyori.adventure.text.minimessage.MiniMessage;
|
|
|
|
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
2026-06-15 19:00:43 +00:00
|
|
|
import org.bukkit.Bukkit;
|
2026-06-27 20:02:05 +00:00
|
|
|
import org.bukkit.GameMode;
|
2026-06-15 19:00:43 +00:00
|
|
|
import org.bukkit.entity.Player;
|
|
|
|
|
import org.bukkit.event.HandlerList;
|
2026-05-23 22:13:25 +00:00
|
|
|
|
2026-05-23 22:58:27 +00:00
|
|
|
import java.util.*;
|
2026-05-23 22:13:25 +00:00
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
2026-06-15 21:17:47 +00:00
|
|
|
@Slf4j
|
2026-05-23 22:13:25 +00:00
|
|
|
public class RoundService implements RoundListener {
|
|
|
|
|
|
2026-05-29 22:03:32 +00:00
|
|
|
private static RoundService instance = null;
|
2026-06-27 20:02:05 +00:00
|
|
|
private final PlayerTeleporterService playerTeleporterService;
|
2026-06-15 19:00:43 +00:00
|
|
|
private final Main main;
|
2026-06-15 20:13:51 +00:00
|
|
|
private final LootService lootService;
|
2026-06-15 20:56:27 +00:00
|
|
|
private final StatService statService;
|
2026-06-27 20:32:43 +00:00
|
|
|
private PlayerMovementListener playerMovementListener;
|
2026-05-29 22:03:32 +00:00
|
|
|
|
2026-05-23 22:13:25 +00:00
|
|
|
@Getter
|
|
|
|
|
private ROUND_STATE roundState;
|
|
|
|
|
private final HashMap<UUID, PLAYER_STATE> players = new HashMap<>();
|
|
|
|
|
|
2026-06-15 21:17:47 +00:00
|
|
|
private final Round round;
|
2026-06-27 20:02:05 +00:00
|
|
|
@Setter
|
2026-06-22 00:02:42 +00:00
|
|
|
private BossBarService bossBarService;
|
2026-06-15 21:17:47 +00:00
|
|
|
|
2026-06-27 20:02:05 +00:00
|
|
|
public static RoundService createSingletonInstance(Round round, Main main, LootService lootService, StatService statService, PlayerTeleporterService playerTeleporterService) {
|
2026-05-29 22:03:32 +00:00
|
|
|
if (instance != null) {
|
|
|
|
|
throw new IllegalStateException("RoundService is already initialized.");
|
|
|
|
|
}
|
2026-06-27 20:02:05 +00:00
|
|
|
instance = new RoundService(round, main, lootService, statService, playerTeleporterService);
|
2026-05-29 22:03:32 +00:00
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-27 20:02:05 +00:00
|
|
|
private RoundService(Round round, Main main, LootService lootService, StatService statService, PlayerTeleporterService playerTeleporterService) {
|
2026-06-15 21:17:47 +00:00
|
|
|
this.round = round;
|
2026-05-23 22:13:25 +00:00
|
|
|
this.roundState = round.register(this);
|
2026-06-15 19:00:43 +00:00
|
|
|
this.main = main;
|
2026-06-15 20:13:51 +00:00
|
|
|
this.lootService = lootService;
|
2026-06-15 20:56:27 +00:00
|
|
|
this.statService = statService;
|
2026-06-27 20:02:05 +00:00
|
|
|
this.playerTeleporterService = playerTeleporterService;
|
2026-05-23 22:13:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Set<UUID> getPlayers(PLAYER_STATE playerState) {
|
|
|
|
|
return players.entrySet().stream()
|
|
|
|
|
.filter(entry -> entry.getValue().equals(playerState))
|
|
|
|
|
.map(Map.Entry::getKey)
|
|
|
|
|
.collect(Collectors.toSet());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void setPlayerState(UUID uuid, PLAYER_STATE playerState) {
|
2026-06-15 20:56:27 +00:00
|
|
|
PLAYER_STATE oldState = players.put(uuid, playerState);
|
|
|
|
|
if (playerState == PLAYER_STATE.SPECTATING && oldState == PLAYER_STATE.REGISTERED) {
|
|
|
|
|
int remaining = getPlayers(PLAYER_STATE.REGISTERED).size();
|
|
|
|
|
statService.setPlacement(uuid, remaining + 1);
|
2026-06-22 00:02:42 +00:00
|
|
|
if (roundState == ROUND_STATE.FINALE && bossBarService != null) {
|
|
|
|
|
bossBarService.updateFinale(remaining);
|
|
|
|
|
}
|
2026-06-15 20:56:27 +00:00
|
|
|
}
|
|
|
|
|
|
2026-06-15 19:00:43 +00:00
|
|
|
if (!roundState.equals(ROUND_STATE.KILL_PHASE) && !roundState.equals(ROUND_STATE.FINALE)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
Set<UUID> uuidSet = getPlayers(PLAYER_STATE.REGISTERED);
|
|
|
|
|
if (uuidSet.size() != 1) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
declareWinner(uuidSet.iterator().next());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void declareWinner(UUID winnerUUID) {
|
|
|
|
|
Player player = Bukkit.getPlayer(winnerUUID);
|
2026-06-15 21:17:47 +00:00
|
|
|
if (player == null) {
|
|
|
|
|
log.error("Winner {} not found", winnerUUID);
|
|
|
|
|
Bukkit.broadcast(MiniMessage.miniMessage().deserialize("<red>Winner not found</red>"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-15 20:56:27 +00:00
|
|
|
statService.setPlacement(winnerUUID, 1);
|
|
|
|
|
statService.setWon(winnerUUID, true);
|
2026-06-15 21:17:47 +00:00
|
|
|
|
|
|
|
|
Bukkit.broadcast(MiniMessage.miniMessage().deserialize(Messages.GAME.WINNER, Placeholder.component("player", player.name())));
|
2026-06-27 20:02:05 +00:00
|
|
|
playerTeleporterService.teleportPlayer(player, DESTINATION.SPECTATOR_AREA);
|
|
|
|
|
player.setHealth(20);
|
|
|
|
|
player.setFoodLevel(20);
|
|
|
|
|
player.getInventory().clear();
|
2026-06-27 21:57:07 +00:00
|
|
|
player.setTotalExperience(0);
|
|
|
|
|
player.setExp(0.0f);
|
2026-06-27 20:32:43 +00:00
|
|
|
player.setLevel(0);
|
2026-06-15 21:17:47 +00:00
|
|
|
round.endRound();
|
2026-05-23 22:13:25 +00:00
|
|
|
}
|
|
|
|
|
|
2026-05-23 22:58:27 +00:00
|
|
|
protected void clear() {
|
|
|
|
|
players.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Optional<PLAYER_STATE> getPlayerState(UUID uuid) {
|
|
|
|
|
return Optional.ofNullable(players.get(uuid));
|
2026-05-23 22:13:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void stateChange(ROUND_STATE roundState) {
|
|
|
|
|
this.roundState = roundState;
|
2026-06-15 19:00:43 +00:00
|
|
|
stopFreeze();
|
2026-05-23 23:30:11 +00:00
|
|
|
if (roundState.equals(ROUND_STATE.PLAYER_REGISTRATION)) {
|
|
|
|
|
clear();
|
2026-06-15 20:13:51 +00:00
|
|
|
lootService.clear();
|
2026-05-23 23:30:11 +00:00
|
|
|
}
|
2026-06-15 19:00:43 +00:00
|
|
|
if (roundState.equals(ROUND_STATE.COUNTDOWN)) {
|
2026-06-27 20:02:05 +00:00
|
|
|
Bukkit.getOnlinePlayers().stream()
|
|
|
|
|
.filter(player -> PLAYER_STATE.REGISTERED.equals(getPlayerState(player.getUniqueId()).orElse(null)))
|
|
|
|
|
.forEach(player -> {
|
|
|
|
|
player.setHealth(20);
|
|
|
|
|
player.setFoodLevel(20);
|
|
|
|
|
player.setGameMode(GameMode.SURVIVAL);
|
|
|
|
|
player.getInventory().clear();
|
2026-06-27 21:57:07 +00:00
|
|
|
player.setTotalExperience(0);
|
|
|
|
|
player.setExp(0.0f);
|
|
|
|
|
player.setLevel(0);
|
2026-06-27 20:02:05 +00:00
|
|
|
});
|
2026-06-15 19:00:43 +00:00
|
|
|
startFreeze();
|
2026-06-27 20:32:43 +00:00
|
|
|
WorldBorderUtil.resetBorder();
|
2026-06-15 19:00:43 +00:00
|
|
|
}
|
2026-06-27 20:32:43 +00:00
|
|
|
if (roundState.equals(ROUND_STATE.FINALE)) {
|
2026-06-27 22:35:39 +00:00
|
|
|
WorldBorderUtil.setSize(60);
|
2026-06-27 20:32:43 +00:00
|
|
|
}
|
2026-06-28 00:19:28 +00:00
|
|
|
if (!roundState.equals(ROUND_STATE.ENDED) && !roundState.equals(ROUND_STATE.PLAYER_REGISTRATION)) {
|
2026-06-27 20:32:43 +00:00
|
|
|
Bukkit.broadcast(MiniMessage.miniMessage().deserialize(Messages.GAME.NEXT_STATE, Placeholder.parsed("round", roundState.getHumanReadableName())));
|
2026-06-27 20:17:50 +00:00
|
|
|
}
|
2026-06-15 19:00:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void stopFreeze() {
|
|
|
|
|
if (playerMovementListener == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
HandlerList.unregisterAll(playerMovementListener);
|
|
|
|
|
playerMovementListener = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void startFreeze() {
|
|
|
|
|
stopFreeze();
|
|
|
|
|
Set<UUID> uuidSet = getPlayers(PLAYER_STATE.REGISTERED);
|
|
|
|
|
playerMovementListener = new PlayerMovementListener(uuidSet);
|
|
|
|
|
main.getServer().getPluginManager().registerEvents(playerMovementListener, main);
|
2026-05-23 22:13:25 +00:00
|
|
|
}
|
2026-06-22 00:02:42 +00:00
|
|
|
|
2026-05-23 22:13:25 +00:00
|
|
|
}
|