Compare commits

..

No commits in common. "400032a94cdb39d24b37c98b65f30d42424ba1d1" and "56455b4c50e24cda69b4389b90efb93075480e69" have entirely different histories.

15 changed files with 52 additions and 145 deletions

View File

@ -58,7 +58,7 @@ public class ChangeTeam extends SubCommand {
}
private void changeTeam(CommandSender commandSender, Player player, Team team) {
Optional<Team> optionalOldTeam = gameManager.getTeam(player);
Optional<Team> optionalOldTeam = gameManager.getTeam(player.getUniqueId());
if (optionalOldTeam.isPresent()) {
moveBetweenTeams(commandSender, player, team, optionalOldTeam.get());
return;

View File

@ -12,7 +12,6 @@ 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.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -76,8 +75,7 @@ public class CreateTeam extends SubCommand {
int highestId = gameManager.getMaxTeamId();
Team team = new Team(MiniMessage.miniMessage().deserialize(String.format("<color:%s>%s</color>", color, name)),
highestId + 1, player.getLocation(), player.getLocation(), player.getLocation(), teamColor,
Material.RED_BANNER, "§c");
highestId + 1, player.getLocation(), player.getLocation(), player.getLocation(), teamColor);
return consumer.apply(team);
}

View File

@ -40,7 +40,7 @@ public class SelectClass extends SubCommand {
return 0;
}
GamePhase gamePhase = optionalGamePhase.get();
Optional<TeamPlayer> optionalTeamPlayer = gameManager.getTeamPlayer(player);
Optional<TeamPlayer> optionalTeamPlayer = gameManager.getTeamPlayer(player.getUniqueId());
if (optionalTeamPlayer.isEmpty()) {
commandSender.sendRichMessage("<red>You have to be in a CTF team to select a class.</red>");
return 0;

View File

@ -3,9 +3,6 @@ package com.alttd.ctf.config;
import com.alttd.ctf.Main;
import com.alttd.ctf.game.GamePhase;
import lombok.extern.slf4j.Slf4j;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.time.Duration;
import java.util.HashMap;
@ -91,7 +88,6 @@ public class GameConfig extends AbstractConfig {
public static double CAPTURE_RADIUS = 5;
public static int CAPTURE_SCORE = 50;
public static double TURN_IN_RADIUS = 3;
public static @NotNull Material MATERIAL = Material.RED_BANNER;
@SuppressWarnings("unused")
private static void load() {
@ -102,7 +98,6 @@ public class GameConfig extends AbstractConfig {
CAPTURE_RADIUS = config.getDouble(prefix, "capture-radius", CAPTURE_RADIUS);
CAPTURE_SCORE = config.getInt(prefix, "capture-score", CAPTURE_SCORE);
TURN_IN_RADIUS = config.getDouble(prefix, "turn-in-radius", TURN_IN_RADIUS);
MATERIAL = Material.valueOf(config.getString(prefix, "material", MATERIAL.toString()));
}
}

View File

@ -3,9 +3,6 @@ package com.alttd.ctf.events;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerAttemptPickupItemEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
@ -29,20 +26,4 @@ public class InventoryItemInteractionEvent implements Listener {
event.setCancelled(true);
}
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
if (event.getSlotType() != InventoryType.SlotType.ARMOR) {
return;
}
event.setCancelled(true);
}
@EventHandler
public void onInventoryDrag(InventoryDragEvent event) {
if (event.getRawSlots().stream().noneMatch(slot -> slot >= 5 && slot <= 8)) { // Slot numbers 5-8 for armor
return;
}
event.setCancelled(true);
}
}

View File

@ -55,7 +55,7 @@ public class OnPlayerDeath implements Listener {
log.warn("Player {} died while the game wasn't running", player.getName());
return;
}
Optional<TeamPlayer> optionalTeamPlayer = gameManager.getTeamPlayer(player);
Optional<TeamPlayer> optionalTeamPlayer = gameManager.getTeamPlayer(player.getUniqueId());
if (optionalTeamPlayer.isEmpty()) {
return;
}

View File

@ -51,7 +51,7 @@ public class OnPlayerOnlineStatus implements Listener {
if (gamePhase.equals(GamePhase.ENDED)) {
return;
}
Optional<TeamPlayer> optionalTeamPlayer = gameManager.getTeamPlayer(player);
Optional<TeamPlayer> optionalTeamPlayer = gameManager.getTeamPlayer(player.getUniqueId());
TeamPlayer teamPlayer;
if (optionalTeamPlayer.isEmpty()) {
Optional<Team> min = gameManager.getTeams().stream().min(Comparator.comparingInt(team -> team.getPlayers().size()));
@ -59,7 +59,7 @@ public class OnPlayerOnlineStatus implements Listener {
log.error("No team found when attempting to add freshly joined player to a team");
return;
}
teamPlayer = min.get().addPlayer(player);
teamPlayer = min.get().addPlayer(player.getUniqueId());
} else {
teamPlayer = optionalTeamPlayer.get();
}

View File

@ -89,7 +89,7 @@ public class SnowballEvent implements Listener {
return;
}
Optional<TeamPlayer> teamPlayer = gameManager.getTeamPlayer(shooter);
Optional<TeamPlayer> teamPlayer = gameManager.getTeamPlayer(shooter.getUniqueId());
if (teamPlayer.isEmpty()) {
log.debug("The shooter that threw a snowball was not a team player");
return;
@ -100,14 +100,13 @@ public class SnowballEvent implements Listener {
private void handleSnowballHit(EntityDamageByEntityEvent event, SnowballHitConsumer consumer) {
Optional<GamePhase> optionalGamePhase = gameManager.getGamePhase();
if (optionalGamePhase.isEmpty()) {
log.debug("No game is running but player was hit");
log.debug("No game is running but player was hit by snowball");
return;
}
GamePhase gamePhase = optionalGamePhase.get();
if (!gamePhase.equals(GamePhase.COMBAT)) {
log.debug("Not in combat phase but player was hit, cancelling event");
event.setCancelled(true);
log.debug("Not in combat phase but player was hit by snowball");
return;
}
@ -117,8 +116,7 @@ public class SnowballEvent implements Listener {
}
if (!(event.getDamager() instanceof org.bukkit.entity.Snowball snowball)) {
log.debug("The player was hit by something other than a snowball, canceling event");
event.setCancelled(true);
log.debug("The player was hit by something other than a snowball");
return;
}
@ -127,13 +125,13 @@ public class SnowballEvent implements Listener {
return;
}
Optional<TeamPlayer> teamPlayerShooter = gameManager.getTeamPlayer(shooter);
Optional<TeamPlayer> teamPlayerShooter = gameManager.getTeamPlayer(shooter.getUniqueId());
if (teamPlayerShooter.isEmpty()) {
log.debug("The shooter that hit a player with a snowball was not a team player");
return;
}
Optional<TeamPlayer> teamPlayerHit = gameManager.getTeamPlayer(hitPlayer);
Optional<TeamPlayer> teamPlayerHit = gameManager.getTeamPlayer(hitPlayer.getUniqueId());
if (teamPlayerHit.isEmpty()) {
log.debug("The shooter that hit a player with a snowball was not a team player");
return;

View File

@ -33,6 +33,7 @@ public class Flag implements Runnable {
private static final MiniMessage miniMessage = MiniMessage.miniMessage();
private final HashMap<Integer, Integer> teamFlagPointCount = new HashMap<>();
private final ItemStack flagItem = new ItemStack(Material.BLACK_BANNER);
private final BossBar bossBar = createBossBar();
private final HashMap<Integer, Integer> wins = new HashMap<>();
private int lastWinningTeamId = -1;
@ -52,7 +53,6 @@ public class Flag implements Runnable {
throw new IllegalStateException(String.format("Tried to spawn flag in world [%s] that doesn't exist", GameConfig.FLAG.world));
}
this.flagLocation = new Location(world, GameConfig.FLAG.x, GameConfig.FLAG.y, GameConfig.FLAG.z);
gameManager.getTeams().forEach(team -> team.setScore(0));
}
private BossBar createBossBar() {
@ -80,15 +80,15 @@ public class Flag implements Runnable {
}
//TODO knockback enemies from flag location to create space for person who captured mayb short speed boost and heal?
//TODO add de-buffs and enable buffs for others?
player.getInventory().setItem(EquipmentSlot.HEAD, new ItemStack(teamPlayer.getTeam().getFlagMaterial()));
player.getInventory().setItem(EquipmentSlot.HEAD, flagItem);
Bukkit.getScheduler().runTask(main, () -> flagLocation.getBlock().setType(Material.AIR));
flagCarrier = player;
notifyAboutCapture();
resetFlag();
}
public void spawnFlag(Material material) {
Bukkit.getScheduler().runTask(main, () -> flagLocation.getBlock().setType(material));
public void spawnFlag() {
Bukkit.getScheduler().runTask(main, () -> flagLocation.getBlock().setType(flagItem.getType()));
}
private void spawnFlagParticleRing() {
@ -141,7 +141,7 @@ public class Flag implements Runnable {
updateDisplay();
} else {
winningTeam = optionalTeam.get();
spawnFlag(winningTeam.getFlagMaterial());
resetFlag();
//TODO stop capture and let ppl know they can now capture the flag
}
}
@ -159,7 +159,7 @@ public class Flag implements Runnable {
miniMessage.deserialize("<red>kill <player> before they bring it to their base.</red>",
Placeholder.component("player", flagCarrier.displayName())));
Bukkit.getOnlinePlayers().forEach(player ->
gameManager.getTeam(player).ifPresent(team ->
gameManager.getTeam(player.getUniqueId()).ifPresent(team ->
player.showTitle(team.getId() == winningTeam.getId() ? capturingTeamTitle : huntingTeamTitle)));
}
@ -194,10 +194,9 @@ public class Flag implements Runnable {
private void checkFlagCarrier() {
if (flagCarrier.isDead() || !flagCarrier.isOnline()) {
resetFlagCarrier();
spawnFlag(GameConfig.FLAG.MATERIAL);
spawnFlag();
return;
}
double distance = winningTeam.getFlagTurnInLocation().distance(flagCarrier.getLocation());
if (distance > GameConfig.FLAG.TURN_IN_RADIUS) {
Location location = flagCarrier.getLocation();
@ -207,17 +206,18 @@ public class Flag implements Runnable {
spawnParticlesOnSquareBorder(winningTeam.getFlagTurnInLocation(), GameConfig.FLAG.TURN_IN_RADIUS);
return;
}
notifyAboutTurnIn();
spawnFlag(GameConfig.FLAG.MATERIAL);
spawnFlag();
wins.merge(winningTeam.getId(), 1, Integer::sum);
wins.forEach((id, score) -> gameManager.getTeam(id).ifPresent(team -> team.setScore(score)));
winningTeam = null;
Optional<TeamPlayer> optionalTeamPlayer = gameManager.getTeamPlayer(flagCarrier.getUniqueId());
if (optionalTeamPlayer.isEmpty()) {
flagCarrier.getInventory().setItem(EquipmentSlot.HEAD, null);
gameManager.getTeamPlayer(flagCarrier)
.ifPresent(teamPlayer -> teamPlayer.getGameClass().setArmor(flagCarrier, teamPlayer));
} else {
TeamPlayer teamPlayer = optionalTeamPlayer.get();
teamPlayer.getGameClass().setArmor(flagCarrier, teamPlayer);
flagCarrier.getInventory().setItem(EquipmentSlot.HEAD, null);
}
resetFlagCarrier();
}
@ -276,7 +276,7 @@ public class Flag implements Runnable {
*/
private boolean updateScoreBasedOnNearbyPlayers(Collection<Player> players) {
List<TeamPlayer> nearbyPlayers = players.stream()
.map(gameManager::getTeamPlayer)
.map(player -> gameManager.getTeamPlayer(player.getUniqueId()))
.filter(Optional::isPresent)
.map(Optional::get)
.toList();
@ -377,8 +377,8 @@ public class Flag implements Runnable {
return;
}
resetFlagCarrier();
spawnFlag(GameConfig.FLAG.MATERIAL);
gameManager.getTeam(player)
spawnFlag();
gameManager.getTeam(player.getUniqueId())
.ifPresentOrElse(team -> Bukkit.broadcast(MiniMessage.miniMessage()
.deserialize("<red><team>'s flag carrier died! The flag has respawned",
Placeholder.component("team", team.getName()))),

View File

@ -37,7 +37,7 @@ public class FlagTryCaptureEvent implements Listener {
return;
}
Player player = event.getPlayer();
Optional<TeamPlayer> teamPlayer = winningTeam.getPlayer(player);
Optional<TeamPlayer> teamPlayer = winningTeam.getPlayer(player.getUniqueId());
if (teamPlayer.isEmpty()) {
return;
}

View File

@ -39,11 +39,11 @@ public class GameManager {
public void registerPlayer(Team team, Player player) {
unregisterPlayer(player);
teams.get(team.getId()).addPlayer(player);
teams.get(team.getId()).addPlayer(player.getUniqueId());
}
public void unregisterPlayer(Player player) {
teams.values().forEach(team -> team.removePlayer(player));
teams.values().forEach(team -> team.removePlayer(player.getUniqueId()));
}
public void registerTeam(Team team) {
@ -54,17 +54,17 @@ public class GameManager {
return teams.values();
}
public Optional<Team> getTeam(@NotNull Player player) {
return getTeams().stream().filter(filterTeam -> filterTeam.getPlayer(player).isPresent()).findAny();
public Optional<Team> getTeam(@NotNull UUID uuid) {
return getTeams().stream().filter(filterTeam -> filterTeam.getPlayer(uuid).isPresent()).findAny();
}
public Optional<Team> getTeam(int teamId) {
return getTeams().stream().filter(filterTeam -> filterTeam.getId() == teamId).findAny();
}
public Optional<TeamPlayer> getTeamPlayer(@NotNull Player player) {
public Optional<TeamPlayer> getTeamPlayer(@NotNull UUID uuid) {
return getTeams().stream()
.map(team -> team.getPlayer(player))
.map(team -> team.getPlayer(uuid))
.filter(Optional::isPresent)
.findFirst()
.orElseGet(Optional::empty);

View File

@ -21,9 +21,6 @@ import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@Slf4j
@ -55,14 +52,12 @@ public class ClassSelectionPhase implements GamePhaseExecutor {
Bukkit.broadcast(MiniMessage.miniMessage().deserialize("<green>Select your class with <gold>/ctf selectclass</gold></green>"));
CircularIterator<Team> teamCircularIterator = new CircularIterator<>(gameManager.getTeams());
if (teamCircularIterator.hasNext()) {
ArrayList<? extends Player> players = new ArrayList<>(Bukkit.getOnlinePlayers());
Collections.shuffle(players);
players.stream()
Bukkit.getOnlinePlayers().stream()
.filter(player -> !player.hasPermission("ctf.bypass"))
.filter(player -> gameManager.getTeamPlayer(player).isEmpty())
.filter(player -> gameManager.getTeamPlayer(player.getUniqueId()).isEmpty())
.forEach(player -> {
Team team = teamCircularIterator.next();
team.addPlayer(player);
team.addPlayer(player.getUniqueId());
player.sendRichMessage("You joined <team>!", Placeholder.component("team", team.getName()));
});
} else {
@ -73,7 +68,7 @@ public class ClassSelectionPhase implements GamePhaseExecutor {
private void teleportPlayersToStartingZone() {
Bukkit.getOnlinePlayers().forEach(player -> {
Optional<TeamPlayer> teamPlayer = gameManager.getTeamPlayer(player);
Optional<TeamPlayer> teamPlayer = gameManager.getTeamPlayer(player.getUniqueId());
if (teamPlayer.isEmpty()) {
log.warn("{} is not a team player when teleporting to starting zone", player.getName());
return;

View File

@ -1,6 +1,5 @@
package com.alttd.ctf.game.phases;
import com.alttd.ctf.config.GameConfig;
import com.alttd.ctf.flag.Flag;
import com.alttd.ctf.game.GamePhase;
import com.alttd.ctf.game.GamePhaseExecutor;
@ -18,7 +17,7 @@ public class CombatPhase implements GamePhaseExecutor {
@Override
public synchronized void start(Flag flag) {
Bukkit.broadcast(MiniMessage.miniMessage().deserialize("<green>CAPTURE THE FLAG</green>"));
flag.spawnFlag(GameConfig.FLAG.MATERIAL);
flag.spawnFlag();
if (executorService == null) {
executorService = Executors.newSingleThreadScheduledExecutor();
} else if (executorService.isTerminated() || executorService.isShutdown()) {

View File

@ -7,16 +7,7 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.scoreboard.*;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@ -26,8 +17,6 @@ import java.util.*;
@AllArgsConstructor
public class Team {
@JsonIgnore
private final static Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
@JsonIgnore
private final HashMap<UUID, TeamPlayer> players = new HashMap<>();
@JsonProperty("name")
@ -53,27 +42,15 @@ public class Team {
@NotNull
@Getter
private TeamColor color;
@JsonProperty("flagMaterial")
@NotNull
@Getter
private Material flagMaterial;
@JsonProperty("legacyTeamColor")
@NotNull
@Getter
private String legacyTeamColor;
public TeamPlayer addPlayer(Player player) {
removeFromScoreBoard(player);
UUID uuid = player.getUniqueId();
public TeamPlayer addPlayer(UUID uuid) {
TeamPlayer teamPlayer = new TeamPlayer(uuid, this);
players.put(uuid, teamPlayer);
addToScoreboard(player);
log.debug("Added player {} to team with id {}", player.getName(), id);
log.debug("Added player with uuid {} to team with id {}", uuid, id);
return teamPlayer;
}
public Optional<TeamPlayer> getPlayer(@NotNull Player player) {
UUID uuid = player.getUniqueId();
public Optional<TeamPlayer> getPlayer(@NotNull UUID uuid) {
if (!players.containsKey(uuid))
return Optional.empty();
return Optional.of(players.get(uuid));
@ -83,49 +60,13 @@ public class Team {
return players.values();
}
public void removePlayer(@NotNull Player player) {
removeFromScoreBoard(player);
TeamPlayer remove = players.remove(player.getUniqueId());
public void removePlayer(@NotNull UUID uuid) {
TeamPlayer remove = players.remove(uuid);
if (remove != null) {
log.debug("Removed player {} from team with id {}", player.getName(), id);
log.debug("Removed player with uuid {} from team with id {}", uuid, id);
}
}
private void addToScoreboard(Player player) {
org.bukkit.scoreboard.Team team = scoreboard.getTeam("ctf_" + id);
if (team == null) {
team = scoreboard.registerNewTeam("ctf_" + id);
team.displayName(name);
NamedTextColor namedTextColor = NamedTextColor.nearestTo(TextColor.color(color.r(), color.g(), color.b()));
team.color(namedTextColor);
}
team.addPlayer(player);
player.setScoreboard(scoreboard);
}
private void removeFromScoreBoard(Player player) {
scoreboard.getTeams().stream()
.filter(team -> team.getName().startsWith("ctf_"))
.filter(team -> team.hasPlayer(player))
.forEach(team -> team.removePlayer(player));
}
public void setScore(int newScore) {
Objective objective = getOrCreateObjective();
Score score = objective.getScore(legacyTeamColor + PlainTextComponentSerializer.plainText().serialize(name));
score.setScore(newScore);
}
private Objective getOrCreateObjective() {
Objective objective = scoreboard.getObjective("teamScores");
if (objective == null) {
objective = scoreboard.registerNewObjective("teamScores", Criteria.DUMMY,
MiniMessage.miniMessage().deserialize("<gold>CTF score</gold>"));
objective.setDisplaySlot(DisplaySlot.SIDEBAR);
}
return objective;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {

View File

@ -1,3 +1,3 @@
#Sat Feb 15 03:47:20 CET 2025
buildNumber=50
#Tue Feb 11 22:21:13 CET 2025
buildNumber=45
version=0.1