From 8c23df8f9c61a692d84693380b159b0a9bbc0147 Mon Sep 17 00:00:00 2001 From: Cryptite Date: Tue, 21 Sep 2021 15:33:46 -0500 Subject: [PATCH] Multiple Entries with Scoreboards --- ...02-Multiple-Entries-with-Scoreboards.patch | 58 ++++++ ...03-Multiple-Entries-with-Scoreboards.patch | 188 ++++++++++++++++++ 2 files changed, 246 insertions(+) create mode 100644 patches/api/0002-Multiple-Entries-with-Scoreboards.patch create mode 100644 patches/server/0003-Multiple-Entries-with-Scoreboards.patch diff --git a/patches/api/0002-Multiple-Entries-with-Scoreboards.patch b/patches/api/0002-Multiple-Entries-with-Scoreboards.patch new file mode 100644 index 000000000..778fcb352 --- /dev/null +++ b/patches/api/0002-Multiple-Entries-with-Scoreboards.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Tue, 21 Sep 2021 15:20:16 -0500 +Subject: [PATCH] Multiple Entries with Scoreboards + + +diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java +index 30fce0df75494eb9b7409f08ea3d6ff894f7c79f..f9082679ae88677145ae9c9ca0a425b6a5bc3348 100644 +--- a/src/main/java/org/bukkit/scoreboard/Team.java ++++ b/src/main/java/org/bukkit/scoreboard/Team.java +@@ -1,5 +1,6 @@ + package org.bukkit.scoreboard; + ++import java.util.Collection; // Paper + import java.util.Set; + import org.bukkit.ChatColor; + import org.bukkit.OfflinePlayer; +@@ -319,6 +320,20 @@ public interface Team { + */ + void addEntry(@NotNull String entry) throws IllegalStateException, IllegalArgumentException; + ++ // Paper start ++ /** ++ * This puts a collection of entries onto this team for the scoreboard which results in one ++ * packet for the updates rather than a packet-per-entry. ++ *

++ * Entries on other teams will be removed from their respective teams. ++ * ++ * @param entries the entries to add ++ * @throws IllegalArgumentException if entries are null ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ void addEntries(@NotNull Collection entries) throws IllegalStateException, IllegalArgumentException; ++ // Paper end ++ + /** + * Removes the player from this team. + * +@@ -342,6 +357,19 @@ public interface Team { + */ + boolean removeEntry(@NotNull String entry) throws IllegalStateException, IllegalArgumentException; + ++ // Paper start ++ /** ++ * Removes a collection of entries from this team which results in one ++ * packet for the updates rather than a packet-per-entry. ++ * ++ * @param entries the entries to remove ++ * @return if any of the entries were a part of this team ++ * @throws IllegalArgumentException if entry is null ++ * @throws IllegalStateException if this team has been unregistered ++ */ ++ boolean removeEntries(@NotNull Collection entries) throws IllegalStateException, IllegalArgumentException; ++ // Paper end ++ + /** + * Unregisters this team from the Scoreboard + * diff --git a/patches/server/0003-Multiple-Entries-with-Scoreboards.patch b/patches/server/0003-Multiple-Entries-with-Scoreboards.patch new file mode 100644 index 000000000..b9bac16e6 --- /dev/null +++ b/patches/server/0003-Multiple-Entries-with-Scoreboards.patch @@ -0,0 +1,188 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Tue, 21 Sep 2021 15:20:15 -0500 +Subject: [PATCH] Multiple Entries with Scoreboards + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java +index 4c9660176e783999301565790b8cf6f47b0d02a2..3f1b093ae766c6e219ee233a75c64f0c522cc6c2 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java +@@ -42,6 +42,12 @@ public class ClientboundSetPlayerTeamPacket implements Packet players, ClientboundSetPlayerTeamPacket.Action operation) { ++ return new ClientboundSetPlayerTeamPacket(team.getName(), operation == ClientboundSetPlayerTeamPacket.Action.ADD ? 3 : 4, Optional.empty(), players); ++ } ++ // Paper end ++ + public ClientboundSetPlayerTeamPacket(FriendlyByteBuf buf) { + this.name = buf.readUtf(16); + this.method = buf.readByte(); +diff --git a/src/main/java/net/minecraft/server/ServerScoreboard.java b/src/main/java/net/minecraft/server/ServerScoreboard.java +index 130a928f156961bae9ca184b3ca31004dbba1012..5d42967b1d9cbceb004566c0c503df21d1bb5c51 100644 +--- a/src/main/java/net/minecraft/server/ServerScoreboard.java ++++ b/src/main/java/net/minecraft/server/ServerScoreboard.java +@@ -3,6 +3,7 @@ package net.minecraft.server; + import com.google.common.collect.Lists; + import com.google.common.collect.Sets; + import java.util.Iterator; ++import java.util.Collection; // Paper + import java.util.List; + import java.util.Objects; + import java.util.Set; +@@ -92,6 +93,19 @@ public class ServerScoreboard extends Scoreboard { + } + } + ++ // Paper start ++ @Override ++ public boolean addPlayersToTeam(Collection players, PlayerTeam team) { ++ if (super.addPlayersToTeam(players, team)) { ++ this.sendAll(ClientboundSetPlayerTeamPacket.createMultiplePlayerPacket(team, players, ClientboundSetPlayerTeamPacket.Action.ADD)); ++ this.setDirty(); ++ return true; ++ } else { ++ return false; ++ } ++ } ++ // Paper end ++ + @Override + public void removePlayerFromTeam(String playerName, PlayerTeam team) { + super.removePlayerFromTeam(playerName, team); +@@ -99,6 +113,19 @@ public class ServerScoreboard extends Scoreboard { + this.setDirty(); + } + ++ // Paper start ++ @Override ++ public boolean removePlayersFromTeam(Collection players, PlayerTeam team) { ++ if (super.removePlayersFromTeam(players, team)) { ++ this.sendAll(ClientboundSetPlayerTeamPacket.createMultiplePlayerPacket(team, players, ClientboundSetPlayerTeamPacket.Action.REMOVE)); ++ this.setDirty(); ++ return true; ++ } else { ++ return false; ++ } ++ } ++ // Paper end ++ + @Override + public void onObjectiveAdded(Objective objective) { + super.onObjectiveAdded(objective); +diff --git a/src/main/java/net/minecraft/world/scores/Scoreboard.java b/src/main/java/net/minecraft/world/scores/Scoreboard.java +index 3e75ea4d5a6c83ca570b29e3c1a5d51fb132379a..246bb45d73c3948fae081662995ada7cdb49822d 100644 +--- a/src/main/java/net/minecraft/world/scores/Scoreboard.java ++++ b/src/main/java/net/minecraft/world/scores/Scoreboard.java +@@ -224,6 +224,28 @@ public class Scoreboard { + } + } + ++ // Paper start ++ public boolean addPlayersToTeam(Collection players, PlayerTeam team) { ++ boolean anyAdded = false; ++ for (String playerName : players) { ++ if (playerName.length() > 40) { ++ net.minecraft.server.MinecraftServer.LOGGER.warn("The player name '" + playerName + "' is too long!"); ++ } else { ++ if (this.getPlayersTeam(playerName) != null) { ++ this.removePlayerFromTeam(playerName); ++ } ++ ++ this.teamsByPlayer.put(playerName, team); ++ if (team.getPlayers().add(playerName)) { ++ anyAdded = true; ++ } ++ } ++ } ++ ++ return anyAdded; ++ } ++ // Paper end ++ + public boolean removePlayerFromTeam(String playerName) { + PlayerTeam playerTeam = this.getPlayersTeam(playerName); + if (playerTeam != null) { +@@ -243,6 +265,24 @@ public class Scoreboard { + } + } + ++ // Paper start ++ public boolean removePlayersFromTeam(Collection players, PlayerTeam team) { ++ boolean anyRemoved = false; ++ for (String playerName : players) { ++ if (this.getPlayersTeam(playerName) != team) { ++ net.minecraft.server.MinecraftServer.LOGGER.warn("Player " + playerName + " is either on another team or not on any team. Cannot remove from team '" + team.getName() + "'."); ++ } else { ++ this.teamsByPlayer.remove(playerName); ++ if (team.getPlayers().remove(playerName)) { ++ anyRemoved = true; ++ } ++ } ++ } ++ ++ return anyRemoved; ++ } ++ // Paper end ++ + public Collection getTeamNames() { + return this.teamsByName.keySet(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +index 2b87a652798cb632fe76bf20e9e7f8cb8bfb3b7b..f097e9fbdac1a572c12cc0299774455c75e373e9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +@@ -1,6 +1,7 @@ + package org.bukkit.craftbukkit.scoreboard; + + import com.google.common.collect.ImmutableSet; ++import java.util.Collection; // Paper + import java.util.Set; + import net.minecraft.world.scores.PlayerTeam; + import net.minecraft.world.scores.Team.Visibility; +@@ -226,6 +227,16 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { + scoreboard.board.addPlayerToTeam(entry, team); + } + ++ // Paper start ++ @Override ++ public void addEntries(Collection entries) throws IllegalStateException, IllegalArgumentException { ++ Validate.notNull(entries, "Entries cannot be null"); ++ CraftScoreboard scoreboard = checkState(); ++ ++ scoreboard.board.addPlayersToTeam(entries, team); ++ } ++ // Paper end ++ + @Override + public boolean removePlayer(OfflinePlayer player) throws IllegalStateException, IllegalArgumentException { + Validate.notNull(player, "OfflinePlayer cannot be null"); +@@ -245,6 +256,25 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { + return true; + } + ++ // Paper start ++ @Override ++ public boolean removeEntries(Collection entries) throws IllegalStateException, IllegalArgumentException { ++ Validate.notNull(entries, "Entry cannot be null"); ++ CraftScoreboard scoreboard = this.checkState(); ++ ++ boolean anyRemoved = false; ++ Collection teamPlayers = this.team.getPlayers(); ++ for (String entry : entries) { ++ if (teamPlayers.remove(entry)) { ++ anyRemoved = true; ++ } ++ } ++ ++ scoreboard.board.removePlayersFromTeam(entries, team); ++ return anyRemoved; ++ } ++ // Paper end ++ + @Override + public boolean hasPlayer(OfflinePlayer player) throws IllegalArgumentException, IllegalStateException { + Validate.notNull(player, "OfflinePlayer cannot be null");