From c87aad4171ed8852bd5ac65175cbb3faae8928da Mon Sep 17 00:00:00 2001 From: lokspel <208148594+lokspel@users.noreply.github.com> Date: Fri, 22 May 2026 20:41:08 +0400 Subject: [PATCH 1/4] Fix colors --- .../arena/setup/ArenaSetupListener.java | 40 +++++++++---------- .../arena/setup/ArenaSetupManager.java | 4 +- .../manager/arena/util/ArenaUtil.java | 2 +- .../event/events/ffa/interfaces/FFAEvent.java | 4 +- .../fight/event/setup/EventSetupListener.java | 36 ++++++++--------- .../event/setup/EventSpawnMarkerManager.java | 5 +-- .../event/setup/EventWandSetupManager.java | 4 +- .../arena/arenasettings/ffa/ArenaMainGui.java | 2 +- .../arenasettings/normal/ArenaMainGui.java | 2 +- 9 files changed, 49 insertions(+), 50 deletions(-) diff --git a/core/src/main/java/dev/nandi0813/practice/manager/arena/setup/ArenaSetupListener.java b/core/src/main/java/dev/nandi0813/practice/manager/arena/setup/ArenaSetupListener.java index 2bcbb92c..bd615194 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/arena/setup/ArenaSetupListener.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/arena/setup/ArenaSetupListener.java @@ -54,7 +54,7 @@ public void onInteract(PlayerInteractEvent event) { DisplayArena displayArena = session.getArena(); if (displayArena == null) { - player.sendMessage(Common.colorize("Arena not found!")); + Common.sendMMMessage(player, "Arena not found!"); setupManager.stopSetup(player); return; } @@ -125,7 +125,7 @@ private void handleModeSwitch(Player player, ArenaSetupManager.SetupSession sess return; } setupManager.updateWand(player); - player.sendMessage(Common.colorize("Switched to: " + session.getCurrentMode().getDisplayName())); + Common.sendMMMessage(player, "Switched to: " + session.getCurrentMode().getDisplayName()); } private void handleStandardPositions(Player player, Arena arena, Action action, PlayerInteractEvent event) { @@ -145,7 +145,7 @@ private void handleStandardPositions(Player player, Arena arena, Action action, if (action == Action.LEFT_CLICK_BLOCK) { // Check minimum distance from position 2 if (arena.getPosition2() != null && arena.getPosition2().distance(loc) < 1.0) { - player.sendMessage(Common.colorize("Spawn positions must be at least 1 block apart!")); + Common.sendMMMessage(player, "Spawn positions must be at least 1 block apart!"); return; } arena.setPosition1(loc); @@ -154,7 +154,7 @@ private void handleStandardPositions(Player player, Arena arena, Action action, } else { // Check minimum distance from position 1 if (arena.getPosition1() != null && arena.getPosition1().distance(loc) < 1.0) { - player.sendMessage(Common.colorize("Spawn positions must be at least 1 block apart!")); + Common.sendMMMessage(player, "Spawn positions must be at least 1 block apart!"); return; } arena.setPosition2(loc); @@ -183,8 +183,8 @@ private void handleFFAPositions(Player player, FFAArena ffaArena, Action action, // Check minimum distance from all existing spawns (must be at least 1 block apart) for (Location existingSpawn : ffaArena.getFfaPositions()) { if (existingSpawn.distance(loc) < 1.0) { - player.sendMessage(Common.colorize("Spawn positions must be at least 1 block apart from each other!")); - player.sendMessage(Common.colorize("Too close to an existing spawn position.")); + Common.sendMMMessage(player, "Spawn positions must be at least 1 block apart from each other!"); + Common.sendMMMessage(player, "Too close to an existing spawn position."); return; } } @@ -203,9 +203,9 @@ private void handleFFAPositions(Player player, FFAArena ffaArena, Action action, ffaArena.getFfaPositions().remove(index); SpawnMarkerManager.getInstance().updateMarkers(ffaArena); updateGui(ffaArena); - player.sendMessage(Common.colorize("Removed last FFA spawn point. Remaining: " + index)); + Common.sendMMMessage(player, "Removed last FFA spawn point. Remaining: " + index); } else { - player.sendMessage(Common.colorize("No spawn points to remove.")); + Common.sendMMMessage(player, "No spawn points to remove."); } } } @@ -330,7 +330,7 @@ private void handleBuildMax(Player player, DisplayArena arena, Action action) { if (action.name().contains("LEFT")) { arena.setBuildMax(false); arena.setBuildMaxValue(ConfigManager.getInt("MATCH-SETTINGS.BUILD-LIMIT-DEFAULT")); - player.sendMessage(Common.colorize("Build Height Limit disabled for " + arena.getName())); + Common.sendMMMessage(player, "Build Height Limit disabled for " + arena.getName()); return; } @@ -352,7 +352,7 @@ private void handleDeadZone(Player player, DisplayArena arena, Action action) { if (action.name().contains("LEFT")) { arena.setDeadZone(false); - player.sendMessage(Common.colorize("Dead Zone disabled for " + arena.getName())); + Common.sendMMMessage(player, "Dead Zone disabled for " + arena.getName()); return; } @@ -550,34 +550,34 @@ public void onMarkerInteract(PlayerInteractAtEntityEvent event) { // Check if player is in setup mode if (!setupManager.isSettingUp(player)) { - player.sendMessage(Common.colorize("You must be in setup mode to remove spawn markers.")); + Common.sendMMMessage(player, "You must be in setup mode to remove spawn markers."); return; } // Find which arena this marker belongs to DisplayArena arena = SpawnMarkerManager.getInstance().getArenaForMarker(mannequin); if (arena == null) { - player.sendMessage(Common.colorize("Could not find arena for this marker.")); + Common.sendMMMessage(player, "Could not find arena for this marker."); return; } // ONLY allow for FFA arenas if (!(arena instanceof FFAArena ffaArena)) { - player.sendMessage(Common.colorize("Direct marker removal only works for FFA arenas.")); - player.sendMessage(Common.colorize("Use left/right click on blocks to set standard arena spawn positions.")); + Common.sendMMMessage(player, "Direct marker removal only works for FFA arenas."); + Common.sendMMMessage(player, "Use left/right click on blocks to set standard arena spawn positions."); return; } // Check if player is setting up this arena ArenaSetupManager.SetupSession session = setupManager.getSession(player); if (session == null || !session.getArena().equals(arena)) { - player.sendMessage(Common.colorize("You are not currently setting up this arena.")); + Common.sendMMMessage(player, "You are not currently setting up this arena."); return; } // Check if in correct mode if (session.getCurrentMode() != SetupMode.FFA_POSITIONS) { - player.sendMessage(Common.colorize("Switch to FFA Positions mode to remove spawn markers.")); + Common.sendMMMessage(player, "Switch to FFA Positions mode to remove spawn markers."); return; } @@ -587,9 +587,9 @@ public void onMarkerInteract(PlayerInteractAtEntityEvent event) { SpawnMarkerManager.getInstance().updateMarkers(arena); updateGui(arena); - player.sendMessage(Common.colorize("Removed FFA spawn. Remaining: " + ffaArena.getFfaPositions().size())); + Common.sendMMMessage(player, "Removed FFA spawn. Remaining: " + ffaArena.getFfaPositions().size()); } else { - player.sendMessage(Common.colorize("Failed to remove spawn marker.")); + Common.sendMMMessage(player, "Failed to remove spawn marker."); } } @@ -629,9 +629,9 @@ public void onMarkerDamage(EntityDamageByEntityEvent event) { ffaArena.getFfaPositions().remove(index); SpawnMarkerManager.getInstance().updateMarkers(ffaArena); updateGui(ffaArena); - player.sendMessage(Common.colorize("Removed last FFA spawn point. Remaining: " + index)); + Common.sendMMMessage(player, "Removed last FFA spawn point. Remaining: " + index); } else { - player.sendMessage(Common.colorize("No spawn points to remove.")); + Common.sendMMMessage(player, "No spawn points to remove."); } } } diff --git a/core/src/main/java/dev/nandi0813/practice/manager/arena/setup/ArenaSetupManager.java b/core/src/main/java/dev/nandi0813/practice/manager/arena/setup/ArenaSetupManager.java index eeb371c1..f6241301 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/arena/setup/ArenaSetupManager.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/arena/setup/ArenaSetupManager.java @@ -73,7 +73,7 @@ public boolean startSetup(Player player, DisplayArena arena) { // Show spawn position markers SpawnMarkerManager.getInstance().showMarkers(arena); - player.sendMessage(Common.colorize("Setup mode started for arena: " + arena.getName() + ".")); + Common.sendMMMessage(player, "Setup mode started for arena: " + arena.getName() + "."); return true; } @@ -95,7 +95,7 @@ public void stopSetup(Player player) { SpawnMarkerManager.getInstance().clearMarkers(arena); } - player.sendMessage(Common.colorize("Setup mode ended for arena: " + arena.getName() + ".")); + Common.sendMMMessage(player, "Setup mode ended for arena: " + arena.getName() + "."); } public SetupSession getSession(Player player) { diff --git a/core/src/main/java/dev/nandi0813/practice/manager/arena/util/ArenaUtil.java b/core/src/main/java/dev/nandi0813/practice/manager/arena/util/ArenaUtil.java index 80e2225e..004cbf47 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/arena/util/ArenaUtil.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/arena/util/ArenaUtil.java @@ -147,7 +147,7 @@ public static boolean changeStatus(Player player, DisplayArena arena) { List editors = new ArrayList<>(setupManager.getPlayersSettingUpArena(arena)); for (Player editor : editors) { setupManager.stopSetup(editor); - editor.sendMessage(Common.colorize("Setup mode force ended because the arena has been ENABLED!")); + Common.sendMMMessage(editor, "Setup mode force ended because the arena has been ENABLED!"); } } diff --git a/core/src/main/java/dev/nandi0813/practice/manager/fight/event/events/ffa/interfaces/FFAEvent.java b/core/src/main/java/dev/nandi0813/practice/manager/fight/event/events/ffa/interfaces/FFAEvent.java index 1f7da3c5..127625c0 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/fight/event/events/ffa/interfaces/FFAEvent.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/fight/event/events/ffa/interfaces/FFAEvent.java @@ -35,7 +35,7 @@ public FFAEvent(Object starter, EventData eventData, String languagePath) { public void teleport(final Player player) { // Safety check: ensure spawns list is not empty if (eventData.getSpawns() == null || eventData.getSpawns().isEmpty()) { - player.sendMessage(Common.colorize("Error: No spawn points configured for this event!")); + Common.sendMMMessage(player, "Error: No spawn points configured for this event!"); return; } @@ -49,7 +49,7 @@ public void teleport(final Player player) { // Safety check: ensure spawn location is valid if (spawnLocation == null || spawnLocation.getWorld() == null) { - player.sendMessage(Common.colorize("Error: Invalid spawn location!")); + Common.sendMMMessage(player, "Error: Invalid spawn location!"); return; } diff --git a/core/src/main/java/dev/nandi0813/practice/manager/fight/event/setup/EventSetupListener.java b/core/src/main/java/dev/nandi0813/practice/manager/fight/event/setup/EventSetupListener.java index 84cf9da0..845eefd9 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/fight/event/setup/EventSetupListener.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/fight/event/setup/EventSetupListener.java @@ -71,7 +71,7 @@ public void onInteract(PlayerInteractEvent event) { EventData eventData = session.getEventData(); if (eventData == null) { - player.sendMessage(Common.colorize("Event not found!")); + Common.sendMMMessage(player, "Event not found!"); setupManager.stopSetup(player); return; } @@ -193,7 +193,7 @@ public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) { if (spawnIndex < 0 || spawnIndex >= eventData.getSpawns().size()) { markerManager.updateMarkers(eventData); updateGui(eventData); - player.sendMessage(Common.colorize("This spawn marker is outdated. Markers have been refreshed.")); + Common.sendMMMessage(player, "This spawn marker is outdated. Markers have been refreshed."); return; } @@ -202,7 +202,7 @@ public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) { updateGui(eventData); scheduleSave(eventData); - player.sendMessage(Common.colorize("Removed spawn point #" + (spawnIndex + 1) + ". Remaining: " + eventData.getSpawns().size())); + Common.sendMMMessage(player, "Removed spawn point #" + (spawnIndex + 1) + ". Remaining: " + eventData.getSpawns().size()); } // Prevent damage to marker mannequins @@ -244,9 +244,9 @@ public void onMarkerDamage(EntityDamageByEntityEvent event) { EventSpawnMarkerManager.getInstance().updateMarkers(eventData); updateGui(eventData); scheduleSave(eventData); - player.sendMessage(Common.colorize("Removed last spawn point. Remaining: " + index)); + Common.sendMMMessage(player, "Removed last spawn point. Remaining: " + index); } else { - player.sendMessage(Common.colorize("No spawn points to remove.")); + Common.sendMMMessage(player, "No spawn points to remove."); } } @@ -270,7 +270,7 @@ private void handleModeSwitch(Player player, EventWandSetupManager.SetupSession } setupManager.updateWand(player); - player.sendMessage(Common.colorize("Switched to mode: " + session.getCurrentMode().getDisplayName())); + Common.sendMMMessage(player, "Switched to mode: " + session.getCurrentMode().getDisplayName()); } private void handleCornerSelection(Player player, EventData eventData, Action action, PlayerInteractEvent event) { @@ -281,7 +281,7 @@ private void handleCornerSelection(Player player, EventData eventData, Action ac Block targetBlock = event.getClickedBlock(); if (targetBlock == null || targetBlock.getType().equals(Material.AIR)) { - player.sendMessage(Common.colorize("Block location cannot be found!")); + Common.sendMMMessage(player, "Block location cannot be found!"); return; } @@ -313,7 +313,7 @@ private void handleSpawnPoints(Player player, EventData eventData, Action action } if (eventData.getCuboid() == null) { - player.sendMessage(Common.colorize("You must set corners first!")); + Common.sendMMMessage(player, "You must set corners first!"); return; } @@ -325,7 +325,7 @@ private void handleSpawnPoints(Player player, EventData eventData, Action action Location spawnLoc = getSnappedLocation(block, player); if (!eventData.getCuboid().contains(spawnLoc)) { - player.sendMessage(Common.colorize("Spawn point must be within the event cuboid!")); + Common.sendMMMessage(player, "Spawn point must be within the event cuboid!"); return; } @@ -333,7 +333,7 @@ private void handleSpawnPoints(Player player, EventData eventData, Action action eventData.addSpawn(spawnLoc); } catch (IllegalStateException ex) { // Ignore duplicate/invalid add attempts and show the setup error to the player. - player.sendMessage(Common.colorize("" + ex.getMessage())); + Common.sendMMMessage(player, "" + ex.getMessage()); return; } @@ -341,7 +341,7 @@ private void handleSpawnPoints(Player player, EventData eventData, Action action updateGui(eventData); scheduleSave(eventData); - player.sendMessage(Common.colorize("Added spawn point #" + eventData.getSpawns().size() + " at your location.")); + Common.sendMMMessage(player, "Added spawn point #" + eventData.getSpawns().size() + " at your location."); } // Left-click anywhere to remove the last spawn point else if (action == Action.LEFT_CLICK_AIR || action == Action.LEFT_CLICK_BLOCK) { @@ -351,9 +351,9 @@ else if (action == Action.LEFT_CLICK_AIR || action == Action.LEFT_CLICK_BLOCK) { EventSpawnMarkerManager.getInstance().updateMarkers(eventData); updateGui(eventData); scheduleSave(eventData); - player.sendMessage(Common.colorize("Removed last spawn point. Remaining: " + index)); + Common.sendMMMessage(player, "Removed last spawn point. Remaining: " + index); } else { - player.sendMessage(Common.colorize("No spawn points to remove.")); + Common.sendMMMessage(player, "No spawn points to remove."); } } } @@ -366,19 +366,19 @@ private void handleToggleStatus(Player player, EventData eventData, Action actio try { if (eventData.isEnabled()) { eventData.setEnabled(false); - player.sendMessage(Common.colorize("Disabled event: " + eventData.getType().getName())); + Common.sendMMMessage(player, "Disabled event: " + eventData.getType().getName()); } else { if (eventData.getCuboidLoc1() == null || eventData.getCuboidLoc2() == null) { - player.sendMessage(Common.colorize("You must set both corners first!")); + Common.sendMMMessage(player, "You must set both corners first!"); return; } if (eventData.getSpawns().isEmpty()) { - player.sendMessage(Common.colorize("You must set at least one spawn point!")); + Common.sendMMMessage(player, "You must set at least one spawn point!"); return; } eventData.setEnabled(true); - player.sendMessage(Common.colorize("Enabled event: " + eventData.getType().getName())); + Common.sendMMMessage(player, "Enabled event: " + eventData.getType().getName()); // End setup mode for all players currently setting up this event List playersSettingUp = new ArrayList<>(setupManager.getPlayersSettingUpEvent(eventData)); @@ -390,7 +390,7 @@ private void handleToggleStatus(Player player, EventData eventData, Action actio updateGui(eventData); scheduleSave(eventData); } catch (Exception e) { - player.sendMessage(Common.colorize("Error toggling status: " + e.getMessage())); + Common.sendMMMessage(player, "Error toggling status: " + e.getMessage()); } } diff --git a/core/src/main/java/dev/nandi0813/practice/manager/fight/event/setup/EventSpawnMarkerManager.java b/core/src/main/java/dev/nandi0813/practice/manager/fight/event/setup/EventSpawnMarkerManager.java index 8b737a44..c9b1e279 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/fight/event/setup/EventSpawnMarkerManager.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/fight/event/setup/EventSpawnMarkerManager.java @@ -5,7 +5,6 @@ import dev.nandi0813.practice.util.Common; import dev.nandi0813.practice.util.ItemCreateUtil; import lombok.Getter; -import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.EntityType; @@ -110,7 +109,7 @@ private Mannequin createMarker(Location location, String name) { mannequin.setGravity(false); mannequin.setCanPickupItems(false); mannequin.setCustomNameVisible(true); - mannequin.customName(Component.text(Common.colorize(name))); + mannequin.customName(Common.deserializeMiniMessage(name)); mannequin.setAI(false); mannequin.setCollidable(false); mannequin.setSilent(true); @@ -145,7 +144,7 @@ private Mannequin createLabelOnly(Location location) { labelStand.setGravity(false); labelStand.setCanPickupItems(false); labelStand.setCustomNameVisible(true); - labelStand.customName(Component.text(Common.colorize("(Right-click to remove)"))); + labelStand.customName(Common.deserializeMiniMessage("(Right-click to remove)")); labelStand.setAI(false); labelStand.setCollidable(false); labelStand.setSilent(true); diff --git a/core/src/main/java/dev/nandi0813/practice/manager/fight/event/setup/EventWandSetupManager.java b/core/src/main/java/dev/nandi0813/practice/manager/fight/event/setup/EventWandSetupManager.java index 5a6fe15e..ef2d507c 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/fight/event/setup/EventWandSetupManager.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/fight/event/setup/EventWandSetupManager.java @@ -80,7 +80,7 @@ public void startSetup(Player player, EventData eventData) { // Show spawn position markers EventSpawnMarkerManager.getInstance().showMarkers(eventData); - player.sendMessage(Common.colorize("Setup mode started for event: " + eventData.getType().getName() + ".")); + Common.sendMMMessage(player, "Setup mode started for event: " + eventData.getType().getName() + "."); } public void stopSetup(Player player) { @@ -101,7 +101,7 @@ public void stopSetup(Player player) { EventSpawnMarkerManager.getInstance().clearMarkers(eventData); } - player.sendMessage(Common.colorize("Setup mode ended for event: " + eventData.getType().getName() + ".")); + Common.sendMMMessage(player, "Setup mode ended for event: " + eventData.getType().getName() + "."); } public SetupSession getSession(Player player) { diff --git a/core/src/main/java/dev/nandi0813/practice/manager/gui/setup/arena/arenasettings/ffa/ArenaMainGui.java b/core/src/main/java/dev/nandi0813/practice/manager/gui/setup/arena/arenasettings/ffa/ArenaMainGui.java index eb5cf863..932f081f 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/gui/setup/arena/arenasettings/ffa/ArenaMainGui.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/gui/setup/arena/arenasettings/ffa/ArenaMainGui.java @@ -111,7 +111,7 @@ public void handleClickEvent(InventoryClickEvent e) { player.performCommand("arena info " + ffaArena.getName()); } else if (clickType.isRightClick()) { if (!ArenaSetupManager.getInstance().startSetup(player, ffaArena)) { - player.sendMessage(Common.colorize("You can't edit an enabled arena.")); + Common.sendMMMessage(player, "You can't edit an enabled arena."); } } break; diff --git a/core/src/main/java/dev/nandi0813/practice/manager/gui/setup/arena/arenasettings/normal/ArenaMainGui.java b/core/src/main/java/dev/nandi0813/practice/manager/gui/setup/arena/arenasettings/normal/ArenaMainGui.java index a3b97ba3..dc398040 100644 --- a/core/src/main/java/dev/nandi0813/practice/manager/gui/setup/arena/arenasettings/normal/ArenaMainGui.java +++ b/core/src/main/java/dev/nandi0813/practice/manager/gui/setup/arena/arenasettings/normal/ArenaMainGui.java @@ -94,7 +94,7 @@ public void handleClickEvent(InventoryClickEvent e) { player.performCommand("arena info " + arena.getName()); } else if (clickType.isRightClick()) { if (!ArenaSetupManager.getInstance().startSetup(player, arena)) { - player.sendMessage(Common.colorize("You can't edit an enabled arena.")); + Common.sendMMMessage(player, "You can't edit an enabled arena."); } } break; From aefbbb30d2994eb6839e9abef68cda6289bd0e57 Mon Sep 17 00:00:00 2001 From: lokspel <208148594+lokspel@users.noreply.github.com> Date: Sun, 24 May 2026 23:45:11 +0400 Subject: [PATCH 2/4] fix: keep match in liveMatches until rollback completes --- .../nandi0813/practice/manager/fight/match/Match.java | 10 ++++++++-- .../fight/match/listener/MatchLifecycleListener.java | 5 ++++- 2 files changed, 12 insertions(+), 3 deletions(-) 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..ac49d0dc 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; } 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()) From 12e3f3ae0f5a5ff287930ad4ce70758f0b07ddc4 Mon Sep 17 00:00:00 2001 From: lokspel <208148594+lokspel@users.noreply.github.com> Date: Sun, 24 May 2026 23:54:02 +0400 Subject: [PATCH 3/4] fix: set profile status to SPECTATE on match spectate --- .../java/dev/nandi0813/practice/manager/fight/match/Match.java | 1 + 1 file changed, 1 insertion(+) 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 ac49d0dc..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 @@ -469,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); From b4eda51074649385da72e2a505b40f40b0abbe3b Mon Sep 17 00:00:00 2001 From: lokspel <208148594+lokspel@users.noreply.github.com> Date: Mon, 25 May 2026 17:36:38 +0400 Subject: [PATCH 4/4] fix: prevent self-kill counting in FFA crystal deaths --- .../dev/nandi0813/practice/manager/fight/ffa/FFAListener.java | 2 +- .../dev/nandi0813/practice/manager/fight/ffa/game/FFA.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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();