From 18725c934f8062787d75f3813272f6ad650f6576 Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 2 Sep 2026 17:35:36 +0100 Subject: [PATCH 1/9] Remove inventory warning title --- .../MMBattlegrounds/RestrictionManager.java | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/github/minemaniauk/MMBattlegrounds/RestrictionManager.java b/src/main/java/com/github/minemaniauk/MMBattlegrounds/RestrictionManager.java index deb48be..29f4488 100644 --- a/src/main/java/com/github/minemaniauk/MMBattlegrounds/RestrictionManager.java +++ b/src/main/java/com/github/minemaniauk/MMBattlegrounds/RestrictionManager.java @@ -331,16 +331,12 @@ private void broadcastKeepInventoryState(boolean enabled) { if (!areKeepInventoryAlertsEnabled()) { return; } - - String title = enabled ? ChatColor.GREEN + "KEEP INVENTORY ON" : ChatColor.RED + "KEEP INVENTORY OFF"; - String subtitle = enabled - ? ChatColor.YELLOW + "All deaths keep items" - : ChatColor.YELLOW + "Normal death rules restored"; + String message = enabled ? "&7&l> &aKeep inventory is now force-enabled for everyone" : "&7&l> &cKeep inventory force-enable has ended. Normal rules now apply"; - broadcast(title, subtitle, message); + broadcast(message); } private void broadcastKeepInventoryManualEnable() { @@ -378,16 +374,13 @@ private void broadcastUpcomingKeepInventoryChange(long remainingTicks) { } broadcast( - ChatColor.GOLD + "KEEP INVENTORY ENDING", - ChatColor.YELLOW + "Turns off in " + formatDuration(remainingTicks), "&7&l> &eKeep inventory force-enable will end in &f" + formatDuration(remainingTicks) + "&e. Normal death rules will return after that" ); } - private void broadcast(String title, String subtitle, String message) { + private void broadcast(String message) { for (Player player : plugin.getServer().getOnlinePlayers()) { - player.sendTitle(title, subtitle, 10, 50, 20); player.sendMessage(ChatColor.translateAlternateColorCodes('&', message)); } } From 247824b407760cda999077ad4a89b1fc2d2cd961 Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 2 Sep 2026 17:36:07 +0100 Subject: [PATCH 2/9] Bump version --- pom.xml | 2 +- .../github/minemaniauk/MMBattlegrounds/RestrictionManager.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index cf5bf14..691df4d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.github.minemaniauk mmbattlegrounds - 2.0.2 + 3.0.0 jar mmbattlegrounds diff --git a/src/main/java/com/github/minemaniauk/MMBattlegrounds/RestrictionManager.java b/src/main/java/com/github/minemaniauk/MMBattlegrounds/RestrictionManager.java index 29f4488..30466d8 100644 --- a/src/main/java/com/github/minemaniauk/MMBattlegrounds/RestrictionManager.java +++ b/src/main/java/com/github/minemaniauk/MMBattlegrounds/RestrictionManager.java @@ -331,7 +331,7 @@ private void broadcastKeepInventoryState(boolean enabled) { if (!areKeepInventoryAlertsEnabled()) { return; } - + String message = enabled ? "&7&l> &aKeep inventory is now force-enabled for everyone" : "&7&l> &cKeep inventory force-enable has ended. Normal rules now apply"; From 6e32d43749a7e04cb0c5a8f88f5bde5faddfee24 Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 2 Sep 2026 17:42:34 +0100 Subject: [PATCH 3/9] Stop players taking damage after game end --- .../github/minemaniauk/MMBattlegrounds/MMBattlegrounds.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/github/minemaniauk/MMBattlegrounds/MMBattlegrounds.java b/src/main/java/com/github/minemaniauk/MMBattlegrounds/MMBattlegrounds.java index 2c065da..fe5290c 100644 --- a/src/main/java/com/github/minemaniauk/MMBattlegrounds/MMBattlegrounds.java +++ b/src/main/java/com/github/minemaniauk/MMBattlegrounds/MMBattlegrounds.java @@ -513,9 +513,7 @@ public void onPlayerDamaged(EntityDamageEvent event) { return; } - if (event.getEntity() instanceof Player) { - event.setCancelled(true); - } + event.setCancelled(true); } @EventHandler From 63060daa95659cbd29b5f70bea6e64390fd42dc0 Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 2 Sep 2026 19:54:55 +0100 Subject: [PATCH 4/9] Update supply drops These changes are to help with the new scoreboard system Added - Save last drop name in data - isDropActive() returns Boolean Changed - Only one drop can be active at once --- .../MMBattlegrounds/commands/drops/DropSpawn.java | 2 +- .../MMBattlegrounds/drops/DropManager.java | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/github/minemaniauk/MMBattlegrounds/commands/drops/DropSpawn.java b/src/main/java/com/github/minemaniauk/MMBattlegrounds/commands/drops/DropSpawn.java index 4e981ad..a8d7b2a 100644 --- a/src/main/java/com/github/minemaniauk/MMBattlegrounds/commands/drops/DropSpawn.java +++ b/src/main/java/com/github/minemaniauk/MMBattlegrounds/commands/drops/DropSpawn.java @@ -22,7 +22,7 @@ public boolean onCommand(@NonNull CommandSender sender, @NonNull Command command )); case ALREADY_ACTIVE -> sender.sendMessage(ChatColor.translateAlternateColorCodes( '&', - "&c&l> &cThat drop is already inbound" + "&c&l> &cA supply drop is already inbound" )); case INVALID_DROP -> sender.sendMessage(ChatColor.translateAlternateColorCodes( '&', diff --git a/src/main/java/com/github/minemaniauk/MMBattlegrounds/drops/DropManager.java b/src/main/java/com/github/minemaniauk/MMBattlegrounds/drops/DropManager.java index bd544c5..aec446f 100644 --- a/src/main/java/com/github/minemaniauk/MMBattlegrounds/drops/DropManager.java +++ b/src/main/java/com/github/minemaniauk/MMBattlegrounds/drops/DropManager.java @@ -217,18 +217,20 @@ public SpawnResult spawn(Drop drop) { return SpawnResult.NO_SELECTION; } - String key = activeDropKey(drop.name); - - if (activeDrops.containsKey(key)) { + if (!activeDrops.isEmpty()) { return SpawnResult.ALREADY_ACTIVE; } + String key = activeDropKey(drop.name); + DropParticleManager.ActiveArc activeArc = drop.spawn(plugin); if (activeArc == null) { return SpawnResult.INVALID_DROP; } + MMBattlegrounds.getInstance().getData().set("last-drop-name", drop.name); + activeDrops.put(key, activeArc); activeArc.future().whenComplete((location, throwable) -> activeDrops.remove(key, activeArc)); getPlugin().getRestictionManager().enableAllForDuration( @@ -257,6 +259,10 @@ public CancelResult cancel(String name) { return CancelResult.CANCELLED; } + public boolean isDropActive() { + return activeDrops.isEmpty(); + } + private void notifyDropCancelled(String name) { for (Player player : Bukkit.getOnlinePlayers()) { player.sendTitle( From 5c881358b317b3d283cabe272f11dfba97d63dc6 Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 2 Sep 2026 20:35:29 +0100 Subject: [PATCH 5/9] Update depend --- src/main/resources/plugin.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 2d577d1..cf86392 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -5,9 +5,7 @@ main: com.github.minemaniauk.MMBattlegrounds.MMBattlegrounds api-version: '26.1' depend: - FastAsyncWorldEdit -softDepend: - BetterTeams - - HomePlugin commands: startsuddendeath: permission: "mmbattlegrounds.suddendeath.start" From dd8fd5eb624d642e880c6e2fb9c66eb37c56b713 Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 2 Sep 2026 21:19:59 +0100 Subject: [PATCH 6/9] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index add93df..429ff47 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* replay_pid* +dependency-reduced-pom.xml From b4e6944310f60f02c025d8c575806c0bd434d220 Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 2 Sep 2026 21:40:47 +0100 Subject: [PATCH 7/9] Update scoreboard system --- pom.xml | 12 +- .../MMBattlegrounds/MMBattlegrounds.java | 161 ++++++++++++-- .../MMBattlegrounds/ScoreboardManager.java | 202 +++++++++++++----- .../MMBattlegrounds/drops/DropManager.java | 28 ++- .../MMBattlegrounds/homes/HomeData.java | 36 +--- 5 files changed, 339 insertions(+), 100 deletions(-) diff --git a/pom.xml b/pom.xml index 691df4d..582b163 100644 --- a/pom.xml +++ b/pom.xml @@ -88,6 +88,16 @@ 5.1.2 provided - + + net.megavex + scoreboard-library-api + 2.8.2 + + + net.megavex + scoreboard-library-implementation + 2.8.2 + runtime + diff --git a/src/main/java/com/github/minemaniauk/MMBattlegrounds/MMBattlegrounds.java b/src/main/java/com/github/minemaniauk/MMBattlegrounds/MMBattlegrounds.java index fe5290c..1cf8aba 100644 --- a/src/main/java/com/github/minemaniauk/MMBattlegrounds/MMBattlegrounds.java +++ b/src/main/java/com/github/minemaniauk/MMBattlegrounds/MMBattlegrounds.java @@ -1,8 +1,7 @@ package com.github.minemaniauk.MMBattlegrounds; -import com.booksaw.betterTeams.Main; import com.booksaw.betterTeams.Team; -import com.booksaw.betterTeams.database.BetterTeamsDatabase; +import com.booksaw.betterTeams.customEvents.*; import com.github.minemaniauk.MMBattlegrounds.commands.DropTimeTable; import com.github.minemaniauk.MMBattlegrounds.commands.ResetAllBorders; import com.github.minemaniauk.MMBattlegrounds.commands.StartSuddenDeath; @@ -15,6 +14,9 @@ import com.github.minemaniauk.MMBattlegrounds.homes.commands.HomeCommand; import com.github.minemaniauk.MMBattlegrounds.homes.commands.Homes; import com.github.minemaniauk.MMBattlegrounds.homes.commands.SetHome; +import net.megavex.scoreboardlibrary.api.ScoreboardLibrary; +import net.megavex.scoreboardlibrary.api.exception.NoPacketAdapterAvailableException; +import net.megavex.scoreboardlibrary.api.noop.NoopScoreboardLibrary; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -23,10 +25,8 @@ import org.bukkit.entity.*; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockExplodeEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.player.*; @@ -47,8 +47,9 @@ public final class MMBattlegrounds extends JavaPlugin implements Listener { private static MMBattlegrounds instance; private ScoreboardManager scoreboardManager; + private ScoreboardLibrary scoreboardLibrary; private DropManager dropManager; - private RestrictionManager restictionManager; + private RestrictionManager restrictionManager; private FileConfiguration config; private File configFile; private FileConfiguration data; @@ -82,13 +83,20 @@ public void onEnable() { 20L ); + try { + scoreboardLibrary = ScoreboardLibrary.loadScoreboardLibrary(this); + } catch (NoPacketAdapterAvailableException e) { + scoreboardLibrary = new NoopScoreboardLibrary(); + this.getLogger().warning("Server version unsupported, scoreboard functionality will not be visible!"); + } + scoreboardManager = new ScoreboardManager(); dropManager = new DropManager(this); - restictionManager = new RestrictionManager(this); + restrictionManager = new RestrictionManager(this); Bukkit.getScheduler().runTaskTimer(this, this::update, 0L, 20L); getServer().getPluginManager().registerEvents(this, this); - getServer().getPluginManager().registerEvents(restictionManager, this); + getServer().getPluginManager().registerEvents(restrictionManager, this); TeleportHelper.register(this); getCommand("startsuddendeath").setExecutor(new StartSuddenDeath()); getCommand("dropcreate").setExecutor(new DropCreate()); @@ -130,8 +138,8 @@ public void onEnable() { @Override public void onDisable() { - if (restictionManager != null) { - restictionManager.disableAllSilently(); + if (restrictionManager != null) { + restrictionManager.disableAllSilently(); } } @@ -167,6 +175,8 @@ public void onInventoryClose(InventoryCloseEvent event) { @EventHandler public void onPlayerLeave(PlayerQuitEvent event) { + scoreboardManager.removePlayerScoreBoard(event.getPlayer()); + if (isTagged(event.getPlayer())) { event.getPlayer().setHealth(0); } @@ -179,8 +189,59 @@ public void onPlayerLeave(PlayerQuitEvent event) { } } + @EventHandler + public void onTeamJoin(PlayerJoinTeamEvent event) { + Bukkit.getScheduler().runTask(this, () -> { + scoreboardManager.updatePlayerStatuses(); + }); + } + + @EventHandler + public void onTeamLeave(PlayerLeaveTeamEvent event) { + Bukkit.getScheduler().runTask(this, () -> { + scoreboardManager.updatePlayerStatuses(); + }); + } + + @EventHandler + public void onTeamCreate(CreateTeamEvent event) { + Bukkit.getScheduler().runTask(this, () -> { + scoreboardManager.updatePlayerStatuses(); + }); + } + + @EventHandler + public void onTeamDisband(DisbandTeamEvent event) { + Bukkit.getScheduler().runTask(this, () -> { + scoreboardManager.updatePlayerStatuses(); + }); + } + + @EventHandler + public void onTeamNameChange(TeamNameChangeEvent event) { + Bukkit.getScheduler().runTask(this, () -> { + scoreboardManager.updatePlayerStatuses(); + }); + } + + @EventHandler + public void onTeamTagChange(TeamTagChangeEvent event) { + Bukkit.getScheduler().runTask(this, () -> { + scoreboardManager.updatePlayerStatuses(); + }); + } + + @EventHandler + public void onTeamColorChange(TeamColorChangeEvent event) { + Bukkit.getScheduler().runTask(this, () -> { + scoreboardManager.updatePlayerStatuses(); + }); + } + + @EventHandler public void onPlayerKicked(PlayerKickEvent event) { + scoreboardManager.removePlayerScoreBoard(event.getPlayer()); combatTags.remove(event.getPlayer().getUniqueId()); if (gamePhase != GamePhase.NORMAL){ if (event.getPlayer().getGameMode() == GameMode.SURVIVAL){ @@ -285,6 +346,19 @@ public void onPlayerDeath(PlayerDeathEvent event) { if (event.getEntity().getKiller() != null){ combatTags.remove(event.getEntity().getKiller().getUniqueId()); event.getEntity().getKiller().sendMessage(ChatColor.GREEN + "You are no longer in combat"); + + // Increment player deaths + FileConfiguration playerData = loadPlayerData(player); + int playerDeaths = playerData.getInt("deaths", 0); + playerData.set("deaths", playerDeaths + 1); + savePlayerData(player, playerData); + + // Increment killer kills + Player killer = event.getEntity().getKiller(); + FileConfiguration killerData = loadPlayerData(killer); + int killerKills = killerData.getInt("kills", 0); + killerData.set("kills", killerKills + 1); + savePlayerData(killer, killerData); } if (isTagged(player)) { @@ -292,7 +366,7 @@ public void onPlayerDeath(PlayerDeathEvent event) { player.sendMessage(ChatColor.GREEN + "You are no longer in combat"); } - + scoreboardManager.updatePlayerStatuses(); if (gamePhase != GamePhase.NORMAL) { @@ -568,7 +642,7 @@ public void update() { case NORMAL: long normRemainingTimeMillis = Math.max(0L, suddenDeathScheduledStartTime - now); - scoreboardManager.update(normRemainingTimeMillis, GamePhase.NORMAL); + scoreboardManager.updateTime(normRemainingTimeMillis, GamePhase.NORMAL); break; case SUDDEN_DEATH: @@ -581,15 +655,15 @@ public void update() { return; } - scoreboardManager.update(teamDisbandRemainingMillis, GamePhase.SUDDEN_DEATH); + scoreboardManager.updateTime(teamDisbandRemainingMillis, GamePhase.SUDDEN_DEATH); break; case SUDDEN_DEATH_NO_TEAMS: - scoreboardManager.update(0L, GamePhase.SUDDEN_DEATH_NO_TEAMS); + scoreboardManager.updateTime(0L, GamePhase.SUDDEN_DEATH_NO_TEAMS); break; case GAME_OVER: - scoreboardManager.update(0L, GamePhase.GAME_OVER); + scoreboardManager.updateTime(0L, GamePhase.GAME_OVER); break; } } @@ -728,12 +802,69 @@ public void saveData() { } } + public File getPlayerDataFolder() { + File playerDataFolder = new File(getDataFolder(), "player-data"); + + if (!playerDataFolder.exists() && !playerDataFolder.mkdirs()) { + getLogger().warning("Failed to create player data folder at " + playerDataFolder.getAbsolutePath()); + } + + return playerDataFolder; + } + + public File getPlayerDataFile(Player player) { + return getPlayerDataFile(player.getUniqueId()); + } + + public File getPlayerDataFile(UUID playerId) { + return new File(getPlayerDataFolder(), playerId + ".yml"); + } + + public FileConfiguration loadPlayerData(Player player) { + return loadPlayerData(player.getUniqueId()); + } + + public FileConfiguration loadPlayerData(UUID playerId) { + return YamlConfiguration.loadConfiguration(getPlayerDataFile(playerId)); + } + + public boolean savePlayerData(Player player, FileConfiguration playerData) { + return savePlayerData(player.getUniqueId(), playerData); + } + + public boolean savePlayerData(UUID playerId, FileConfiguration playerData) { + try { + playerData.save(getPlayerDataFile(playerId)); + return true; + } catch (IOException e) { + getLogger().log(java.util.logging.Level.SEVERE, "Failed to save player data for " + playerId, e); + return false; + } + } + + public boolean deletePlayerData(Player player) { + return deletePlayerData(player.getUniqueId()); + } + + public boolean deletePlayerData(UUID playerId) { + File playerDataFile = getPlayerDataFile(playerId); + return !playerDataFile.exists() || playerDataFile.delete(); + } + + public ScoreboardLibrary getScoreboardLibrary() { + return this.scoreboardLibrary; + } + + public ScoreboardManager getScoreboardManager() { + return this.scoreboardManager; + } + public DropManager getDropManager() { return this.dropManager; } public RestrictionManager getRestictionManager() { - return this.restictionManager; + return this.restrictionManager; } public FileConfiguration getData() { diff --git a/src/main/java/com/github/minemaniauk/MMBattlegrounds/ScoreboardManager.java b/src/main/java/com/github/minemaniauk/MMBattlegrounds/ScoreboardManager.java index 5ca49da..47a294e 100644 --- a/src/main/java/com/github/minemaniauk/MMBattlegrounds/ScoreboardManager.java +++ b/src/main/java/com/github/minemaniauk/MMBattlegrounds/ScoreboardManager.java @@ -1,48 +1,79 @@ package com.github.minemaniauk.MMBattlegrounds; +import com.booksaw.betterTeams.Team; +import com.booksaw.betterTeams.team.TeamManager; +import com.github.minemaniauk.MMBattlegrounds.drops.Drop; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.megavex.scoreboardlibrary.api.ScoreboardLibrary; +import net.megavex.scoreboardlibrary.api.sidebar.Sidebar; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; +import org.bukkit.Location; import org.bukkit.entity.Player; -import org.bukkit.scoreboard.Criteria; -import org.bukkit.scoreboard.DisplaySlot; -import org.bukkit.scoreboard.Objective; -import org.bukkit.scoreboard.Scoreboard; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.UUID; public class ScoreboardManager { - public Scoreboard scoreboard; - public Objective phaseObjective; - public Objective timeObjective; + public ScoreboardLibrary library; + public Map sidebars = new HashMap<>(); public ScoreboardManager() { - scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); - phaseObjective = scoreboard.registerNewObjective("phase", Criteria.DUMMY, ChatColor.translateAlternateColorCodes('&', "&c&lPhase: &4None")); - timeObjective = scoreboard.registerNewObjective("time", Criteria.DUMMY, ChatColor.translateAlternateColorCodes('&', "&a&lTime remaining: &4None")); + library = getPlugin().getScoreboardLibrary(); } public void AddPlayerScoreBoard(Player player) { - player.setScoreboard(scoreboard); + Sidebar sidebar = library.createSidebar(); + sidebar.title( + Component.text("Breakneck ", NamedTextColor.YELLOW) + .decorate(TextDecoration.BOLD) + .append( + Component.text("BG", NamedTextColor.GOLD) + .decoration(TextDecoration.BOLD, false) + ) + ); + + sidebar.line(0, Component.empty()); + sidebar.line(1, Component.text(player.getName()).color(NamedTextColor.YELLOW)); + sidebar.line(2, getTeamComponent(player)); + //TODO SHOW DAMAGE/WEAKNESS LEVEL (Needs logic to be completed first) + //sidebar.line(3, Component.text("Damage Level: ").color(NamedTextColor.RED).append())) + + sidebar.line(4, Component.empty()); + + sidebar.line(5, getDropStatus()); + sidebar.line(6, getDropLocation()); + + sidebar.line(7, Component.empty()); + + sidebar.line(8, Component.text("Loading...").color(NamedTextColor.RED)); + sidebar.line(9, Component.text("Loading...").color(NamedTextColor.GREEN).decorate(TextDecoration.BOLD)); + + sidebars.put(player.getUniqueId(), sidebar); + sidebar.addPlayer(player); } - private String lastTimeLine = null; + public void removePlayerScoreBoard(Player player) { + Sidebar sidebar = sidebars.get(player.getUniqueId()); + sidebar.close(); + sidebars.remove(player.getUniqueId()); + } - public void update(long remainingTime, GamePhase phase) { + public void updateTime(long remainingTime, GamePhase phase) { long remainingTimeSeconds = Math.max(0L, remainingTime / 1000L); - if (lastTimeLine != null) { - phaseObjective.getScoreboard().resetScores(lastTimeLine); - lastTimeLine = null; - } - switch (phase) { case NORMAL: if (remainingTimeSeconds == 0L) { - phaseObjective.setDisplayName(ChatColor.RED + "Waiting for sudden death..."); - - lastTimeLine = ChatColor.GREEN.toString() + ChatColor.BOLD + "0d 0h 0m"; - phaseObjective.getScore(lastTimeLine).setScore(1); - - phaseObjective.setDisplaySlot(DisplaySlot.SIDEBAR); + updatePhaseLines( + Component.text("Waiting for sudden death...").color(NamedTextColor.RED), + Component.text("0d 0h 0m").color(NamedTextColor.GREEN).decorate(TextDecoration.BOLD) + ); return; } @@ -51,46 +82,119 @@ public void update(long remainingTime, GamePhase phase) { long normMinutes = (remainingTimeSeconds % 3600) / 60; long normSeconds = remainingTimeSeconds % 60; - phaseObjective.setDisplayName(ChatColor.RED + "Sudden Death in:"); - - lastTimeLine = ChatColor.GREEN.toString() + ChatColor.BOLD - + normDays + "d " + normHours + "h " + normMinutes + "m " + normSeconds + "s"; - - phaseObjective.getScore(lastTimeLine).setScore(1); - phaseObjective.setDisplaySlot(DisplaySlot.SIDEBAR); + updatePhaseLines( + Component.text("Sudden Death in:").color(NamedTextColor.RED), + Component.text(normDays + "d " + normHours + "h " + normMinutes + "m " + normSeconds + "s") + .color(NamedTextColor.GREEN) + .decorate(TextDecoration.BOLD) + ); break; case SUDDEN_DEATH: long sdMinutes = remainingTimeSeconds / 60; long sdSeconds = remainingTimeSeconds % 60; - phaseObjective.setDisplayName(ChatColor.RED + "Teams disband in:"); + updatePhaseLines( + Component.text("Teams disband in:").color(NamedTextColor.RED), + Component.text(sdMinutes + "m " + sdSeconds + "s") + .color(NamedTextColor.GREEN) + .decorate(TextDecoration.BOLD) + ); + break; - lastTimeLine = ChatColor.GREEN.toString() + ChatColor.BOLD - + sdMinutes + "m " + sdSeconds + "s"; + case SUDDEN_DEATH_NO_TEAMS: + updatePhaseLines( + Component.text("Last stand").color(NamedTextColor.RED).decorate(TextDecoration.BOLD), + Component.text("Everyone for themselves").color(NamedTextColor.DARK_RED) + ); + break; - phaseObjective.getScore(lastTimeLine).setScore(1); - phaseObjective.setDisplaySlot(DisplaySlot.SIDEBAR); + case GAME_OVER: + updatePhaseLines( + Component.text("GAME OVER").color(NamedTextColor.RED).decorate(TextDecoration.BOLD), + Component.text("Thanks for playing").color(NamedTextColor.GRAY) + ); break; + } + } - case SUDDEN_DEATH_NO_TEAMS: - phaseObjective.setDisplayName(ChatColor.RED.toString() + ChatColor.BOLD + "Last stand"); + private void updatePhaseLines(Component phaseLine, Component timeLine) { + for (Sidebar sidebar : sidebars.values()) { + sidebar.line(8, phaseLine); + sidebar.line(9, timeLine); + } + } - lastTimeLine = ChatColor.DARK_RED + "Everyone for themselves"; - phaseObjective.getScore(lastTimeLine).setScore(1); + public void updateDropStatuses() { + for (Sidebar sidebar : sidebars.values()) { + sidebar.line(5, getDropStatus()); + sidebar.line(6, getDropLocation()); + } + } - phaseObjective.setDisplaySlot(DisplaySlot.SIDEBAR); - break; + public void updatePlayerStatuses() { + for (Map.Entry entry : sidebars.entrySet()) { + Player p = Bukkit.getPlayer(entry.getKey()); + Sidebar sidebar = entry.getValue(); - case GAME_OVER: - phaseObjective.setDisplayName(ChatColor.RED.toString() + ChatColor.BOLD + "GAME OVER"); + sidebar.line(1, Component.text(p.getName()).color(NamedTextColor.YELLOW)); + sidebar.line(2, getTeamComponent(p)); + //TODO SHOW DAMAGE LEVEL (Needs damage level logic to be completed first) + //sidebar.line(2, Component.text("Damage Level: ").color(NamedTextColor.RED).append())) + } + } - lastTimeLine = ChatColor.GRAY + "Thanks for playing"; - phaseObjective.getScore(lastTimeLine).setScore(1); + private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); - phaseObjective.setDisplaySlot(DisplaySlot.SIDEBAR); - break; + public static Component getTeamComponent(Player player) { + if (!Bukkit.getPluginManager().isPluginEnabled("BetterTeams")) { + return Component.text("No Team", NamedTextColor.GRAY); + } + + Team team = Team.getTeam(player); + + if (team == null) { + return Component.text("No Team", NamedTextColor.GRAY); + } + + return MINI_MESSAGE.deserialize(team.getTag()); + } + + private Component getDropStatus() { + String lastDropName = getPlugin().getData().getString("last-drop-name"); + + if (getPlugin().getDropManager().isDropActive()) { + return Component.text("Drop Inbound...").color(NamedTextColor.RED); + } + + if (getPlugin().getDropManager().wasLastDropCancelled()) { + return Component.text("Drop Cancelled...").color(NamedTextColor.DARK_RED); } + + if (lastDropName == null || lastDropName.isEmpty()) { + return Component.text("No Drop").color(NamedTextColor.RED); + } + + return Component.text("Drop Landed...").color(NamedTextColor.RED); } + private Component getDropLocation() { + String lastDropName = getPlugin().getData().getString("last-drop-name"); + + if (lastDropName == null || lastDropName.isEmpty() || getPlugin().getDropManager().wasLastDropCancelled()) { + return Component.text("X:- Z:-").color(NamedTextColor.GREEN).decorate(TextDecoration.BOLD); + } + + Drop drop = getPlugin().getDropManager().getDrop(lastDropName); + if (drop == null) { + return Component.text("X:- Z:-").color(NamedTextColor.GREEN).decorate(TextDecoration.BOLD); + } + + Location dropLocation = drop.location; + return Component.text("X:" + dropLocation.getBlockX() + " Z:" + dropLocation.getBlockZ()).color(NamedTextColor.GREEN).decorate(TextDecoration.BOLD); + } + + private MMBattlegrounds getPlugin() { + return MMBattlegrounds.getInstance(); + } } diff --git a/src/main/java/com/github/minemaniauk/MMBattlegrounds/drops/DropManager.java b/src/main/java/com/github/minemaniauk/MMBattlegrounds/drops/DropManager.java index aec446f..f79b99e 100644 --- a/src/main/java/com/github/minemaniauk/MMBattlegrounds/drops/DropManager.java +++ b/src/main/java/com/github/minemaniauk/MMBattlegrounds/drops/DropManager.java @@ -46,6 +46,7 @@ public enum CancelResult { public HashMap selectedDrop = new HashMap<>(); private final Map activeDrops = new HashMap<>(); private final Map activeEditorSessions = new HashMap<>(); + private boolean lastDropCancelled; public DropManager(JavaPlugin plugin) { this.plugin = plugin; @@ -229,10 +230,17 @@ public SpawnResult spawn(Drop drop) { return SpawnResult.INVALID_DROP; } - MMBattlegrounds.getInstance().getData().set("last-drop-name", drop.name); - activeDrops.put(key, activeArc); - activeArc.future().whenComplete((location, throwable) -> activeDrops.remove(key, activeArc)); + lastDropCancelled = false; + getPlugin().getData().set("last-drop-name", drop.name); + getPlugin().saveData(); + getPlugin().getScoreboardManager().updateDropStatuses(); + + activeArc.future().whenComplete((location, throwable) -> { + if (activeDrops.remove(key, activeArc)) { + getPlugin().getScoreboardManager().updateDropStatuses(); + } + }); getPlugin().getRestictionManager().enableAllForDuration( getPlugin().getRestictionManager().getDropKeepInventoryDurationTicks() ); @@ -245,12 +253,18 @@ public CancelResult cancel(String name) { } String key = activeDropKey(name); - DropParticleManager.ActiveArc activeArc = activeDrops.remove(key); + DropParticleManager.ActiveArc activeArc = activeDrops.get(key); if (activeArc == null || !activeArc.cancel()) { return CancelResult.NOT_ACTIVE; } + activeDrops.remove(key, activeArc); + lastDropCancelled = true; + getPlugin().getData().set("last-drop-name", null); + getPlugin().saveData(); + getPlugin().getScoreboardManager().updateDropStatuses(); + if (activeDrops.isEmpty()) { getPlugin().getRestictionManager().disableAll(); } @@ -260,7 +274,11 @@ public CancelResult cancel(String name) { } public boolean isDropActive() { - return activeDrops.isEmpty(); + return !activeDrops.isEmpty(); + } + + public boolean wasLastDropCancelled() { + return lastDropCancelled; } private void notifyDropCancelled(String name) { diff --git a/src/main/java/com/github/minemaniauk/MMBattlegrounds/homes/HomeData.java b/src/main/java/com/github/minemaniauk/MMBattlegrounds/homes/HomeData.java index f44e65a..1a5cf22 100644 --- a/src/main/java/com/github/minemaniauk/MMBattlegrounds/homes/HomeData.java +++ b/src/main/java/com/github/minemaniauk/MMBattlegrounds/homes/HomeData.java @@ -6,11 +6,8 @@ import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; -import java.io.File; -import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.logging.Level; public class HomeData { public Player player; @@ -36,30 +33,17 @@ public void removeHome(Home home) { } public void save() { - File playerFile = getPlayerFile(player); + FileConfiguration dataFile = new YamlConfiguration(); - try { - File parent = playerFile.getParentFile(); - if (parent != null && !parent.exists() && !parent.mkdirs()) { - throw new IOException("Failed to create home data folder at " + parent.getAbsolutePath()); - } - - FileConfiguration dataFile = new YamlConfiguration(); - - for (Map.Entry entry : homes.entrySet()) { - dataFile.set(entry.getKey() + ".location", entry.getValue().location); - } - - dataFile.save(playerFile); - } catch (IOException e) { - MMBattlegrounds.getInstance().getLogger().log(Level.SEVERE, "Something went wrong saving home data", e); + for (Map.Entry entry : homes.entrySet()) { + dataFile.set(entry.getKey() + ".location", entry.getValue().location); } + + MMBattlegrounds.getInstance().savePlayerData(player, dataFile); } public static HomeData load(Player player) { - File playerFile = getPlayerFile(player); - - FileConfiguration dataFile = YamlConfiguration.loadConfiguration(playerFile); + FileConfiguration dataFile = MMBattlegrounds.getInstance().loadPlayerData(player); HashMap homeMap = new HashMap<>(); for (String key : dataFile.getKeys(false)) { @@ -73,12 +57,4 @@ public static HomeData load(Player player) { return new HomeData(player, homeMap); } - - private static File getPlayerFile(Player player) { - return new File(getHomesFolder(), player.getUniqueId() + ".yml"); - } - - private static File getHomesFolder() { - return new File(MMBattlegrounds.getInstance().getDataFolder(), "player-data"); - } } From 1df7fec5344d31a7ff4b853b4b5cbf97cf7de561 Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 2 Sep 2026 21:56:13 +0100 Subject: [PATCH 8/9] Reorder scoreboard and add kill counter --- .../MMBattlegrounds/ScoreboardManager.java | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/github/minemaniauk/MMBattlegrounds/ScoreboardManager.java b/src/main/java/com/github/minemaniauk/MMBattlegrounds/ScoreboardManager.java index 47a294e..007792b 100644 --- a/src/main/java/com/github/minemaniauk/MMBattlegrounds/ScoreboardManager.java +++ b/src/main/java/com/github/minemaniauk/MMBattlegrounds/ScoreboardManager.java @@ -40,19 +40,29 @@ public void AddPlayerScoreBoard(Player player) { sidebar.line(0, Component.empty()); sidebar.line(1, Component.text(player.getName()).color(NamedTextColor.YELLOW)); - sidebar.line(2, getTeamComponent(player)); + sidebar.line( + 2, + Component.text("Kills: ", NamedTextColor.RED) + .append(Component.text( + getPlugin().loadPlayerData(player).getInt("kills", 0), + NamedTextColor.DARK_RED + )) + ); + //TODO SHOW DAMAGE/WEAKNESS LEVEL (Needs logic to be completed first) //sidebar.line(3, Component.text("Damage Level: ").color(NamedTextColor.RED).append())) - sidebar.line(4, Component.empty()); + sidebar.line(4, getTeamComponent(player)); + + sidebar.line(5, Component.empty()); - sidebar.line(5, getDropStatus()); - sidebar.line(6, getDropLocation()); + sidebar.line(6, getDropStatus()); + sidebar.line(7, getDropLocation()); - sidebar.line(7, Component.empty()); + sidebar.line(8, Component.empty()); - sidebar.line(8, Component.text("Loading...").color(NamedTextColor.RED)); - sidebar.line(9, Component.text("Loading...").color(NamedTextColor.GREEN).decorate(TextDecoration.BOLD)); + sidebar.line(9, Component.text("Loading...").color(NamedTextColor.RED)); + sidebar.line(10, Component.text("Loading...").color(NamedTextColor.GREEN).decorate(TextDecoration.BOLD)); sidebars.put(player.getUniqueId(), sidebar); sidebar.addPlayer(player); @@ -120,15 +130,15 @@ public void updateTime(long remainingTime, GamePhase phase) { private void updatePhaseLines(Component phaseLine, Component timeLine) { for (Sidebar sidebar : sidebars.values()) { - sidebar.line(8, phaseLine); - sidebar.line(9, timeLine); + sidebar.line(9, phaseLine); + sidebar.line(10, timeLine); } } public void updateDropStatuses() { for (Sidebar sidebar : sidebars.values()) { - sidebar.line(5, getDropStatus()); - sidebar.line(6, getDropLocation()); + sidebar.line(6, getDropStatus()); + sidebar.line(7, getDropLocation()); } } @@ -138,9 +148,19 @@ public void updatePlayerStatuses() { Sidebar sidebar = entry.getValue(); sidebar.line(1, Component.text(p.getName()).color(NamedTextColor.YELLOW)); - sidebar.line(2, getTeamComponent(p)); + sidebar.line( + 2, + Component.text("Kills: ", NamedTextColor.RED) + .append(Component.text( + getPlugin().loadPlayerData(p).getInt("kills", 0), + NamedTextColor.DARK_RED + )) + ); + //TODO SHOW DAMAGE LEVEL (Needs damage level logic to be completed first) - //sidebar.line(2, Component.text("Damage Level: ").color(NamedTextColor.RED).append())) + //sidebar.line(3, Component.text("Damage Level: ").color(NamedTextColor.RED).append())) + + sidebar.line(4, getTeamComponent(p)); } } From e964d4a69129b986707d9bfd609436af2dda189b Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 2 Sep 2026 22:00:57 +0100 Subject: [PATCH 9/9] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 617124b..4d283b9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MMBattlegrounds -MMBattlegrounds is the plugin used in the server internally known as batt2 it is NOT a plugin used on the battlegrounds smp +MMBattlegrounds is the plugin used in the server Breakneck Battlegrounds it is NOT a plugin used on the battlegrounds smp > **Versioning** >