diff --git a/core/src/main/java/dev/nandi0813/practice/manager/fight/ffa/FFAListener.java b/core/src/main/java/dev/nandi0813/practice/manager/fight/ffa/FFAListener.java index 07ae5ae2..7d515764 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/fight/ffa/FFAListener.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/fight/ffa/FFAListener.java @@ -398,7 +398,7 @@ public void onPlayerDeath(PlayerDeathEvent e) { DeathCause cause = FightUtil.convert(damageSource.getDamageType()); ffa.killPlayer(player, killer, cause.getMessage().replace("%killer%", killer != null ? killer.getName() : "Unknown")); - if (killer != null) { + if (killer != null && !killer.equals(player)) { Statistic statistic = ffa.getStatistics().computeIfAbsent( killer, p -> new Statistic(ProfileManager.getInstance().getUuids().get(p)) diff --git a/core/src/main/java/dev/nandi0813/practice/manager/fight/ffa/game/FFA.java b/core/src/main/java/dev/nandi0813/practice/manager/fight/ffa/game/FFA.java index 3aa73807..2f740d2a 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/fight/ffa/game/FFA.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/fight/ffa/game/FFA.java @@ -224,7 +224,7 @@ public void killPlayer(Player player, Player killer, String deathMessage) { // check whether a recent attacker should be credited instead. if (killer == null) { Player lastAttacker = getLastAttacker(player); - if (lastAttacker != null && deathMessage != null + if (lastAttacker != null && !lastAttacker.equals(player) && deathMessage != null && deathMessage.equals(dev.nandi0813.practice.manager.fight.util.DeathCause.VOID.getMessage())) { killer = lastAttacker; deathMessage = dev.nandi0813.practice.manager.fight.util.DeathCause.VOID_BY_PLAYER @@ -237,7 +237,7 @@ public void killPlayer(Player player, Player killer, String deathMessage) { Profile deadProfile = fightPlayers.get(player).getProfile(); deadProfile.getStats().getLadderStat(players.get(player)).increaseDeaths(); - if (killer != null) { + if (killer != null && !killer.equals(player)) { Profile killerProfile = fightPlayers.get(killer).getProfile(); killerProfile.getStats().getLadderStat(players.get(killer)).increaseKills(); diff --git a/core/src/main/java/dev/nandi0813/practice/manager/fight/match/Match.java b/core/src/main/java/dev/nandi0813/practice/manager/fight/match/Match.java index c4542476..eb9d2969 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/fight/match/Match.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/fight/match/Match.java @@ -343,7 +343,13 @@ public void endMatch() { removeSpectator(spectator); // Reset the arena and only make it reusable after rollback completes. - resetMap(() -> this.arena.setAvailable(true)); + // Also defer live-match removal to the rollback callback so block event listeners + // can still resolve this match via cuboid lookup during the multi-tick rollback, + // preventing untracked block changes from leaking into the next match. + resetMap(() -> { + MatchManager.getInstance().getLiveMatches().remove(this); + this.arena.setAvailable(true); + }); this.cancel(); @@ -422,7 +428,7 @@ public void addSpectator(Player player, Player target, boolean teleport, boolean return; } - if (this.status.equals(MatchStatus.OVER)) { + if (this.status.equals(MatchStatus.OVER) || this.players.isEmpty()) { Common.sendMMMessage(player, LanguageManager.getString("SPECTATE.MATCH.MATCH-ENDED")); return; } @@ -463,6 +469,7 @@ public void addSpectator(Player player, Player target, boolean teleport, boolean } Profile profile = ProfileManager.getInstance().getProfile(player); + profile.setStatus(ProfileStatus.SPECTATE); if (profile.isStaffMode()) { InventoryManager.getInstance().setStaffModeInventory(player); diff --git a/core/src/main/java/dev/nandi0813/practice/manager/fight/match/listener/MatchLifecycleListener.java b/core/src/main/java/dev/nandi0813/practice/manager/fight/match/listener/MatchLifecycleListener.java index f6ab538f..a65c556c 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/fight/match/listener/MatchLifecycleListener.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/fight/match/listener/MatchLifecycleListener.java @@ -58,7 +58,10 @@ public void onMatchEnd(MatchEndEvent e) { if (party != null) party.setMatch(null); - MatchManager.getInstance().getLiveMatches().remove(match); + // Live match removal is deferred to after rollback completes in Match.endMatch(). + // This ensures block event listeners can still resolve the match via cuboid lookup + // during the multi-tick rollback window, preventing untracked block changes. + // MatchManager.getInstance().getLiveMatches().remove(match); // Update GUIs if (match instanceof Duel && ((Duel) match).isRanked())