From 141eed466caf92bb8387d077773c84f59655029d Mon Sep 17 00:00:00 2001 From: R0bbyYT Date: Sat, 8 Aug 2020 23:22:58 +0200 Subject: [PATCH] Added Scoreboard interface and TabList Scoreboard --- .../server/scoreboard/BelowNameTag.java | 76 +++-------------- .../server/scoreboard/Scoreboard.java | 82 ++++++++++++++++++ .../minestom/server/scoreboard/Sidebar.java | 27 +++--- .../minestom/server/scoreboard/TabList.java | 85 +++++++++++++++++++ 4 files changed, 192 insertions(+), 78 deletions(-) create mode 100644 src/main/java/net/minestom/server/scoreboard/Scoreboard.java create mode 100644 src/main/java/net/minestom/server/scoreboard/TabList.java diff --git a/src/main/java/net/minestom/server/scoreboard/BelowNameTag.java b/src/main/java/net/minestom/server/scoreboard/BelowNameTag.java index 672aca71d..03210fc64 100644 --- a/src/main/java/net/minestom/server/scoreboard/BelowNameTag.java +++ b/src/main/java/net/minestom/server/scoreboard/BelowNameTag.java @@ -1,11 +1,7 @@ package net.minestom.server.scoreboard; -import net.minestom.server.Viewable; -import net.minestom.server.chat.ColoredText; import net.minestom.server.entity.Player; -import net.minestom.server.network.packet.server.play.DisplayScoreboardPacket; import net.minestom.server.network.packet.server.play.ScoreboardObjectivePacket; -import net.minestom.server.network.packet.server.play.UpdateScorePacket; import net.minestom.server.network.player.PlayerConnection; import java.util.Collections; @@ -15,14 +11,17 @@ import java.util.concurrent.CopyOnWriteArraySet; /** * Represents a scoreboard which rendered a tag below the name */ -public class BelowNameTag implements Viewable { +public class BelowNameTag implements Scoreboard { + + /** + * WARNING: You shouldn't create scoreboards with the same prefix as those + */ + public static final String BELOW_NAME_TAG_PREFIX = "bnt-"; private final Set viewers = new CopyOnWriteArraySet<>(); private final String objectiveName; private final ScoreboardObjectivePacket scoreboardObjectivePacket; - private final ScoreboardObjectivePacket destructionObjectivePacket; - private final DisplayScoreboardPacket displayScoreboardPacket; /** * Creates a new below name scoreboard @@ -31,63 +30,14 @@ public class BelowNameTag implements Viewable { * @param value The value of the scoreboard */ public BelowNameTag(String name, String value) { - this.objectiveName = name; + this.objectiveName = BELOW_NAME_TAG_PREFIX + name; - this.scoreboardObjectivePacket = this.getCreationObjectivePacket(value); - - this.displayScoreboardPacket = new DisplayScoreboardPacket(); - this.displayScoreboardPacket.position = 2; // Below name - this.displayScoreboardPacket.scoreName = this.objectiveName; - - this.destructionObjectivePacket = this.getDestructionObjectivePacket(); + this.scoreboardObjectivePacket = this.getCreationObjectivePacket(value, ScoreboardObjectivePacket.Type.INTEGER); } - /** - * Creates a creation objective packet for the tag below name - * - * @param value The value of the tag - * @return the creation objective packet - */ - private ScoreboardObjectivePacket getCreationObjectivePacket(String value) { - ScoreboardObjectivePacket packet = new ScoreboardObjectivePacket(); - packet.objectiveName = this.objectiveName; - packet.mode = 0; // Create/Update - packet.objectiveValue = ColoredText.of(value); - packet.type = ScoreboardObjectivePacket.Type.INTEGER; - - return packet; - } - - /** - * Creates the destruction objective packet for the tag below name - * - * @return the destruction objective packet - */ - private ScoreboardObjectivePacket getDestructionObjectivePacket() { - ScoreboardObjectivePacket packet = new ScoreboardObjectivePacket(); - packet.objectiveName = this.objectiveName; - packet.mode = 1; - packet.objectiveValue = ColoredText.of(""); - packet.type = ScoreboardObjectivePacket.Type.INTEGER; - - return packet; - } - - /** - * Updates the score of a {@link Player} - * - * @param player The player - * @param score The new score - */ - public void updateScore(Player player, int score) { - UpdateScorePacket packet = new UpdateScorePacket(); - packet.entityName = player.getUsername(); - packet.action = 0; //Create/Update - packet.objectiveName = this.objectiveName; - packet.value = score; - - // Sends to all viewers an update packet - sendPacketToViewers(packet); + @Override + public String getObjectiveName() { + return this.objectiveName; } @Override @@ -97,7 +47,7 @@ public class BelowNameTag implements Viewable { if (result) { connection.sendPacket(this.scoreboardObjectivePacket); - connection.sendPacket(this.displayScoreboardPacket); + connection.sendPacket(this.getDisplayScoreboardPacket((byte) 2)); player.setBelowNameTag(this); } @@ -111,7 +61,7 @@ public class BelowNameTag implements Viewable { PlayerConnection connection = player.getPlayerConnection(); if (result) { - connection.sendPacket(this.destructionObjectivePacket); + connection.sendPacket(this.getDestructionObjectivePacket()); player.setBelowNameTag(null); } diff --git a/src/main/java/net/minestom/server/scoreboard/Scoreboard.java b/src/main/java/net/minestom/server/scoreboard/Scoreboard.java new file mode 100644 index 000000000..2361ae226 --- /dev/null +++ b/src/main/java/net/minestom/server/scoreboard/Scoreboard.java @@ -0,0 +1,82 @@ +package net.minestom.server.scoreboard; + +import net.minestom.server.Viewable; +import net.minestom.server.chat.ColoredText; +import net.minestom.server.entity.Player; +import net.minestom.server.network.packet.server.play.DisplayScoreboardPacket; +import net.minestom.server.network.packet.server.play.ScoreboardObjectivePacket; +import net.minestom.server.network.packet.server.play.UpdateScorePacket; + +/** + * This interface represents all scoreboard of Minecraft + */ +public interface Scoreboard extends Viewable { + + /** + * Creates a creation objective packet + * + * @param value The value for the objective + * @param type The type for the objective + * @return the creation objective packet + */ + default ScoreboardObjectivePacket getCreationObjectivePacket(String value, ScoreboardObjectivePacket.Type type) { + final ScoreboardObjectivePacket packet = new ScoreboardObjectivePacket(); + packet.objectiveName = this.getObjectiveName(); + packet.mode = 0; // Create Scoreboard + packet.objectiveValue = ColoredText.of(value); + packet.type = type; + + return packet; + } + + /** + * Creates the destruction objective packet + * + * @return the destruction objective packet + */ + default ScoreboardObjectivePacket getDestructionObjectivePacket() { + final ScoreboardObjectivePacket packet = new ScoreboardObjectivePacket(); + packet.objectiveName = this.getObjectiveName(); + packet.mode = 1; // Destroy Scoreboard + + return packet; + } + + /** + * Creates the {@link DisplayScoreboardPacket} + * + * @param position The position of the scoreboard + * @return the created display scoreboard packet + */ + default DisplayScoreboardPacket getDisplayScoreboardPacket(byte position) { + final DisplayScoreboardPacket packet = new DisplayScoreboardPacket(); + packet.position = position; + packet.scoreName = this.getObjectiveName(); + + return packet; + } + + /** + * Updates the score of a {@link Player} + * + * @param player The player + * @param score The new score + */ + default void updateScore(Player player, int score) { + final UpdateScorePacket packet = new UpdateScorePacket(); + packet.entityName = player.getUsername(); + packet.action = 0; // Create/Update score + packet.objectiveName = this.getObjectiveName(); + packet.value = score; + + sendPacketsToViewers(packet); + } + + /** + * Gets the objective name of the scoreboard + * + * @return the objective name + */ + String getObjectiveName(); + +} diff --git a/src/main/java/net/minestom/server/scoreboard/Sidebar.java b/src/main/java/net/minestom/server/scoreboard/Sidebar.java index 5c4d25afd..27fdc53f6 100644 --- a/src/main/java/net/minestom/server/scoreboard/Sidebar.java +++ b/src/main/java/net/minestom/server/scoreboard/Sidebar.java @@ -1,7 +1,6 @@ package net.minestom.server.scoreboard; import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet; -import net.minestom.server.Viewable; import net.minestom.server.chat.ChatParser; import net.minestom.server.chat.ColoredText; import net.minestom.server.entity.Player; @@ -21,11 +20,13 @@ import java.util.concurrent.atomic.AtomicInteger; /** * Represents a sidebar which can contain up to 16 {@link ScoreboardLine}'s */ -public class Sidebar implements Viewable { +public class Sidebar implements Scoreboard { private static final AtomicInteger COUNTER = new AtomicInteger(); - // WARNING: you shouldn't create scoreboards/teams with the same prefixes as those + /** + * WARNING: You shouldn't create scoreboards/teams with the same prefixes as those + */ private static final String SCOREBOARD_PREFIX = "sb-"; private static final String TEAM_PREFIX = "sbt-"; @@ -173,15 +174,8 @@ public class Sidebar implements Viewable { final boolean result = this.viewers.add(player); PlayerConnection playerConnection = player.getPlayerConnection(); - ScoreboardObjectivePacket scoreboardObjectivePacket = new ScoreboardObjectivePacket(); - scoreboardObjectivePacket.objectiveName = objectiveName; - scoreboardObjectivePacket.mode = 0; // Create scoreboard - scoreboardObjectivePacket.objectiveValue = ColoredText.of(title); - scoreboardObjectivePacket.type = ScoreboardObjectivePacket.Type.INTEGER; // Type integer - - DisplayScoreboardPacket displayScoreboardPacket = new DisplayScoreboardPacket(); - displayScoreboardPacket.position = 1; // Sidebar - displayScoreboardPacket.scoreName = objectiveName; + ScoreboardObjectivePacket scoreboardObjectivePacket = this.getCreationObjectivePacket(this.title, ScoreboardObjectivePacket.Type.INTEGER); + DisplayScoreboardPacket displayScoreboardPacket = this.getDisplayScoreboardPacket((byte) 1); playerConnection.sendPacket(scoreboardObjectivePacket); // Creative objective playerConnection.sendPacket(displayScoreboardPacket); // Show sidebar scoreboard (wait for scores packet) @@ -197,9 +191,7 @@ public class Sidebar implements Viewable { public boolean removeViewer(Player player) { boolean result = this.viewers.remove(player); PlayerConnection playerConnection = player.getPlayerConnection(); - ScoreboardObjectivePacket scoreboardObjectivePacket = new ScoreboardObjectivePacket(); - scoreboardObjectivePacket.objectiveName = objectiveName; - scoreboardObjectivePacket.mode = 1; // Remove + ScoreboardObjectivePacket scoreboardObjectivePacket = this.getDestructionObjectivePacket(); playerConnection.sendPacket(scoreboardObjectivePacket); for (ScoreboardLine line : lines) { @@ -214,6 +206,11 @@ public class Sidebar implements Viewable { return viewers; } + @Override + public String getObjectiveName() { + return this.objectiveName; + } + /** * This class is used to create a line for the sidebar. */ diff --git a/src/main/java/net/minestom/server/scoreboard/TabList.java b/src/main/java/net/minestom/server/scoreboard/TabList.java new file mode 100644 index 000000000..7e9192b13 --- /dev/null +++ b/src/main/java/net/minestom/server/scoreboard/TabList.java @@ -0,0 +1,85 @@ +package net.minestom.server.scoreboard; + +import net.minestom.server.entity.Player; +import net.minestom.server.network.packet.server.play.ScoreboardObjectivePacket; +import net.minestom.server.network.player.PlayerConnection; + +import java.util.Collections; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +/** + * Represents the {@link Player} tab list as a {@link Scoreboard} + */ +public class TabList implements Scoreboard { + + /** + * WARNING: You shouldn't create scoreboards with the same prefix as those + */ + private static final String TAB_LIST_PREFIX = "tl-"; + + private final Set viewers; + private final String objectiveName; + + private ScoreboardObjectivePacket.Type type; + + public TabList(String name, ScoreboardObjectivePacket.Type type) { + this.viewers = new CopyOnWriteArraySet<>(); + this.objectiveName = TAB_LIST_PREFIX + name; + + this.type = type; + } + + /** + * Gets the scoreboard objective type + * + * @return the scoreboard objective type + */ + public ScoreboardObjectivePacket.Type getType() { + return type; + } + + /** + * Changes the scoreboard objective type + * + * @param type The new type for the objective + */ + public void setType(ScoreboardObjectivePacket.Type type) { + this.type = type; + } + + @Override + public boolean addViewer(Player player) { + boolean result = this.viewers.add(player); + PlayerConnection connection = player.getPlayerConnection(); + + if (result) { + connection.sendPacket(this.getCreationObjectivePacket("", this.type)); + connection.sendPacket(this.getDisplayScoreboardPacket((byte) 0)); + } + + return result; + } + + @Override + public boolean removeViewer(Player player) { + boolean result = this.viewers.remove(player); + PlayerConnection connection = player.getPlayerConnection(); + + if (result) { + connection.sendPacket(this.getDestructionObjectivePacket()); + } + + return result; + } + + @Override + public Set getViewers() { + return Collections.unmodifiableSet(this.viewers); + } + + @Override + public String getObjectiveName() { + return this.objectiveName; + } +}