Skip to content
Open

Dev #599

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/reusable_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ jobs:
purpur
bukkit
spigot
game-versions: '1.21.11'
game-versions: '>=1.21.11 <=26.2'
game-version-filter: none
retry-attempts: 3
retry-delay: 15000
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String
SpectatorManager.getInstance().getSpectators().get(player).removeSpectator(player);
}

// Update sender reference to the current online Player instance
// in case the original sender disconnected and rejoined since the request was sent.
request.setSender(target);
request.acceptRequest();
} else
Common.sendMMMessage(player, LanguageManager.getString("command.accept.player-not-available").replace("%target%", target.getName()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

public class NickCommand implements CommandExecutor, TabCompleter {

Expand Down Expand Up @@ -63,6 +64,21 @@ private static String renderNamePreview(Player target, String rawTemplate) {
);
}

private static String getPlainName(String rawTemplate, String playerName) {
String normalizedTemplate = NameFormatUtil.normalizePlayerNameTemplate(rawTemplate);
return PLAIN_TEXT_SERIALIZER.serialize(
NameFormatUtil.applyPlayerPlaceholders(
NameFormatUtil.parseConfiguredComponent(normalizedTemplate),
playerName
)
).trim();
}

private static boolean isValidNickname(String rawTemplate, String playerName) {
String plainName = getPlainName(rawTemplate, playerName);
return Pattern.compile(ConfigManager.getString("PLAYER.NICKNAME.VALIDATION-PATTERN")).matcher(plainName).matches();
}

@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player player)) {
Expand Down Expand Up @@ -138,6 +154,11 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String
return false;
}

if (!isValidNickname(nameTemplate, target.getName())) {
Common.sendMMMessage(player, LanguageManager.getString("COMMAND.NICK.INVALID-NAME"));
return false;
}

applyNameTemplate(target, nameTemplate);
String formattedNamePreview = renderNamePreview(target, nameTemplate);

Expand Down Expand Up @@ -183,4 +204,4 @@ public List<String> onTabComplete(CommandSender sender, Command command, String
Collections.sort(completion);
return completion;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import dev.nandi0813.practice.manager.fight.match.enums.TeamEnum;
import dev.nandi0813.practice.manager.fight.util.FightPlayer;
import dev.nandi0813.practice.manager.fight.util.KitSelectionHandler;
import dev.nandi0813.practice.manager.fight.match.util.KitUtil;
import dev.nandi0813.practice.manager.ladder.abstraction.normal.NormalLadder;
import lombok.Getter;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

/**
* FFA-specific fight player that handles custom kit selection.
Expand All @@ -17,10 +19,14 @@
public class FFAFightPlayer extends FightPlayer {

private final FFA ffa;
private final NormalLadder ladder;
private NormalLadder ladder;

private KitSelectionHandler kitSelectionHandler;
private int chosenKit;
private int chosenKit = -1;

private ItemStack[] savedInventory;
private ItemStack[] savedArmor;
private ItemStack[] savedExtra;

public FFAFightPlayer(Player player, FFA ffa, NormalLadder ladder) {
super(player, ffa);
Expand All @@ -36,25 +42,42 @@ public FFAFightPlayer(Player player, FFA ffa, NormalLadder ladder) {

/**
* Displays the kit chooser GUI or applies the chosen kit.
* Used only for initial kit selection on join.
*/
public void showKitChooserOrApplyKit() {
if (this.kitSelectionHandler != null) {
this.kitSelectionHandler.showKitChooserOrApplyKit(TeamEnum.FFA);
} else {
// No custom kits, apply default kit directly
applyDefaultKit();
}
}

/**
* Restores the player's kit on death.
* Uses saved kit data if a custom kit was selected, otherwise applies the current ladder's default kit.
*/
public void restoreKitOnDeath() {
if (savedInventory != null) {
KitUtil.loadKit(player, TeamEnum.FFA, savedArmor, savedInventory, savedExtra);
} else {
KitUtil.loadDefaultLadderKit(player, TeamEnum.FFA, ladder);
}
}

/**
* Called when player clicks a kit slot to select it.
* After selection, the player becomes a full combatant.
*/
public void selectKit(int slot) {
if (this.kitSelectionHandler != null && this.kitSelectionHandler.getKits() != null
if (this.kitSelectionHandler != null && this.kitSelectionHandler.getKits() != null
&& this.kitSelectionHandler.getKits().containsKey(slot)) {
this.kitSelectionHandler.selectKit(slot, TeamEnum.FFA);
this.chosenKit = slot;

KitSelectionHandler handler = this.kitSelectionHandler;
savedInventory = cloneItems(handler.getKits().get(slot).getInventory());
savedArmor = cloneItems(handler.getKits().get(slot).getArmor());
savedExtra = cloneItems(handler.getKits().get(slot).getExtra());
}
}

Expand All @@ -73,5 +96,25 @@ public void applyDefaultKit() {
this.kitSelectionHandler = new KitSelectionHandler(player, getProfile(), ladder);
this.kitSelectionHandler.showKitChooserOrApplyKit(TeamEnum.FFA);
}
}

/**
* Resets the player's state for a new ladder (called on /ffa kit switch).
*/
public void resetForNewLadder(NormalLadder newLadder) {
this.ladder = newLadder;
this.chosenKit = -1;
this.savedInventory = null;
this.savedArmor = null;
this.savedExtra = null;
this.kitSelectionHandler = new KitSelectionHandler(player, getProfile(), newLadder);
}

private static ItemStack[] cloneItems(ItemStack[] source) {
if (source == null) return null;
ItemStack[] copy = source.clone();
for (int i = 0; i < copy.length; i++) {
if (copy[i] != null) copy[i] = copy[i].clone();
}
return copy;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import dev.nandi0813.practice.util.Cuboid;
import dev.nandi0813.practice.util.NumberUtil;
import dev.nandi0813.practice.util.fightmapchange.FightChangeOptimized;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.damage.DamageSource;
Expand Down Expand Up @@ -198,8 +197,6 @@ protected static void arrowDisplayHearth(Player shooter, Player target, double f
.replace("%health%", String.valueOf(health)));
}

private static final String FFA_DEATH_ANIMATION_ENABLED_PATH = "FFA.DEATH-ANIMATION.ENABLED";

private static final boolean ALLOW_DESTROYABLE_BLOCK = ConfigManager.getBoolean("FFA.ALLOW-DESTROYABLE-BLOCK");

/**
Expand Down Expand Up @@ -379,10 +376,7 @@ public void onPlayerDeath(PlayerDeathEvent e) {
e.setDroppedExp(0);
e.setKeepInventory(true);
e.setKeepLevel(true);
e.setDeathMessage(null);

boolean playVanillaDeathAnimation = ConfigManager.getConfig().getBoolean(FFA_DEATH_ANIMATION_ENABLED_PATH, true);
e.setCancelled(!playVanillaDeathAnimation);
e.setCancelled(true);

DamageSource damageSource = e.getDamageSource();

Expand All @@ -398,43 +392,17 @@ public void onPlayerDeath(PlayerDeathEvent e) {
if (cause == DeathCause.EXPLOSION && killer != null && !killer.equals(player)) {
cause = DeathCause.EXPLOSION_BY_PLAYER;
}
ffa.killPlayer(player, killer, cause.getMessage().replace("%killer%", killer != null ? killer.getName() : "Unknown"));

Player finalKiller = killer;
DeathCause finalCause = cause;

Runnable deathTask = () -> {
if (playVanillaDeathAnimation && player.isOnline() && player.isDead()) {
player.spigot().respawn();
}
ffa.killPlayer(player, finalKiller, finalCause.getMessage().replace("%killer%", finalKiller != null ? finalKiller.getName() : "Unknown"));

if (finalKiller != null && !finalKiller.equals(player)) {
Statistic statistic = ffa.getStatistics().computeIfAbsent(
finalKiller,
p -> new Statistic(ProfileManager.getInstance().getUuids().get(p))
);
statistic.setKills(statistic.getKills() + 1);
}
};

if (playVanillaDeathAnimation) {
long delayTicks = 15L;
Bukkit.getScheduler().runTaskLater(ZonePractice.getInstance(), deathTask, delayTicks);
} else {
deathTask.run();
if (killer != null && !killer.equals(player)) {
Statistic statistic = ffa.getStatistics().computeIfAbsent(
killer,
p -> new Statistic(ProfileManager.getInstance().getUuids().get(p))
);
statistic.setKills(statistic.getKills() + 1);
}
}

@EventHandler
public void onFFARespawn(PlayerRespawnEvent e) {
Player player = e.getPlayer();

FFA ffa = FFAManager.getInstance().getFFAByPlayer(player);
if (ffa == null) return;

e.setRespawnLocation(player.getLocation());
}

private Player resolveKiller(Player victim, FFA ffa, DamageSource damageSource) {
Player killer = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public void addPlayer(Player player, NormalLadder ladder) {
return;

players.put(player, ladder);

// Use FFAFightPlayer to handle custom kit selection
FFAFightPlayer ffaFightPlayer = new FFAFightPlayer(player, this, ladder);
fightPlayers.put(player, ffaFightPlayer);
Expand Down Expand Up @@ -146,7 +146,7 @@ public void addPlayer(Player player, NormalLadder ladder) {

// Show kit chooser or apply default kit
ffaFightPlayer.showKitChooserOrApplyKit();

dev.nandi0813.practice.manager.fight.util.PlayerUtil.setAttackSpeed(player, ladder.getAttackCooldownModifier());

ProfileManager.getInstance().getProfile(player).setStatus(ProfileStatus.FFA);
Expand All @@ -161,6 +161,11 @@ public void changePlayerLadder(Player player, NormalLadder ladder) {
PlayerUtil.setFightPlayer(player, ladder);
KitUtil.loadDefaultLadderKit(player, TeamEnum.FFA, ladder);
dev.nandi0813.practice.manager.fight.util.PlayerUtil.setAttackSpeed(player, ladder.getAttackCooldownModifier());

FFAFightPlayer ffaFightPlayer = fightPlayers.get(player);
if (ffaFightPlayer != null) {
ffaFightPlayer.resetForNewLadder(ladder);
}
}

/**
Expand Down Expand Up @@ -264,7 +269,7 @@ public void killPlayer(Player player, Player killer, String deathMessage) {
private void applySelectedOrDefaultKit(Player player) {
FFAFightPlayer ffaFightPlayer = fightPlayers.get(player);
if (ffaFightPlayer != null) {
ffaFightPlayer.showKitChooserOrApplyKit();
ffaFightPlayer.restoreKitOnDeath();
return;
}

Expand Down Expand Up @@ -485,4 +490,4 @@ private void removePlayerFromBelowName(Player player) {
MatchManager.getInstance().getBelowNameManager().cleanUpForUser(player);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import dev.nandi0813.practice.manager.fight.match.runnable.game.BridgeArrowRunnable;
import dev.nandi0813.practice.manager.fight.match.util.KnockbackUtil;
import dev.nandi0813.practice.manager.fight.match.util.MatchFightPlayer;

import dev.nandi0813.practice.manager.fight.match.util.TeamUtil;
import dev.nandi0813.practice.manager.fight.util.*;
import dev.nandi0813.practice.manager.fight.util.Stats.Statistic;
Expand Down Expand Up @@ -51,6 +50,7 @@

import static dev.nandi0813.practice.manager.arena.util.ArenaUtil.containsDestroyableBlock;
import static dev.nandi0813.practice.util.PermanentConfig.FIGHT_ENTITY;
import static dev.nandi0813.practice.util.PermanentConfig.PLACED_IN_FIGHT;

public class LadderTypeListener implements Listener {

Expand All @@ -59,7 +59,6 @@ public class LadderTypeListener implements Listener {
private static final String SHIELD_STUN_DURATION_PATH = AXE_LADDER_SETTINGS_PATH + ".SHIELD-STUN.DURATION-TICKS";
private static final String SHIELD_STUN_REQUIRE_AXE_PATH = AXE_LADDER_SETTINGS_PATH + ".SHIELD-STUN.REQUIRE-AXE";
private static final String SHIELD_SKIP_VANILLA_TICK_PATH = AXE_LADDER_SETTINGS_PATH + ".SKIP-VANILLA-DAMAGE-TICK-WHEN-SHIELD-BLOCKED";
private static final String DEATH_ANIMATION_ENABLED_PATH = "MATCH-SETTINGS.DEATH-ANIMATION.ENABLED";
private static final int SKYWARS_KILLER_EXP_LEVEL_REWARD = 5;
private static final int SKYWARS_ENCHANT_LAPIS_AMOUNT = 3;

Expand Down Expand Up @@ -196,6 +195,7 @@ private static void enforceShieldDamageTickBypass(Player target) {
// Run one tick later so vanilla cannot restore the damage immunity window.
Bukkit.getScheduler().runTask(ZonePractice.getInstance(), () -> {
if (!target.isOnline() || target.isDead()) {
return;
}
});
}
Expand Down Expand Up @@ -680,10 +680,7 @@ public void onPlayerDeath(PlayerDeathEvent e) {
e.setDroppedExp(0);
e.setKeepInventory(true);
e.setKeepLevel(true);
e.deathMessage(null);

boolean playVanillaDeathAnimation = ConfigManager.getConfig().getBoolean(DEATH_ANIMATION_ENABLED_PATH, true);
e.setCancelled(!playVanillaDeathAnimation);
e.setCancelled(true);

DamageSource damageSource = e.getDamageSource();
Player killer;
Expand All @@ -694,18 +691,8 @@ public void onPlayerDeath(PlayerDeathEvent e) {
}

DeathCause cause = FightUtil.convert(damageSource.getDamageType());
if (cause == DeathCause.EXPLOSION && killer != null && !killer.equals(player)) {
cause = DeathCause.EXPLOSION_BY_PLAYER;
}
DeathCause finalCause = cause;

long delayTicks = playVanillaDeathAnimation ? 15L : 1L;
Bukkit.getScheduler().runTaskLater(ZonePractice.getInstance(), () -> {
if (playVanillaDeathAnimation && player.isOnline() && player.isDead()) {
player.spigot().respawn();
}
match.killPlayer(player, killer, finalCause.getMessage().replace("%killer%", killer != null ? killer.getName() : "Unknown"));
}, delayTicks);
Bukkit.getScheduler().runTaskLater(ZonePractice.getInstance(), () ->
match.killPlayer(player, killer, cause.getMessage().replace("%killer%", killer != null ? killer.getName() : "Unknown")), 1L);

if (killer != null) {
Statistic statistic = match.getCurrentStat(killer);
Expand All @@ -719,16 +706,6 @@ public void onPlayerDeath(PlayerDeathEvent e) {
}
}

@EventHandler
public void onMatchRespawn(PlayerRespawnEvent e) {
Player player = e.getPlayer();

Match match = MatchManager.getInstance().getLiveMatchByPlayer(player);
if (match == null) return;

e.setRespawnLocation(player.getLocation());
}

private static void onEntityDamageByEntity(EntityDamageByEntityEvent e) {
if (!(e.getEntity() instanceof Player target)) return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import dev.nandi0813.practice.manager.fight.match.Match;
import dev.nandi0813.practice.manager.fight.match.MatchManager;
import dev.nandi0813.practice.manager.fight.match.enums.MatchStatus;
import dev.nandi0813.practice.manager.fight.match.enums.TeamEnum;
import dev.nandi0813.practice.manager.fight.match.interfaces.Team;
import dev.nandi0813.practice.manager.fight.match.util.MatchFightPlayer;
Expand Down Expand Up @@ -59,6 +60,9 @@ public void onPlayerTeleport(PlayerTeleportEvent e) {
Match match = MatchManager.getInstance().getLiveMatchByPlayer(e.getPlayer());
if (match == null) return;

if (match.getStatus().equals(MatchStatus.END) || match.getStatus().equals(MatchStatus.OVER))
return;

if (!match.getArena().getCuboid().contains(e.getTo()))
e.setCancelled(true);
}
Expand Down
Loading
Loading