Compare commits

..

No commits in common. "e62d0df9dfde4d4b484d2c3901caac0e733c01f3" and "c09c55ed7a344ef13932ffb8b903c01f88111f20" have entirely different histories.

14 changed files with 19 additions and 262 deletions

View File

@ -89,7 +89,7 @@ public class Main extends JavaPlugin {
pluginManager.registerEvents(new FlagTryCaptureEvent(flag), this);
pluginManager.registerEvents(new OnPlayerDeath(gameManager, worldBorderApi, this, flag), this);
pluginManager.registerEvents(new InventoryItemInteractionEvent(), this);
pluginManager.registerEvents(new OnPlayerOnlineStatus(gameManager, flag, worldBorderApi), this);
pluginManager.registerEvents(new OnPlayerOnlineStatus(gameManager, flag), this);
pluginManager.registerEvents(new GUIListener(), this);
}

View File

@ -46,9 +46,7 @@ public class SelectClass extends SubCommand {
return 0;
}
TeamPlayer teamPlayer = optionalTeamPlayer.get();
if (!teamPlayer.isDead()
&& !gamePhase.equals(GamePhase.CLASS_SELECTION)
&& teamPlayer.getTeam().getSpawnLocation().distance(player.getLocation()) > 5) {
if (!gamePhase.equals(GamePhase.CLASS_SELECTION) && teamPlayer.getTeam().getSpawnLocation().distance(player.getLocation()) > 5) {
commandSender.sendRichMessage("<red>You have to be near your spawn to change classes.</red>");
return 0;
}

View File

@ -5,14 +5,12 @@ import com.alttd.ctf.config.GameConfig;
import com.alttd.ctf.flag.Flag;
import com.alttd.ctf.game.GameManager;
import com.alttd.ctf.game.GamePhase;
import com.alttd.ctf.stats.Stat;
import com.alttd.ctf.team.TeamPlayer;
import com.github.yannicklamprecht.worldborder.api.WorldBorderApi;
import lombok.extern.slf4j.Slf4j;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.Bukkit;
import org.bukkit.damage.DamageEffect;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -46,18 +44,7 @@ public class OnPlayerDeath implements Listener {
Player player = event.getPlayer();
player.getInventory().clear();
player.updateInventory();
gameManager.getTeamPlayer(player)
.ifPresent(TeamPlayer::setDead);
flag.handleCarrierDeathOrDisconnect(player);
try {
if (event.getDamageSource().getDamageType().getDamageEffect().equals(DamageEffect.FREEZING)) {
gameManager.getTeamPlayer(player)
.ifPresent(teamPlayer -> teamPlayer.increaseStat(Stat.DEATHS_IN_POWDERED_SNOW));
}
} catch (Exception e) {
log.warn("Failed to check for death cause due to exception", e);
}
}
@EventHandler

View File

@ -5,10 +5,8 @@ import com.alttd.ctf.database.DiscordUserMapper;
import com.alttd.ctf.flag.Flag;
import com.alttd.ctf.game.GameManager;
import com.alttd.ctf.game.GamePhase;
import com.alttd.ctf.game_class.creation.FighterCreator;
import com.alttd.ctf.team.Team;
import com.alttd.ctf.team.TeamPlayer;
import com.github.yannicklamprecht.worldborder.api.WorldBorderApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.exceptions.PersistenceException;
import org.bukkit.attribute.Attribute;
@ -28,12 +26,10 @@ public class OnPlayerOnlineStatus implements Listener {
private final GameManager gameManager;
private final Flag flag;
private final WorldBorderApi worldBorderApi;
public OnPlayerOnlineStatus(GameManager gameManager, Flag flag, WorldBorderApi worldBorderApi) {
public OnPlayerOnlineStatus(GameManager gameManager, Flag flag) {
this.gameManager = gameManager;
this.flag = flag;
this.worldBorderApi = worldBorderApi;
}
@EventHandler
@ -64,10 +60,8 @@ public class OnPlayerOnlineStatus implements Listener {
teamPlayer = min.get().addPlayer(player);
} else {
teamPlayer = optionalTeamPlayer.get();
teamPlayer.getTeam().addToScoreboard(player);
}
FighterCreator.createFighter(teamPlayer.getTeam().getColor())
.apply(teamPlayer, worldBorderApi, gamePhase, true);
player.teleportAsync(teamPlayer.getTeam().getSpawnLocation());
}
private void resetPlayer(Player player) {

View File

@ -1,108 +0,0 @@
package com.alttd.ctf.events;
import com.alttd.ctf.game.GameManager;
import com.alttd.ctf.stats.Stat;
import com.alttd.ctf.team.TeamPlayer;
import lombok.extern.slf4j.Slf4j;
import org.bukkit.Tag;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.entity.Player;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import java.util.Optional;
@Slf4j
public class OtherGameEvents implements Listener {
private final GameManager gameManager;
public OtherGameEvents(GameManager gameManager) {
this.gameManager = gameManager;
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
if (gameManager.getGamePhase().isEmpty()) {
return;
}
if (!Tag.SNOW.isTagged(event.getBlock().getType())) {
event.setCancelled(true);
return;
}
gameManager.getTeamPlayer(event.getPlayer())
.ifPresent(teamPlayer -> teamPlayer.increaseStat(Stat.SNOW_MINED));
}
@EventHandler
public void onBlockPlace(BlockBreakEvent event) {
if (gameManager.getGamePhase().isEmpty()) {
return;
}
if (!Tag.SNOW.isTagged(event.getBlock().getType())) {
event.setCancelled(true);
log.warn("Player {} placed a block that wasn't snow: {}",
event.getPlayer().getName(), event.getBlock().getType());
return;
}
gameManager.getTeamPlayer(event.getPlayer())
.ifPresent(teamPlayer -> teamPlayer.increaseStat(Stat.BLOCKS_PLACED));
}
@EventHandler
public void onPotionSplash(PotionSplashEvent event) {
ThrownPotion thrownPotion = event.getPotion();
if (!(thrownPotion.getShooter() instanceof Player player))
return;
Optional<TeamPlayer> optionalTeamPlayer = gameManager.getTeamPlayer(player);
if (optionalTeamPlayer.isEmpty())
return;
TeamPlayer teamPlayer = optionalTeamPlayer.get();
event.getAffectedEntities().stream()
.filter(livingEntity -> livingEntity instanceof Player)
.map(livingEntity -> (Player) livingEntity)
.forEach(target -> {
if (shouldHeal(teamPlayer, target)) {
return;
}
event.setIntensity(target, 0);
});
double totalHealing = thrownPotion.getEffects().stream()
.filter(effect -> effect.getType() == PotionEffectType.INSTANT_HEALTH)
.flatMapToDouble(effect -> event.getAffectedEntities().stream()
.filter(livingEntity -> livingEntity instanceof Player)
.map(livingEntity -> (Player) livingEntity)
.mapToDouble(target -> calculateActualHealing(target, effect, event.getIntensity(target))))
.sum();
teamPlayer.increaseStat(Stat.DAMAGE_HEALED, totalHealing);
}
private boolean shouldHeal(TeamPlayer healer, Player target) {
Optional<TeamPlayer> optionalTeamTarget = gameManager.getTeamPlayer(target);
return optionalTeamTarget.isPresent() && healer.getTeam() == optionalTeamTarget.get().getTeam();
}
private double calculateActualHealing(Player target, PotionEffect effect, double intensity) {
AttributeInstance playerMaxHealth = target.getAttribute(Attribute.GENERIC_MAX_HEALTH);
if (playerMaxHealth == null) {
return 0;
}
double missingHealth = playerMaxHealth.getValue() - target.getHealth();
//Only counts healing on teammates since intensity was set to 0 for non teammates
double potentialHealing = (effect.getAmplifier() + 1) * intensity;
return Math.min(potentialHealing, missingHealth);
}
}

View File

@ -3,7 +3,6 @@ package com.alttd.ctf.events;
import com.alttd.ctf.game.GameManager;
import com.alttd.ctf.game.GamePhase;
import com.alttd.ctf.game_class.GameClass;
import com.alttd.ctf.stats.Stat;
import com.alttd.ctf.team.TeamPlayer;
import lombok.extern.slf4j.Slf4j;
import org.bukkit.Location;
@ -47,13 +46,8 @@ public class SnowballEvent implements Listener {
GameClass shooterClass = shooterTeamPlayer.getGameClass();
shooter.setCooldown(Material.SNOWBALL, shooterClass.getThrowTickSpeed());
double newHealth = Math.max(hitPlayer.getHealth() - shooterClass.getDamage(), 0);
hitPlayer.setHealth(newHealth);
shooterTeamPlayer.increaseStat(Stat.DAMAGE_DONE, shooterClass.getDamage());
if (newHealth <= 0) {
shooterTeamPlayer.increaseStat(Stat.KILLS);
}
double newHealth = hitPlayer.getHealth() - shooterClass.getDamage();
hitPlayer.setHealth(Math.max(newHealth, 0));
log.debug("{} health was set to {} because of a snowball thrown by {}",
hitPlayer.getName(), Math.max(newHealth, 0), shooter.getName());
});
@ -64,7 +58,6 @@ public class SnowballEvent implements Listener {
handleSnowballThrown(event, (shooter, shooterTeamPlayer) -> {
GameClass shooterClass = shooterTeamPlayer.getGameClass();
shooter.setCooldown(Material.SNOWBALL, shooterClass.getThrowTickSpeed());
shooterTeamPlayer.increaseStat(Stat.SNOWBALLS_THROWN);
});
}

View File

@ -3,7 +3,6 @@ package com.alttd.ctf.flag;
import com.alttd.ctf.Main;
import com.alttd.ctf.config.GameConfig;
import com.alttd.ctf.game.GameManager;
import com.alttd.ctf.stats.Stat;
import com.alttd.ctf.team.Team;
import com.alttd.ctf.team.TeamColor;
import com.alttd.ctf.team.TeamPlayer;
@ -86,7 +85,6 @@ public class Flag implements Runnable {
Bukkit.getScheduler().runTask(main, () -> flagLocation.getBlock().setType(Material.AIR));
flagCarrier = player;
player.addPotionEffect(new PotionEffect(PotionEffectType.SLOWNESS, PotionEffect.INFINITE_DURATION, 0, false, false));
player.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, PotionEffect.INFINITE_DURATION, 0, false, false));
notifyAboutCapture();
resetFlag();
}
@ -167,8 +165,7 @@ public class Flag implements Runnable {
Placeholder.component("player", flagCarrier.displayName())));
Bukkit.getOnlinePlayers().forEach(player ->
gameManager.getTeam(player).ifPresent(team ->
player.showTitle(team.getId().intValue() == winningTeam.getId().intValue()
? capturingTeamTitle : huntingTeamTitle)));
player.showTitle(team.getId() == winningTeam.getId() ? capturingTeamTitle : huntingTeamTitle)));
}
private void spawnParticlesOnSquareBorder(Location center, double size) {
@ -224,10 +221,7 @@ public class Flag implements Runnable {
flagCarrier.getInventory().setItem(EquipmentSlot.HEAD, null);
gameManager.getTeamPlayer(flagCarrier)
.ifPresent(teamPlayer -> {
teamPlayer.getGameClass().setArmor(flagCarrier, teamPlayer);
teamPlayer.increaseStat(Stat.FLAGS_CAPTURED);
});
.ifPresent(teamPlayer -> teamPlayer.getGameClass().setArmor(flagCarrier, teamPlayer));
resetFlagCarrier();
}
@ -324,7 +318,6 @@ public class Flag implements Runnable {
return Math.max(updatedValue, 0);
});
});
nearbyPlayers.forEach(teamPlayer -> teamPlayer.increaseStat(Stat.TIME_SPEND_CAPTURING_FLAG));
return true;
}
@ -383,7 +376,6 @@ public class Flag implements Runnable {
resetFlagCarrier();
resetFlag();
wins.clear();
gameManager.getTeams().forEach(team -> team.setScore(0));
}
public void handleCarrierDeathOrDisconnect(Player player) {

View File

@ -32,8 +32,6 @@ public class CombatPhase implements GamePhaseExecutor {
@Override
public void end(GamePhase ignored) {
if (executorService != null) {
executorService.shutdown();
}
executorService.shutdown();
}
}

View File

@ -4,11 +4,11 @@ import com.alttd.ctf.flag.Flag;
import com.alttd.ctf.game.GameManager;
import com.alttd.ctf.game.GamePhase;
import com.alttd.ctf.game.GamePhaseExecutor;
import com.alttd.ctf.game_class.GameClass;
import com.github.yannicklamprecht.worldborder.api.WorldBorderApi;
import lombok.extern.slf4j.Slf4j;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@Slf4j
public class GatheringPhase implements GamePhaseExecutor {
@ -37,12 +37,8 @@ public class GatheringPhase implements GamePhaseExecutor {
return;
}
gameManager.getTeams().forEach(team -> {
team.getPlayers().forEach(teamPlayer -> {
Player player = Bukkit.getPlayer(teamPlayer.getUuid());
if (player == null || !player.isOnline()) {
return;
}
teamPlayer.resetWorldBorder(player, worldBorderApi, nextPhase, flag.getFlagLocation());
team.getPlayers().forEach(player -> {
player.resetWorldBorder(Bukkit.getPlayer(player.getUuid()), worldBorderApi, nextPhase, flag.getFlagLocation());
});
});
}

View File

@ -1,58 +0,0 @@
package com.alttd.ctf.stats;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import java.util.UUID;
@Getter
public final class PlayerStat {
private static final CommandSender commandSender = Bukkit.getConsoleSender();
private final UUID uuid;
private final String inGameName;
private boolean completedGame = false;
private int flagsCaptured = 0;
private int kills = 0;
private double damageDone = 0;
private double damageHealed = 0;
private int snowMined = 0;
private int blocksPlaced = 0;
private int snowballsThrown = 0;
private long timeSpendCapturingFlag = 0;
private int deathsInPowderedSnow = 0;
public PlayerStat(UUID uuid, String inGameName) {
this.uuid = uuid;
this.inGameName = inGameName;
}
public void increaseStat(Stat stat) throws IllegalArgumentException {
switch (stat) {
case COMPLETED_GAME -> {
if (!completedGame) {
Bukkit.dispatchCommand(commandSender, String.format("lp user %s permission set ctf.game.completed", inGameName));
}
completedGame = true;
}
case FLAGS_CAPTURED -> flagsCaptured++;
case KILLS -> kills++;
case SNOW_MINED -> snowMined++;
case BLOCKS_PLACED -> blocksPlaced++;
case SNOWBALLS_THROWN -> snowballsThrown++;
case TIME_SPEND_CAPTURING_FLAG -> timeSpendCapturingFlag++;
case DEATHS_IN_POWDERED_SNOW -> deathsInPowderedSnow++; //TODO announce if they are the first person to do this and save they are the first
case DAMAGE_DONE, DAMAGE_HEALED -> throw new IllegalArgumentException(String.format("%s requires a number", stat.name()));
}
}
public void increaseStat(Stat stat, double value) throws IllegalArgumentException {
switch (stat) {
case DAMAGE_DONE -> damageDone += value;
case DAMAGE_HEALED -> damageHealed += value;
default -> throw new IllegalArgumentException(String.format("%s cannot be passed with a number", stat.name()));
}
}
}

View File

@ -1,14 +0,0 @@
package com.alttd.ctf.stats;
public enum Stat {
COMPLETED_GAME,
FLAGS_CAPTURED,
KILLS,
DAMAGE_DONE,
DAMAGE_HEALED,
SNOW_MINED,
BLOCKS_PLACED,
SNOWBALLS_THROWN,
TIME_SPEND_CAPTURING_FLAG,
DEATHS_IN_POWDERED_SNOW
}

View File

@ -76,7 +76,7 @@ public class Team {
public TeamPlayer addPlayer(Player player) {
removeFromScoreBoard(player);
UUID uuid = player.getUniqueId();
TeamPlayer teamPlayer = new TeamPlayer(player, this);
TeamPlayer teamPlayer = new TeamPlayer(uuid, this);
players.put(uuid, teamPlayer);
addToScoreboard(player);
if (discordTeam != null) {
@ -113,7 +113,7 @@ public class Team {
log.debug("Removed player {} from team with id {}", player.getName(), id);
}
public void addToScoreboard(Player player) {
private void addToScoreboard(Player player) {
org.bukkit.scoreboard.Team team = scoreboard.getTeam("ctf_" + id);
if (team == null) {
team = scoreboard.registerNewTeam("ctf_" + id);

View File

@ -7,8 +7,6 @@ import com.alttd.ctf.game.GamePhase;
import com.alttd.ctf.game_class.GameClass;
import com.alttd.ctf.game_class.GameClassRetrieval;
import com.alttd.ctf.gui.ClassSelectionGUI;
import com.alttd.ctf.stats.PlayerStat;
import com.alttd.ctf.stats.Stat;
import com.github.yannicklamprecht.worldborder.api.WorldBorderApi;
import lombok.Getter;
import lombok.Setter;
@ -23,17 +21,14 @@ import java.util.*;
@Getter
public class TeamPlayer {
private final PlayerStat playerStat;
private final UUID uuid;
private final Team team;
@Setter
private GameClass gameClass;
private boolean isDead = false;
protected TeamPlayer(Player player, Team team) {
this.uuid = player.getUniqueId();
protected TeamPlayer(UUID uuid, Team team) {
this.uuid = uuid;
this.team = team;
this.playerStat = new PlayerStat(uuid, player.getName());
}
public void respawn(@NotNull Player player, @NotNull WorldBorderApi worldBorderApi, @NotNull GamePhase gamePhase) {
@ -53,17 +48,9 @@ public class TeamPlayer {
}
player.teleportAsync(spawnLocation).thenAcceptAsync(unused ->
resetWorldBorder(player, worldBorderApi, gamePhase, worldBorderCenter));
isDead = false;
}
public void setDead() {
isDead = true;
}
public void resetWorldBorder(@NotNull Player player, WorldBorderApi worldBorderApi, GamePhase gamePhase, Location worldBorderCenter) {
if (!player.isOnline()) {
return;
}
public void resetWorldBorder(Player player, WorldBorderApi worldBorderApi, GamePhase gamePhase, Location worldBorderCenter) {
WorldBorderSettings worldBorderSettings = GameConfig.WORLD_BORDER.getGAME_PHASE_WORLD_BORDER().get(gamePhase);
if (worldBorderSettings == null) {
throw new IllegalStateException("All phases need to have world border settings");
@ -91,12 +78,4 @@ public class TeamPlayer {
public int hashCode() {
return Objects.hash(uuid);
}
public void increaseStat(Stat stat) {
playerStat.increaseStat(stat);
}
public void increaseStat(Stat stat, double amount) {
playerStat.increaseStat(stat, amount);
}
}

View File

@ -1,3 +1,3 @@
#Sun Feb 23 01:14:21 CET 2025
buildNumber=70
#Sat Feb 15 22:27:11 CET 2025
buildNumber=66
version=0.1