From 0e31ffb9f8374f4b95216f5e6da3270722db7bf7 Mon Sep 17 00:00:00 2001 From: "Alex \"mcmonkey\" Goodwin" Date: Thu, 30 Apr 2020 05:51:10 -0700 Subject: [PATCH] Implement packet-based scoreboard team enforcement (#2127) * Implement packet-based scoreboard team enforcement This should fix incompatibility with scoreboard plugins that break the main scoreboard * impl to 1.8-1.12, move event logic, fix Setting usage * pull setting if to outside of foreach loop * fix return vs continue, minor opti as requested --- .../java/net/citizensnpcs/EventListen.java | 14 ++++++++++++++ .../citizensnpcs/trait/ScoreboardTrait.java | 7 ++++++- .../main/java/net/citizensnpcs/util/NMS.java | 4 ++++ .../java/net/citizensnpcs/util/NMSBridge.java | 2 ++ .../nms/v1_10_R1/entity/HumanController.java | 4 ++++ .../nms/v1_10_R1/util/NMSImpl.java | 18 ++++++++++++++++++ .../nms/v1_11_R1/entity/HumanController.java | 4 ++++ .../nms/v1_11_R1/util/NMSImpl.java | 18 ++++++++++++++++++ .../nms/v1_12_R1/entity/HumanController.java | 4 ++++ .../nms/v1_12_R1/util/NMSImpl.java | 18 ++++++++++++++++++ .../nms/v1_13_R2/entity/HumanController.java | 4 ++++ .../nms/v1_13_R2/util/NMSImpl.java | 18 ++++++++++++++++++ .../nms/v1_14_R1/entity/HumanController.java | 4 ++++ .../nms/v1_14_R1/util/NMSImpl.java | 18 ++++++++++++++++++ .../nms/v1_15_R1/entity/HumanController.java | 4 ++++ .../nms/v1_15_R1/util/NMSImpl.java | 18 ++++++++++++++++++ .../nms/v1_8_R3/entity/HumanController.java | 4 ++++ .../citizensnpcs/nms/v1_8_R3/util/NMSImpl.java | 18 ++++++++++++++++++ 18 files changed, 180 insertions(+), 1 deletion(-) diff --git a/main/src/main/java/net/citizensnpcs/EventListen.java b/main/src/main/java/net/citizensnpcs/EventListen.java index c0b08271c..646fe6c2e 100644 --- a/main/src/main/java/net/citizensnpcs/EventListen.java +++ b/main/src/main/java/net/citizensnpcs/EventListen.java @@ -481,6 +481,20 @@ public class EventListen implements Listener { @EventHandler(priority = EventPriority.MONITOR) public void onPlayerJoin(PlayerJoinEvent event) { skinUpdateTracker.updatePlayer(event.getPlayer(), 6 * 20, true); + + if (Setting.USE_SCOREBOARD_TEAMS.asBoolean()) { + for (NPC npc : getAllNPCs()) { + if (!(npc.getEntity() instanceof Player)) { + continue; + } + String teamName = npc.data().get(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA, ""); + Team team = null; + if (teamName.length() == 0 || (team = Bukkit.getScoreboardManager().getMainScoreboard().getTeam(teamName)) == null) + continue; + + NMS.sendTeamPacket(event.getPlayer(), team); + } + } } @EventHandler(ignoreCancelled = true) diff --git a/main/src/main/java/net/citizensnpcs/trait/ScoreboardTrait.java b/main/src/main/java/net/citizensnpcs/trait/ScoreboardTrait.java index d365e220b..036f26742 100644 --- a/main/src/main/java/net/citizensnpcs/trait/ScoreboardTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/ScoreboardTrait.java @@ -4,7 +4,9 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; +import org.bukkit.entity.Player; import org.bukkit.scoreboard.Team; import org.bukkit.scoreboard.Team.Option; import org.bukkit.scoreboard.Team.OptionStatus; @@ -90,6 +92,9 @@ public class ScoreboardTrait extends Trait { } } } + for (Player player : Bukkit.getOnlinePlayers()) { + NMS.sendTeamPacket(player, team); + } } public void removeTag(String tag) { @@ -103,4 +108,4 @@ public class ScoreboardTrait extends Trait { private static boolean SUPPORT_GLOWING_COLOR = true; private static boolean SUPPORT_TAGS = true; private static boolean SUPPORT_TEAM_SETOPTION = true; -} \ No newline at end of file +} diff --git a/main/src/main/java/net/citizensnpcs/util/NMS.java b/main/src/main/java/net/citizensnpcs/util/NMS.java index 9539a38ce..cb54a8478 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMS.java +++ b/main/src/main/java/net/citizensnpcs/util/NMS.java @@ -366,6 +366,10 @@ public class NMS { BRIDGE.sendTabListRemove(recipient, listPlayer); } + public static void sendTeamPacket(Player recipient, Team team) { + BRIDGE.sendTeamPacket(recipient, team); + } + public static void setBodyYaw(Entity entity, float yaw) { BRIDGE.setBodyYaw(entity, yaw); } diff --git a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java index 6cd6ef7fe..35f40ea31 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java +++ b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java @@ -119,6 +119,8 @@ public interface NMSBridge { public void sendTabListRemove(Player recipient, Player listPlayer); + public void sendTeamPacket(Player recipient, Team team); + public void setBodyYaw(Entity entity, float yaw); public void setDestination(Entity entity, double x, double y, double z, float speed); diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HumanController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HumanController.java index 8de8479cd..81b41f8d0 100644 --- a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HumanController.java +++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HumanController.java @@ -83,6 +83,10 @@ public class HumanController extends AbstractEntityController { team.addPlayer(handle.getBukkitEntity()); handle.getNPC().data().set(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA, teamName); + + for (Player player : Bukkit.getOnlinePlayers()) { + NMS.sendTeamPacket(player, team); + } } } }, 20); diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java index f167a91ab..2ab9c98be 100644 --- a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java +++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java @@ -191,6 +191,7 @@ import net.minecraft.server.v1_10_R1.NetworkManager; import net.minecraft.server.v1_10_R1.Packet; import net.minecraft.server.v1_10_R1.PacketPlayOutEntityTeleport; import net.minecraft.server.v1_10_R1.PacketPlayOutPlayerInfo; +import net.minecraft.server.v1_10_R1.PacketPlayOutScoreboardTeam; import net.minecraft.server.v1_10_R1.PathEntity; import net.minecraft.server.v1_10_R1.PathPoint; import net.minecraft.server.v1_10_R1.PathType; @@ -859,6 +860,23 @@ public class NMSImpl implements NMSBridge { new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entities)); } + @Override + public void sendTeamPacket(Player recipient, Team team) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(team); + + if (TEAM_FIELD == null) { + TEAM_FIELD = NMS.getGetter(team.getClass(), "team"); + } + + try { + ScoreboardTeam nmsTeam = (ScoreboardTeam) TEAM_FIELD.invoke(team); + sendPacket(recipient, new PacketPlayOutScoreboardTeam(nmsTeam, 0)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + @Override public void sendTabListRemove(Player recipient, Player listPlayer) { Preconditions.checkNotNull(recipient); diff --git a/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/entity/HumanController.java b/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/entity/HumanController.java index 8951fba9c..1da076f8d 100644 --- a/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/entity/HumanController.java +++ b/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/entity/HumanController.java @@ -83,6 +83,10 @@ public class HumanController extends AbstractEntityController { team.addPlayer(handle.getBukkitEntity()); handle.getNPC().data().set(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA, teamName); + + for (Player player : Bukkit.getOnlinePlayers()) { + NMS.sendTeamPacket(player, team); + } } } }, 20); diff --git a/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/util/NMSImpl.java b/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/util/NMSImpl.java index 9c3f8df39..fb1b84526 100644 --- a/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/util/NMSImpl.java +++ b/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/util/NMSImpl.java @@ -209,6 +209,7 @@ import net.minecraft.server.v1_11_R1.NetworkManager; import net.minecraft.server.v1_11_R1.Packet; import net.minecraft.server.v1_11_R1.PacketPlayOutEntityTeleport; import net.minecraft.server.v1_11_R1.PacketPlayOutPlayerInfo; +import net.minecraft.server.v1_11_R1.PacketPlayOutScoreboardTeam; import net.minecraft.server.v1_11_R1.PathEntity; import net.minecraft.server.v1_11_R1.PathPoint; import net.minecraft.server.v1_11_R1.PathType; @@ -926,6 +927,23 @@ public class NMSImpl implements NMSBridge { new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entity)); } + @Override + public void sendTeamPacket(Player recipient, Team team) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(team); + + if (TEAM_FIELD == null) { + TEAM_FIELD = NMS.getGetter(team.getClass(), "team"); + } + + try { + ScoreboardTeam nmsTeam = (ScoreboardTeam) TEAM_FIELD.invoke(team); + sendPacket(recipient, new PacketPlayOutScoreboardTeam(nmsTeam, 0)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + @Override public void setBodyYaw(org.bukkit.entity.Entity entity, float yaw) { getHandle(entity).yaw = yaw; diff --git a/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/entity/HumanController.java b/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/entity/HumanController.java index f3fe52d55..a5efbdb85 100644 --- a/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/entity/HumanController.java +++ b/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/entity/HumanController.java @@ -83,6 +83,10 @@ public class HumanController extends AbstractEntityController { team.addPlayer(handle.getBukkitEntity()); handle.getNPC().data().set(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA, teamName); + + for (Player player : Bukkit.getOnlinePlayers()) { + NMS.sendTeamPacket(player, team); + } } } }, 20); diff --git a/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/util/NMSImpl.java b/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/util/NMSImpl.java index 4507843e2..4c01b6a26 100644 --- a/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/util/NMSImpl.java +++ b/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/util/NMSImpl.java @@ -213,6 +213,7 @@ import net.minecraft.server.v1_12_R1.NetworkManager; import net.minecraft.server.v1_12_R1.Packet; import net.minecraft.server.v1_12_R1.PacketPlayOutEntityTeleport; import net.minecraft.server.v1_12_R1.PacketPlayOutPlayerInfo; +import net.minecraft.server.v1_12_R1.PacketPlayOutScoreboardTeam; import net.minecraft.server.v1_12_R1.PathEntity; import net.minecraft.server.v1_12_R1.PathPoint; import net.minecraft.server.v1_12_R1.PathType; @@ -923,6 +924,23 @@ public class NMSImpl implements NMSBridge { new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entities)); } + @Override + public void sendTeamPacket(Player recipient, Team team) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(team); + + if (TEAM_FIELD == null) { + TEAM_FIELD = NMS.getGetter(team.getClass(), "team"); + } + + try { + ScoreboardTeam nmsTeam = (ScoreboardTeam) TEAM_FIELD.invoke(team); + sendPacket(recipient, new PacketPlayOutScoreboardTeam(nmsTeam, 0)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + @Override public void sendTabListRemove(Player recipient, Player listPlayer) { Preconditions.checkNotNull(recipient); diff --git a/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/entity/HumanController.java b/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/entity/HumanController.java index 7b699c836..83efe547a 100644 --- a/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/entity/HumanController.java +++ b/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/entity/HumanController.java @@ -83,6 +83,10 @@ public class HumanController extends AbstractEntityController { team.addPlayer(handle.getBukkitEntity()); handle.getNPC().data().set(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA, teamName); + + for (Player player : Bukkit.getOnlinePlayers()) { + NMS.sendTeamPacket(player, team); + } } } }, 20); diff --git a/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/util/NMSImpl.java b/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/util/NMSImpl.java index da8c2cf0a..a0451e0af 100644 --- a/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/util/NMSImpl.java +++ b/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/util/NMSImpl.java @@ -228,6 +228,7 @@ import net.minecraft.server.v1_13_R2.NetworkManager; import net.minecraft.server.v1_13_R2.Packet; import net.minecraft.server.v1_13_R2.PacketPlayOutEntityTeleport; import net.minecraft.server.v1_13_R2.PacketPlayOutPlayerInfo; +import net.minecraft.server.v1_13_R2.PacketPlayOutScoreboardTeam; import net.minecraft.server.v1_13_R2.PathEntity; import net.minecraft.server.v1_13_R2.PathPoint; import net.minecraft.server.v1_13_R2.PathType; @@ -958,6 +959,23 @@ public class NMSImpl implements NMSBridge { new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entities)); } + @Override + public void sendTeamPacket(Player recipient, Team team) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(team); + + if (TEAM_FIELD == null) { + TEAM_FIELD = NMS.getGetter(team.getClass(), "team"); + } + + try { + ScoreboardTeam nmsTeam = (ScoreboardTeam) TEAM_FIELD.invoke(team); + sendPacket(recipient, new PacketPlayOutScoreboardTeam(nmsTeam, 0)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + @Override public void sendTabListRemove(Player recipient, Player listPlayer) { Preconditions.checkNotNull(recipient); diff --git a/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/entity/HumanController.java b/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/entity/HumanController.java index ae0227fb7..7f1f55cd6 100644 --- a/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/entity/HumanController.java +++ b/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/entity/HumanController.java @@ -83,6 +83,10 @@ public class HumanController extends AbstractEntityController { team.addPlayer(handle.getBukkitEntity()); handle.getNPC().data().set(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA, teamName); + + for (Player player : Bukkit.getOnlinePlayers()) { + NMS.sendTeamPacket(player, team); + } } } }, 20); diff --git a/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/NMSImpl.java b/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/NMSImpl.java index c43983364..4771cbfcd 100644 --- a/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/NMSImpl.java +++ b/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/NMSImpl.java @@ -247,6 +247,7 @@ import net.minecraft.server.v1_14_R1.NetworkManager; import net.minecraft.server.v1_14_R1.Packet; import net.minecraft.server.v1_14_R1.PacketPlayOutEntityTeleport; import net.minecraft.server.v1_14_R1.PacketPlayOutPlayerInfo; +import net.minecraft.server.v1_14_R1.PacketPlayOutScoreboardTeam; import net.minecraft.server.v1_14_R1.PathEntity; import net.minecraft.server.v1_14_R1.PathPoint; import net.minecraft.server.v1_14_R1.PathType; @@ -1021,6 +1022,23 @@ public class NMSImpl implements NMSBridge { new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entity)); } + @Override + public void sendTeamPacket(Player recipient, Team team) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(team); + + if (TEAM_FIELD == null) { + TEAM_FIELD = NMS.getGetter(team.getClass(), "team"); + } + + try { + ScoreboardTeam nmsTeam = (ScoreboardTeam) TEAM_FIELD.invoke(team); + sendPacket(recipient, new PacketPlayOutScoreboardTeam(nmsTeam, 0)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + @Override public void setBodyYaw(org.bukkit.entity.Entity entity, float yaw) { getHandle(entity).yaw = yaw; diff --git a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/HumanController.java b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/HumanController.java index 0f51ac790..09e2392a9 100644 --- a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/HumanController.java +++ b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/HumanController.java @@ -83,6 +83,10 @@ public class HumanController extends AbstractEntityController { team.addPlayer(handle.getBukkitEntity()); handle.getNPC().data().set(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA, teamName); + + for (Player player : Bukkit.getOnlinePlayers()) { + NMS.sendTeamPacket(player, team); + } } } }, 20); diff --git a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/NMSImpl.java b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/NMSImpl.java index e08999080..7bad30ab6 100644 --- a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/NMSImpl.java +++ b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/NMSImpl.java @@ -248,6 +248,7 @@ import net.minecraft.server.v1_15_R1.NetworkManager; import net.minecraft.server.v1_15_R1.Packet; import net.minecraft.server.v1_15_R1.PacketPlayOutEntityTeleport; import net.minecraft.server.v1_15_R1.PacketPlayOutPlayerInfo; +import net.minecraft.server.v1_15_R1.PacketPlayOutScoreboardTeam; import net.minecraft.server.v1_15_R1.PathEntity; import net.minecraft.server.v1_15_R1.PathPoint; import net.minecraft.server.v1_15_R1.PathType; @@ -1024,6 +1025,23 @@ public class NMSImpl implements NMSBridge { new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entity)); } + @Override + public void sendTeamPacket(Player recipient, Team team) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(team); + + if (TEAM_FIELD == null) { + TEAM_FIELD = NMS.getGetter(team.getClass(), "team"); + } + + try { + ScoreboardTeam nmsTeam = (ScoreboardTeam) TEAM_FIELD.invoke(team); + sendPacket(recipient, new PacketPlayOutScoreboardTeam(nmsTeam, 0)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + @Override public void setBodyYaw(org.bukkit.entity.Entity entity, float yaw) { getHandle(entity).yaw = yaw; diff --git a/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/entity/HumanController.java b/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/entity/HumanController.java index d723bbec7..144370666 100644 --- a/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/entity/HumanController.java +++ b/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/entity/HumanController.java @@ -83,6 +83,10 @@ public class HumanController extends AbstractEntityController { team.addPlayer(handle.getBukkitEntity()); handle.getNPC().data().set(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA, teamName); + + for (Player player : Bukkit.getOnlinePlayers()) { + NMS.sendTeamPacket(player, team); + } } } }, 20); diff --git a/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/util/NMSImpl.java b/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/util/NMSImpl.java index 5d9e01ff4..186be1b3f 100644 --- a/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/util/NMSImpl.java +++ b/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/util/NMSImpl.java @@ -165,6 +165,7 @@ import net.minecraft.server.v1_8_R3.NetworkManager; import net.minecraft.server.v1_8_R3.Packet; import net.minecraft.server.v1_8_R3.PacketPlayOutEntityTeleport; import net.minecraft.server.v1_8_R3.PacketPlayOutPlayerInfo; +import net.minecraft.server.v1_8_R3.PacketPlayOutScoreboardTeam; import net.minecraft.server.v1_8_R3.PathEntity; import net.minecraft.server.v1_8_R3.PathPoint; import net.minecraft.server.v1_8_R3.PathfinderGoalSelector; @@ -786,6 +787,23 @@ public class NMSImpl implements NMSBridge { new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entities)); } + @Override + public void sendTeamPacket(Player recipient, Team team) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(team); + + if (TEAM_FIELD == null) { + TEAM_FIELD = NMS.getField(team.getClass(), "team"); + } + + try { + ScoreboardTeam nmsTeam = (ScoreboardTeam) TEAM_FIELD.get(team); + sendPacket(recipient, new PacketPlayOutScoreboardTeam(nmsTeam, 0)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + @Override public void sendTabListRemove(Player recipient, Player listPlayer) { Preconditions.checkNotNull(recipient);