mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-03 23:17:48 +01:00
Merge remote-tracking branch 'origin/feature/scoreboard'
# Conflicts: # src/main/java/net/minestom/server/entity/Player.java
This commit is contained in:
commit
91de2ee6a2
@ -13,6 +13,7 @@ import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.scoreboard.Team;
|
||||
import net.minestom.server.sound.Sound;
|
||||
import net.minestom.server.sound.SoundCategory;
|
||||
import net.minestom.server.utils.Position;
|
||||
@ -55,6 +56,8 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
*/
|
||||
private long fireDamagePeriod = 1000L;
|
||||
|
||||
private Team team;
|
||||
|
||||
public LivingEntity(EntityType entityType, Position spawnPosition) {
|
||||
super(entityType, spawnPosition);
|
||||
setupAttributes();
|
||||
@ -522,4 +525,40 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
fireDamagePeriod = timeUnit.toMilliseconds(fireDamagePeriod);
|
||||
this.fireDamagePeriod = fireDamagePeriod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the {@link Team} for the entity
|
||||
*
|
||||
* @param team The new team
|
||||
*/
|
||||
public void setTeam(Team team) {
|
||||
if (this.team == team) return;
|
||||
|
||||
String member;
|
||||
|
||||
if (this instanceof Player) {
|
||||
Player player = (Player) this;
|
||||
member = player.getUsername();
|
||||
} else {
|
||||
member = this.uuid.toString();
|
||||
}
|
||||
|
||||
if (this.team != null) {
|
||||
this.team.removeMember(member);
|
||||
}
|
||||
|
||||
this.team = team;
|
||||
if (team != null) {
|
||||
team.addMember(member);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Team} of the entity
|
||||
*
|
||||
* @return the {@link Team}
|
||||
*/
|
||||
public Team getTeam() {
|
||||
return team;
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,24 @@ import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
|
||||
public class ScoreboardObjectivePacket implements ServerPacket {
|
||||
|
||||
/**
|
||||
* An unique name for the objective
|
||||
*/
|
||||
public String objectiveName;
|
||||
/**
|
||||
* 0 = create the scoreboard <br>
|
||||
* 1 = to remove the scoreboard<br>
|
||||
* 2 = to update the display text
|
||||
*/
|
||||
public byte mode;
|
||||
/**
|
||||
* The text to be displayed for the score
|
||||
*/
|
||||
public ColoredText objectiveValue;
|
||||
public int type;
|
||||
/**
|
||||
* The type how the score is displayed
|
||||
*/
|
||||
public Type type;
|
||||
|
||||
@Override
|
||||
public void write(PacketWriter writer) {
|
||||
@ -19,7 +33,7 @@ public class ScoreboardObjectivePacket implements ServerPacket {
|
||||
|
||||
if (mode == 0 || mode == 2) {
|
||||
writer.writeSizedString(objectiveValue.toString());
|
||||
writer.writeVarInt(type);
|
||||
writer.writeVarInt(type.ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,4 +41,12 @@ public class ScoreboardObjectivePacket implements ServerPacket {
|
||||
public int getId() {
|
||||
return ServerPacketIdentifier.SCOREBOARD_OBJECTIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This enumeration represents all available types for the scoreboard objective
|
||||
*/
|
||||
public enum Type {
|
||||
INTEGER,
|
||||
HEARTS
|
||||
}
|
||||
}
|
||||
|
@ -4,35 +4,73 @@ import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
|
||||
/**
|
||||
* The packet creates or updates teams
|
||||
*/
|
||||
public class TeamsPacket implements ServerPacket {
|
||||
|
||||
/**
|
||||
* The registry name of the team
|
||||
*/
|
||||
public String teamName;
|
||||
/**
|
||||
* The action of the packet
|
||||
*/
|
||||
public Action action;
|
||||
|
||||
/**
|
||||
* The display name for the team
|
||||
*/
|
||||
public String teamDisplayName;
|
||||
/**
|
||||
* The friendly flags to
|
||||
*/
|
||||
public byte friendlyFlags;
|
||||
/**
|
||||
* Visibility state for the name tag
|
||||
*/
|
||||
public NameTagVisibility nameTagVisibility;
|
||||
/**
|
||||
* Rule for the collision
|
||||
*/
|
||||
public CollisionRule collisionRule;
|
||||
/**
|
||||
* The color of the team
|
||||
*/
|
||||
public int teamColor;
|
||||
/**
|
||||
* The prefix of the team
|
||||
*/
|
||||
public String teamPrefix;
|
||||
/**
|
||||
* The suffix of the team
|
||||
*/
|
||||
public String teamSuffix;
|
||||
/**
|
||||
* An array with all entities in the team
|
||||
*/
|
||||
public String[] entities;
|
||||
|
||||
/**
|
||||
* Writes data into the {@link PacketWriter}
|
||||
*
|
||||
* @param writer The writer to writes
|
||||
*/
|
||||
@Override
|
||||
public void write(PacketWriter writer) {
|
||||
writer.writeSizedString(teamName);
|
||||
writer.writeByte((byte) action.ordinal());
|
||||
writer.writeSizedString(this.teamName);
|
||||
writer.writeByte((byte) this.action.ordinal());
|
||||
|
||||
switch (action) {
|
||||
case CREATE_TEAM:
|
||||
case UPDATE_TEAM_INFO:
|
||||
writer.writeSizedString(teamDisplayName);
|
||||
writer.writeByte(friendlyFlags);
|
||||
writer.writeSizedString(nameTagVisibility.getIdentifier());
|
||||
writer.writeSizedString(collisionRule.getIdentifier());
|
||||
writer.writeVarInt(teamColor);
|
||||
writer.writeSizedString(teamPrefix);
|
||||
writer.writeSizedString(teamSuffix);
|
||||
writer.writeSizedString(this.teamDisplayName);
|
||||
writer.writeByte(this.friendlyFlags);
|
||||
writer.writeSizedString(this.nameTagVisibility.getIdentifier());
|
||||
writer.writeSizedString(this.collisionRule.getIdentifier());
|
||||
writer.writeVarInt(this.teamColor);
|
||||
writer.writeSizedString(this.teamPrefix);
|
||||
writer.writeSizedString(this.teamSuffix);
|
||||
break;
|
||||
case REMOVE_TEAM:
|
||||
|
||||
@ -45,48 +83,127 @@ public class TeamsPacket implements ServerPacket {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the identifier of the packet
|
||||
*
|
||||
* @return the identifier
|
||||
*/
|
||||
@Override
|
||||
public int getId() {
|
||||
return ServerPacketIdentifier.TEAMS;
|
||||
}
|
||||
|
||||
/**
|
||||
* An enumeration which representing all actions for the packet
|
||||
*/
|
||||
public enum Action {
|
||||
/**
|
||||
* An action to create a new team
|
||||
*/
|
||||
CREATE_TEAM,
|
||||
/**
|
||||
* An action to remove a team
|
||||
*/
|
||||
REMOVE_TEAM,
|
||||
/**
|
||||
* An action to update the team information
|
||||
*/
|
||||
UPDATE_TEAM_INFO,
|
||||
/**
|
||||
* An action to add player to the team
|
||||
*/
|
||||
ADD_PLAYERS_TEAM,
|
||||
/**
|
||||
* An action to remove player from the team
|
||||
*/
|
||||
REMOVE_PLAYERS_TEAM
|
||||
}
|
||||
|
||||
/**
|
||||
* An enumeration which representing all visibility states for the name tags
|
||||
*/
|
||||
public enum NameTagVisibility {
|
||||
/**
|
||||
* The name tag is visible
|
||||
*/
|
||||
ALWAYS("always"),
|
||||
/**
|
||||
* Hides the name tag for other teams
|
||||
*/
|
||||
HIDE_FOR_OTHER_TEAMS("hideForOtherTeams"),
|
||||
/**
|
||||
* Hides the name tag for the own team
|
||||
*/
|
||||
HIDE_FOR_OWN_TEAM("hideForOwnTeam"),
|
||||
/**
|
||||
* The name tag is invisible
|
||||
*/
|
||||
NEVER("never");
|
||||
|
||||
private String identifier;
|
||||
/**
|
||||
* The identifier for the client
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
* @param identifier The client identifier
|
||||
*/
|
||||
NameTagVisibility(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the client identifier
|
||||
*
|
||||
* @return the identifier
|
||||
*/
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An enumeration which representing all rules for the collision
|
||||
*/
|
||||
public enum CollisionRule {
|
||||
/**
|
||||
* Can push all objects and can be pushed by all objects
|
||||
*/
|
||||
ALWAYS("always"),
|
||||
/**
|
||||
* Can push objects of other teams, but teammates cannot
|
||||
*/
|
||||
PUSH_OTHER_TEAMS("pushOtherTeams"),
|
||||
/**
|
||||
* Can only push objects of the same team
|
||||
*/
|
||||
PUSH_OWN_TEAM("pushOwnTeam"),
|
||||
/**
|
||||
* Cannot push an object, but neither can they be pushed
|
||||
*/
|
||||
NEVER("never");
|
||||
|
||||
private String identifier;
|
||||
/**
|
||||
* The identifier for the client
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
* @param identifier The identifier for the client
|
||||
*/
|
||||
CollisionRule(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the identifier of the rule
|
||||
*
|
||||
* @return the identifier
|
||||
*/
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
@ -1,78 +0,0 @@
|
||||
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;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
// TODO fix score and objective refresh
|
||||
public class BelowNameScoreboard implements Viewable {
|
||||
|
||||
private static final AtomicInteger counter = new AtomicInteger();
|
||||
|
||||
// WARNING: you shouldn't create scoreboards/teams with the same prefixes as those
|
||||
private static final String SCOREBOARD_PREFIX = "bn-";
|
||||
private static final String TEAM_PREFIX = "bnt-";
|
||||
|
||||
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||
|
||||
private String objectiveName;
|
||||
|
||||
private ScoreboardObjectivePacket scoreboardObjectivePacket;
|
||||
private DisplayScoreboardPacket displayScoreboardPacket;
|
||||
|
||||
public BelowNameScoreboard() {
|
||||
this.objectiveName = SCOREBOARD_PREFIX + counter.incrementAndGet();
|
||||
|
||||
scoreboardObjectivePacket = new ScoreboardObjectivePacket();
|
||||
scoreboardObjectivePacket.objectiveName = objectiveName;
|
||||
scoreboardObjectivePacket.mode = 0;
|
||||
scoreboardObjectivePacket.objectiveValue = ColoredText.of(objectiveName);
|
||||
scoreboardObjectivePacket.type = 0;
|
||||
|
||||
displayScoreboardPacket = new DisplayScoreboardPacket();
|
||||
displayScoreboardPacket.position = 2; // Below name
|
||||
displayScoreboardPacket.scoreName = objectiveName;
|
||||
}
|
||||
|
||||
public void updateScore(Player player, int score) {
|
||||
UpdateScorePacket updateScorePacket = new UpdateScorePacket();
|
||||
updateScorePacket.entityName = player.getUsername();
|
||||
updateScorePacket.action = 0; // Create/update
|
||||
updateScorePacket.objectiveName = objectiveName;
|
||||
updateScorePacket.value = score;
|
||||
|
||||
sendPacketToViewers(updateScorePacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addViewer(Player player) {
|
||||
boolean result = this.viewers.add(player);
|
||||
PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
playerConnection.sendPacket(scoreboardObjectivePacket);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeViewer(Player player) {
|
||||
return this.viewers.remove(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Player> getViewers() {
|
||||
return Collections.unmodifiableSet(viewers);
|
||||
}
|
||||
|
||||
public void displayScoreboard(Player player) {
|
||||
PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
playerConnection.sendPacket(displayScoreboardPacket);
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
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 a scoreboard which rendered a tag below the name
|
||||
*/
|
||||
public class BelowNameTag implements Scoreboard {
|
||||
|
||||
/**
|
||||
* <b>WARNING:</b> You shouldn't create scoreboards with the same prefix as those
|
||||
*/
|
||||
public static final String BELOW_NAME_TAG_PREFIX = "bnt-";
|
||||
|
||||
private final Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||
private final String objectiveName;
|
||||
|
||||
private final ScoreboardObjectivePacket scoreboardObjectivePacket;
|
||||
|
||||
/**
|
||||
* Creates a new below name scoreboard
|
||||
*
|
||||
* @param name The objective name of the scoreboard
|
||||
* @param value The value of the scoreboard
|
||||
*/
|
||||
public BelowNameTag(String name, String value) {
|
||||
this.objectiveName = BELOW_NAME_TAG_PREFIX + name;
|
||||
|
||||
this.scoreboardObjectivePacket = this.getCreationObjectivePacket(value, ScoreboardObjectivePacket.Type.INTEGER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getObjectiveName() {
|
||||
return this.objectiveName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addViewer(Player player) {
|
||||
boolean result = this.viewers.add(player);
|
||||
PlayerConnection connection = player.getPlayerConnection();
|
||||
|
||||
if (result) {
|
||||
connection.sendPacket(this.scoreboardObjectivePacket);
|
||||
connection.sendPacket(this.getDisplayScoreboardPacket((byte) 2));
|
||||
|
||||
player.setBelowNameTag(this);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeViewer(Player player) {
|
||||
boolean result = this.viewers.remove(player);
|
||||
PlayerConnection connection = player.getPlayerConnection();
|
||||
|
||||
if (result) {
|
||||
connection.sendPacket(this.getDestructionObjectivePacket());
|
||||
player.setBelowNameTag(null);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Player> getViewers() {
|
||||
return Collections.unmodifiableSet(viewers);
|
||||
}
|
||||
}
|
82
src/main/java/net/minestom/server/scoreboard/Scoreboard.java
Normal file
82
src/main/java/net/minestom/server/scoreboard/Scoreboard.java
Normal file
@ -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();
|
||||
|
||||
}
|
@ -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;
|
||||
@ -18,30 +17,42 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class Sidebar implements Viewable {
|
||||
/**
|
||||
* Represents a sidebar which can contain up to 16 {@link ScoreboardLine}'s
|
||||
*/
|
||||
public class Sidebar implements Scoreboard {
|
||||
|
||||
private static final AtomicInteger counter = new AtomicInteger();
|
||||
private static final AtomicInteger COUNTER = new AtomicInteger();
|
||||
|
||||
// WARNING: you shouldn't create scoreboards/teams with the same prefixes as those
|
||||
/**
|
||||
* <b>WARNING:</b> 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-";
|
||||
|
||||
// Limited by notchian client, do not change
|
||||
/**
|
||||
* Limited by the notch client, do not change
|
||||
*/
|
||||
private static final int MAX_LINES_COUNT = 15;
|
||||
|
||||
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||
private final Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||
|
||||
private ConcurrentLinkedQueue<ScoreboardLine> lines = new ConcurrentLinkedQueue<>();
|
||||
private IntLinkedOpenHashSet availableColors = new IntLinkedOpenHashSet();
|
||||
private final ConcurrentLinkedQueue<ScoreboardLine> lines = new ConcurrentLinkedQueue<>();
|
||||
private final IntLinkedOpenHashSet availableColors = new IntLinkedOpenHashSet();
|
||||
|
||||
private String objectiveName;
|
||||
private final String objectiveName;
|
||||
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* Creates a new sidebar
|
||||
*
|
||||
* @param title The title of the sidebar
|
||||
*/
|
||||
public Sidebar(String title) {
|
||||
this.title = title;
|
||||
|
||||
this.objectiveName = SCOREBOARD_PREFIX + counter.incrementAndGet();
|
||||
this.objectiveName = SCOREBOARD_PREFIX + COUNTER.incrementAndGet();
|
||||
|
||||
// Fill available colors for entities name showed in scoreboard
|
||||
for (int i = 0; i < 16; i++) {
|
||||
@ -49,6 +60,11 @@ public class Sidebar implements Viewable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the {@link Sidebar} title
|
||||
*
|
||||
* @param title The new sidebar title
|
||||
*/
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
|
||||
@ -56,11 +72,16 @@ public class Sidebar implements Viewable {
|
||||
scoreboardObjectivePacket.objectiveName = objectiveName;
|
||||
scoreboardObjectivePacket.mode = 2; // Update display text
|
||||
scoreboardObjectivePacket.objectiveValue = ColoredText.of(title);
|
||||
scoreboardObjectivePacket.type = 0;
|
||||
scoreboardObjectivePacket.type = ScoreboardObjectivePacket.Type.INTEGER;
|
||||
|
||||
sendPacketToViewers(scoreboardObjectivePacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ScoreboardLine}
|
||||
*
|
||||
* @param scoreboardLine The new scoreboard line
|
||||
*/
|
||||
public void createLine(ScoreboardLine scoreboardLine) {
|
||||
synchronized (lines) {
|
||||
Check.stateCondition(lines.size() >= MAX_LINES_COUNT, "You cannot have more than " + MAX_LINES_COUNT + " lines");
|
||||
@ -84,6 +105,12 @@ public class Sidebar implements Viewable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a line content through the given identifier
|
||||
*
|
||||
* @param id The identifier of the line
|
||||
* @param content The new content for the line
|
||||
*/
|
||||
public void updateLineContent(String id, ColoredText content) {
|
||||
final ScoreboardLine scoreboardLine = getLine(id);
|
||||
if (scoreboardLine != null) {
|
||||
@ -92,6 +119,12 @@ public class Sidebar implements Viewable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the score of a line through the given identifier
|
||||
*
|
||||
* @param id The identifier of the team
|
||||
* @param score The new score for the line
|
||||
*/
|
||||
public void updateLineScore(String id, int score) {
|
||||
final ScoreboardLine scoreboardLine = getLine(id);
|
||||
if (scoreboardLine != null) {
|
||||
@ -100,6 +133,12 @@ public class Sidebar implements Viewable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link ScoreboardLine} through the given identifier
|
||||
*
|
||||
* @param id The identifier of the line
|
||||
* @return a {@link ScoreboardLine} or {@code null}
|
||||
*/
|
||||
public ScoreboardLine getLine(String id) {
|
||||
for (ScoreboardLine line : lines) {
|
||||
if (line.id.equals(id))
|
||||
@ -108,6 +147,11 @@ public class Sidebar implements Viewable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a {@link ScoreboardLine} through the given identifier
|
||||
*
|
||||
* @param id The identifier of the line
|
||||
*/
|
||||
public void removeLine(String id) {
|
||||
synchronized (lines) {
|
||||
Iterator<ScoreboardLine> iterator = lines.iterator();
|
||||
@ -130,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 = 0; // 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)
|
||||
@ -154,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) {
|
||||
@ -171,15 +206,38 @@ 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.
|
||||
*/
|
||||
public static class ScoreboardLine {
|
||||
|
||||
private String id; // ID used to modify the line later
|
||||
/**
|
||||
* The identifier is used to modify the line later
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* The content for the line
|
||||
*/
|
||||
private ColoredText content;
|
||||
/**
|
||||
* The score of the line
|
||||
*/
|
||||
private int line;
|
||||
|
||||
private String teamName;
|
||||
private int colorName; // Name of the score (entityName) which is essentially an ID
|
||||
/**
|
||||
* The name of the score ({@code entityName}) which is essentially an identifier
|
||||
*/
|
||||
private int colorName;
|
||||
private String entityName;
|
||||
/**
|
||||
* The sidebar team of the line
|
||||
*/
|
||||
private SidebarTeam sidebarTeam;
|
||||
|
||||
public ScoreboardLine(String id, ColoredText content, int line) {
|
||||
@ -187,17 +245,32 @@ public class Sidebar implements Viewable {
|
||||
this.content = content;
|
||||
this.line = line;
|
||||
|
||||
this.teamName = TEAM_PREFIX + counter.incrementAndGet();
|
||||
this.teamName = TEAM_PREFIX + COUNTER.incrementAndGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the identifier of the line
|
||||
*
|
||||
* @return the line identifier
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content of the line
|
||||
*
|
||||
* @return The line content
|
||||
*/
|
||||
public ColoredText getContent() {
|
||||
return sidebarTeam == null ? content : sidebarTeam.getPrefix();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position of the line
|
||||
*
|
||||
* @return the line position
|
||||
*/
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
@ -208,6 +281,9 @@ public class Sidebar implements Viewable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SidebarTeam}
|
||||
*/
|
||||
private void createTeam() {
|
||||
this.entityName = ChatParser.COLOR_CHAR + Integer.toHexString(colorName);
|
||||
|
||||
@ -220,6 +296,12 @@ public class Sidebar implements Viewable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a score creation packet
|
||||
*
|
||||
* @param objectiveName The objective name to be updated
|
||||
* @return a {@link UpdateScorePacket}
|
||||
*/
|
||||
private UpdateScorePacket getScoreCreationPacket(String objectiveName) {
|
||||
UpdateScorePacket updateScorePacket = new UpdateScorePacket();
|
||||
updateScorePacket.entityName = entityName;
|
||||
@ -229,6 +311,12 @@ public class Sidebar implements Viewable {
|
||||
return updateScorePacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a score destruction packet
|
||||
*
|
||||
* @param objectiveName The objective name to be destroyed
|
||||
* @return a {@link UpdateScorePacket}
|
||||
*/
|
||||
private UpdateScorePacket getScoreDestructionPacket(String objectiveName) {
|
||||
UpdateScorePacket updateScorePacket = new UpdateScorePacket();
|
||||
updateScorePacket.entityName = entityName;
|
||||
@ -237,18 +325,33 @@ public class Sidebar implements Viewable {
|
||||
return updateScorePacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a line score update packet
|
||||
*
|
||||
* @param objectiveName The objective name to be updated
|
||||
* @param score The new score
|
||||
* @return a {@link UpdateScorePacket}
|
||||
*/
|
||||
private UpdateScorePacket getLineScoreUpdatePacket(String objectiveName, int score) {
|
||||
UpdateScorePacket updateScorePacket = getScoreCreationPacket(objectiveName);
|
||||
updateScorePacket.value = score;
|
||||
return updateScorePacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the prefix of the {@link SidebarTeam}
|
||||
*
|
||||
* @param content The new content
|
||||
*/
|
||||
private void refreshContent(ColoredText content) {
|
||||
this.sidebarTeam.refreshPrefix(content);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used to create a team for the sidebar
|
||||
*/
|
||||
private static class SidebarTeam {
|
||||
|
||||
private String teamName;
|
||||
@ -262,6 +365,14 @@ public class Sidebar implements Viewable {
|
||||
private int teamColor = 2;
|
||||
|
||||
|
||||
/**
|
||||
* The constructor to creates a team
|
||||
*
|
||||
* @param teamName The registry name of the team
|
||||
* @param prefix The team prefix
|
||||
* @param suffix The team suffix
|
||||
* @param entityName The team entity name
|
||||
*/
|
||||
private SidebarTeam(String teamName, ColoredText prefix, ColoredText suffix, String entityName) {
|
||||
this.teamName = teamName;
|
||||
this.prefix = prefix;
|
||||
@ -269,6 +380,11 @@ public class Sidebar implements Viewable {
|
||||
this.entityName = entityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a team creation packet
|
||||
*
|
||||
* @return a {@link TeamsPacket} which creates a new team
|
||||
*/
|
||||
private TeamsPacket getCreationPacket() {
|
||||
TeamsPacket teamsPacket = new TeamsPacket();
|
||||
teamsPacket.teamName = teamName;
|
||||
@ -284,6 +400,11 @@ public class Sidebar implements Viewable {
|
||||
return teamsPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a team destruction packet
|
||||
*
|
||||
* @return a {@link TeamsPacket} which destroyed a team
|
||||
*/
|
||||
private TeamsPacket getDestructionPacket() {
|
||||
TeamsPacket teamsPacket = new TeamsPacket();
|
||||
teamsPacket.teamName = teamName;
|
||||
@ -291,6 +412,12 @@ public class Sidebar implements Viewable {
|
||||
return teamsPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the prefix of the {@link SidebarTeam}
|
||||
*
|
||||
* @param prefix The new prefix
|
||||
* @return a {@link TeamsPacket} with the updated prefix
|
||||
*/
|
||||
private TeamsPacket updatePrefix(ColoredText prefix) {
|
||||
TeamsPacket teamsPacket = new TeamsPacket();
|
||||
teamsPacket.teamName = teamName;
|
||||
@ -305,14 +432,29 @@ public class Sidebar implements Viewable {
|
||||
return teamsPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entity name of the team
|
||||
*
|
||||
* @return the entity name
|
||||
*/
|
||||
private String getEntityName() {
|
||||
return entityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the prefix of the team
|
||||
*
|
||||
* @return the prefix
|
||||
*/
|
||||
private ColoredText getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the prefix of the {@link SidebarTeam}
|
||||
*
|
||||
* @param prefix The refreshed prefix
|
||||
*/
|
||||
private void refreshPrefix(ColoredText prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
85
src/main/java/net/minestom/server/scoreboard/TabList.java
Normal file
85
src/main/java/net/minestom/server/scoreboard/TabList.java
Normal file
@ -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 {
|
||||
|
||||
/**
|
||||
* <b>WARNING:</b> You shouldn't create scoreboards with the same prefix as those
|
||||
*/
|
||||
private static final String TAB_LIST_PREFIX = "tl-";
|
||||
|
||||
private final Set<Player> 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<Player> getViewers() {
|
||||
return Collections.unmodifiableSet(this.viewers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getObjectiveName() {
|
||||
return this.objectiveName;
|
||||
}
|
||||
}
|
@ -1,142 +1,350 @@
|
||||
package net.minestom.server.scoreboard;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.entity.LivingEntity;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.PacketWriterUtils;
|
||||
import net.minestom.server.network.packet.server.play.TeamsPacket;
|
||||
import net.minestom.server.network.packet.server.play.TeamsPacket.CollisionRule;
|
||||
import net.minestom.server.network.packet.server.play.TeamsPacket.NameTagVisibility;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* This object represents a team on a scoreboard that has a common display theme and other properties.
|
||||
*/
|
||||
public class Team {
|
||||
|
||||
private String teamName;
|
||||
private ColoredText teamDisplayName = ColoredText.of("");
|
||||
private byte friendlyFlags = 0x00;
|
||||
private TeamsPacket.NameTagVisibility nameTagVisibility = TeamsPacket.NameTagVisibility.ALWAYS;
|
||||
private TeamsPacket.CollisionRule collisionRule = TeamsPacket.CollisionRule.NEVER;
|
||||
private ChatColor teamColor = ChatColor.WHITE;
|
||||
/**
|
||||
* A collection of all registered entities who are on the team
|
||||
*/
|
||||
private final Set<String> members;
|
||||
/**
|
||||
* Creation packet for the team to create
|
||||
*/
|
||||
private final TeamsPacket teamsCreationPacket;
|
||||
/**
|
||||
* A byte buf to destroy the team
|
||||
*/
|
||||
private final ByteBuf teamsDestroyPacket;
|
||||
|
||||
private ColoredText prefix = ColoredText.of("");
|
||||
private ColoredText suffix = ColoredText.of("");
|
||||
/**
|
||||
* The registry name of the team
|
||||
*/
|
||||
private final String teamName;
|
||||
/**
|
||||
* The display name of the team
|
||||
*/
|
||||
private ColoredText teamDisplayName;
|
||||
/**
|
||||
* A BitMask
|
||||
*/
|
||||
private byte friendlyFlags;
|
||||
/**
|
||||
* The visibility of the team
|
||||
*/
|
||||
private NameTagVisibility nameTagVisibility;
|
||||
/**
|
||||
* The collision rule of the team
|
||||
*/
|
||||
private CollisionRule collisionRule;
|
||||
|
||||
private String[] entities = new String[0];
|
||||
private Set<Player> players = new CopyOnWriteArraySet<>();
|
||||
/**
|
||||
* Used to color the name of players on the team <br>
|
||||
* The color of a team defines how the names of the team members are visualized
|
||||
*/
|
||||
private ChatColor teamColor;
|
||||
|
||||
private TeamsPacket teamsCreationPacket;
|
||||
/**
|
||||
* Shown before the names of the players who belong to this team
|
||||
*/
|
||||
private ColoredText prefix;
|
||||
/**
|
||||
* Shown after the names of the player who belong to this team
|
||||
*/
|
||||
private ColoredText suffix;
|
||||
|
||||
private ByteBuf teamsDestroyPacket;
|
||||
/**
|
||||
* Identifiers for the entities in this team
|
||||
*/
|
||||
private String[] entities;
|
||||
|
||||
/**
|
||||
* Default constructor to creates a team
|
||||
*
|
||||
* @param teamName The registry name for the team
|
||||
*/
|
||||
protected Team(String teamName) {
|
||||
this.teamName = teamName;
|
||||
|
||||
teamsCreationPacket = new TeamsPacket();
|
||||
teamsCreationPacket.teamName = teamName;
|
||||
teamsCreationPacket.action = TeamsPacket.Action.CREATE_TEAM;
|
||||
teamsCreationPacket.teamDisplayName = teamDisplayName.toString();
|
||||
teamsCreationPacket.friendlyFlags = friendlyFlags;
|
||||
teamsCreationPacket.nameTagVisibility = nameTagVisibility;
|
||||
teamsCreationPacket.collisionRule = collisionRule;
|
||||
teamsCreationPacket.teamColor = teamColor.getId();
|
||||
teamsCreationPacket.teamPrefix = prefix.toString();
|
||||
teamsCreationPacket.teamSuffix = suffix.toString();
|
||||
teamsCreationPacket.entities = entities;
|
||||
this.teamDisplayName = ColoredText.of("");
|
||||
this.friendlyFlags = 0x00;
|
||||
this.nameTagVisibility = NameTagVisibility.ALWAYS;
|
||||
this.collisionRule = CollisionRule.ALWAYS;
|
||||
|
||||
TeamsPacket destroyPacket = new TeamsPacket();
|
||||
destroyPacket.teamName = teamName;
|
||||
destroyPacket.action = TeamsPacket.Action.REMOVE_TEAM;
|
||||
teamsDestroyPacket = PacketUtils.writePacket(destroyPacket); // Directly write packet since it will not change
|
||||
this.teamColor = ChatColor.WHITE;
|
||||
this.prefix = ColoredText.of("");
|
||||
this.suffix = ColoredText.of("");
|
||||
|
||||
this.entities = new String[0];
|
||||
this.members = new CopyOnWriteArraySet<>();
|
||||
|
||||
// Initializes creation packet
|
||||
this.teamsCreationPacket = new TeamsPacket();
|
||||
this.teamsCreationPacket.teamName = teamName;
|
||||
this.teamsCreationPacket.action = TeamsPacket.Action.CREATE_TEAM;
|
||||
this.teamsCreationPacket.teamDisplayName = this.teamDisplayName.toString();
|
||||
this.teamsCreationPacket.friendlyFlags = this.friendlyFlags;
|
||||
this.teamsCreationPacket.nameTagVisibility = this.nameTagVisibility;
|
||||
this.teamsCreationPacket.collisionRule = this.collisionRule;
|
||||
this.teamsCreationPacket.teamColor = this.teamColor.getId();
|
||||
this.teamsCreationPacket.teamPrefix = this.prefix.toString();
|
||||
this.teamsCreationPacket.teamSuffix = this.suffix.toString();
|
||||
this.teamsCreationPacket.entities = this.entities;
|
||||
|
||||
// Directly write packet since it will not change
|
||||
this.teamsDestroyPacket = PacketUtils.writePacket(this.createTeamDestructionPacket());
|
||||
}
|
||||
|
||||
public void addPlayer(Player player) {
|
||||
final String newElement = player.getUsername();
|
||||
/**
|
||||
* Adds a member to the {@link Team}
|
||||
* <br>
|
||||
* This member can be a {@link Player} or an {@link LivingEntity}
|
||||
*
|
||||
* @param member The member to be added
|
||||
*/
|
||||
public void addMember(String member) {
|
||||
final String[] entitiesCache = new String[this.entities.length + 1];
|
||||
System.arraycopy(this.entities, 0, entitiesCache, 0, this.entities.length);
|
||||
entitiesCache[this.entities.length] = member;
|
||||
this.entities = entitiesCache;
|
||||
this.teamsCreationPacket.entities = this.entities;
|
||||
|
||||
TeamsPacket addPlayerPacket = new TeamsPacket();
|
||||
addPlayerPacket.teamName = teamName;
|
||||
// Adds a new member to the team
|
||||
this.members.add(member);
|
||||
|
||||
// Initializes add player packet
|
||||
final TeamsPacket addPlayerPacket = new TeamsPacket();
|
||||
addPlayerPacket.teamName = this.teamName;
|
||||
addPlayerPacket.action = TeamsPacket.Action.ADD_PLAYERS_TEAM;
|
||||
addPlayerPacket.entities = new String[]{newElement};
|
||||
for (Player p : players) {
|
||||
p.getPlayerConnection().sendPacket(addPlayerPacket);
|
||||
}
|
||||
|
||||
String[] entitiesCache = new String[entities.length + 1];
|
||||
System.arraycopy(entities, 0, entitiesCache, 0, entities.length);
|
||||
entitiesCache[entities.length] = newElement;
|
||||
this.entities = entitiesCache;
|
||||
this.teamsCreationPacket.entities = entities;
|
||||
|
||||
this.players.add(player);
|
||||
player.getPlayerConnection().sendPacket(teamsCreationPacket);
|
||||
addPlayerPacket.entities = new String[]{member};
|
||||
// Sends to all online players the add player packet
|
||||
PacketWriterUtils.writeAndSend(MinecraftServer.getConnectionManager().getOnlinePlayers(), addPlayerPacket);
|
||||
}
|
||||
|
||||
public void removePlayer(Player player) {
|
||||
TeamsPacket removePlayerPacket = new TeamsPacket();
|
||||
removePlayerPacket.teamName = teamName;
|
||||
/**
|
||||
* Removes a member from the {@link Team}
|
||||
*
|
||||
* @param member The member to be removed
|
||||
*/
|
||||
public void removeMember(String member) {
|
||||
// Initializes remove player packet
|
||||
final TeamsPacket removePlayerPacket = new TeamsPacket();
|
||||
removePlayerPacket.teamName = this.teamName;
|
||||
removePlayerPacket.action = TeamsPacket.Action.REMOVE_PLAYERS_TEAM;
|
||||
removePlayerPacket.entities = new String[]{player.getUsername()};
|
||||
for (Player p : players) {
|
||||
p.getPlayerConnection().sendPacket(removePlayerPacket);
|
||||
}
|
||||
removePlayerPacket.entities = new String[]{member};
|
||||
// Sends to all online player teh remove player packet
|
||||
PacketWriterUtils.writeAndSend(MinecraftServer.getConnectionManager().getOnlinePlayers(), removePlayerPacket);
|
||||
|
||||
this.players.remove(player);
|
||||
player.getPlayerConnection().sendPacket(teamsDestroyPacket, true); // TODO do not destroy, simply remove the player from the team
|
||||
// Removes the player from the
|
||||
this.members.remove(member);
|
||||
|
||||
String[] entitiesCache = new String[entities.length - 1];
|
||||
final String[] entitiesCache = new String[this.entities.length - 1];
|
||||
int count = 0;
|
||||
for (Player p : players) {
|
||||
entitiesCache[count++] = p.getUsername();
|
||||
for (String teamMember : this.members) {
|
||||
entitiesCache[count++] = teamMember;
|
||||
}
|
||||
this.entities = entitiesCache;
|
||||
this.teamsCreationPacket.entities = entities;
|
||||
this.teamsCreationPacket.entities = this.entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the display name of the team
|
||||
* <br><br>
|
||||
* <b>Warning:</b> This is only changed on the <b>server side</b>
|
||||
*
|
||||
* @param teamDisplayName The new display name
|
||||
*/
|
||||
public void setTeamDisplayName(ColoredText teamDisplayName) {
|
||||
this.teamDisplayName = teamDisplayName;
|
||||
this.teamsCreationPacket.teamDisplayName = teamDisplayName.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the display name of the team and sends an update packet
|
||||
*
|
||||
* @param teamDisplayName The new display name
|
||||
*/
|
||||
public void updateTeamDisplayName(ColoredText teamDisplayName) {
|
||||
this.setTeamDisplayName(teamDisplayName);
|
||||
sendUpdatePacket();
|
||||
}
|
||||
|
||||
public void setNameTagVisibility(TeamsPacket.NameTagVisibility nameTagVisibility) {
|
||||
this.nameTagVisibility = nameTagVisibility;
|
||||
this.teamsCreationPacket.nameTagVisibility = nameTagVisibility;
|
||||
/**
|
||||
* Change the {@link NameTagVisibility} of the team
|
||||
* <br><br>
|
||||
* <b>Warning:</b> This is only changed on the <b>server side</b>
|
||||
*
|
||||
* @param visibility The new tag visibility
|
||||
*/
|
||||
public void setNameTagVisibility(NameTagVisibility visibility) {
|
||||
this.nameTagVisibility = visibility;
|
||||
this.teamsCreationPacket.nameTagVisibility = visibility;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the {@link NameTagVisibility} of the team and sends an update packet
|
||||
*
|
||||
* @param nameTagVisibility The new tag visibility
|
||||
*/
|
||||
public void updateNameTagVisibility(NameTagVisibility nameTagVisibility) {
|
||||
this.setNameTagVisibility(nameTagVisibility);
|
||||
sendUpdatePacket();
|
||||
}
|
||||
|
||||
public void setCollisionRule(TeamsPacket.CollisionRule collisionRule) {
|
||||
this.collisionRule = collisionRule;
|
||||
this.teamsCreationPacket.collisionRule = collisionRule;
|
||||
/**
|
||||
* Change the {@link CollisionRule} of the team
|
||||
* <br><br>
|
||||
* <b>Warning:</b> This is only changed on the <b>server side</b>
|
||||
*
|
||||
* @param rule The new rule
|
||||
*/
|
||||
public void setCollisionRule(CollisionRule rule) {
|
||||
this.collisionRule = rule;
|
||||
this.teamsCreationPacket.collisionRule = rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the collision rule of the team and sends an update packet
|
||||
*
|
||||
* @param collisionRule The new collision rule
|
||||
*/
|
||||
public void updateCollisionRule(CollisionRule collisionRule) {
|
||||
this.setCollisionRule(collisionRule);
|
||||
sendUpdatePacket();
|
||||
}
|
||||
|
||||
public void setTeamColor(ChatColor teamColor) {
|
||||
this.teamColor = teamColor;
|
||||
this.teamsCreationPacket.teamColor = teamColor.getId();
|
||||
/**
|
||||
* Change the color of the team
|
||||
* <br><br>
|
||||
* <b>Warning:</b> This is only changed on the <b>server side</b>
|
||||
*
|
||||
* @param color The new team color
|
||||
*/
|
||||
public void setTeamColor(ChatColor color) {
|
||||
this.teamColor = color;
|
||||
this.teamsCreationPacket.teamColor = color.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the color of the team and sends an update packet
|
||||
*
|
||||
* @param teamColor The new team color
|
||||
*/
|
||||
public void updateTeamColor(ChatColor teamColor) {
|
||||
this.setTeamColor(teamColor);
|
||||
sendUpdatePacket();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the prefix of the team
|
||||
* <br><br>
|
||||
* <b>Warning:</b> This is only changed on the <b>server side</b>
|
||||
*
|
||||
* @param prefix The new prefix
|
||||
*/
|
||||
public void setPrefix(ColoredText prefix) {
|
||||
this.prefix = prefix;
|
||||
this.teamsCreationPacket.teamPrefix = prefix.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the prefix of the team and sends an update packet
|
||||
*
|
||||
* @param prefix The new prefix
|
||||
*/
|
||||
public void updatePrefix(ColoredText prefix) {
|
||||
this.setPrefix(prefix);
|
||||
sendUpdatePacket();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the suffix of the team
|
||||
* <br><br>
|
||||
* <b>Warning:</b> This is only changed on the <b>server side</b>
|
||||
*
|
||||
* @param suffix The new suffix
|
||||
*/
|
||||
public void setSuffix(ColoredText suffix) {
|
||||
this.suffix = suffix;
|
||||
this.teamsCreationPacket.teamSuffix = suffix.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the suffix of the team and sends an update packet
|
||||
*
|
||||
* @param suffix The new suffix
|
||||
*/
|
||||
public void updateSuffix(ColoredText suffix) {
|
||||
this.setSuffix(suffix);
|
||||
sendUpdatePacket();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the friendly flags of the team
|
||||
* <br><br>
|
||||
* <b>Warning:</b> This is only changed on the <b>server side</b>
|
||||
*
|
||||
* @param flag The new friendly flag
|
||||
*/
|
||||
public void setFriendlyFlags(byte flag) {
|
||||
this.friendlyFlags = flag;
|
||||
this.teamsCreationPacket.friendlyFlags = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the friendly flags of the team and sends an update packet
|
||||
*
|
||||
* @param flag The new friendly flag
|
||||
*/
|
||||
public void updateFriendlyFlags(byte flag) {
|
||||
this.setFriendlyFlags(flag);
|
||||
this.sendUpdatePacket();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registry name of the team
|
||||
*
|
||||
* @return the registry name
|
||||
*/
|
||||
public String getTeamName() {
|
||||
return teamName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the creation packet to add a team
|
||||
*
|
||||
* @return the packet to add the team
|
||||
*/
|
||||
public TeamsPacket getTeamsCreationPacket() {
|
||||
return teamsCreationPacket;
|
||||
}
|
||||
|
||||
public ByteBuf getTeamsDestroyPacket() {
|
||||
return teamsDestroyPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an destruction packet to remove the team
|
||||
*
|
||||
* @return the packet to remove the team
|
||||
*/
|
||||
public TeamsPacket createTeamDestructionPacket() {
|
||||
TeamsPacket teamsPacket = new TeamsPacket();
|
||||
teamsPacket.teamName = teamName;
|
||||
@ -144,22 +352,99 @@ public class Team {
|
||||
return teamsPacket;
|
||||
}
|
||||
|
||||
public Set<Player> getPlayers() {
|
||||
return Collections.unmodifiableSet(players);
|
||||
/**
|
||||
* Obtains an unmodifiable {@link Set} of registered players who are on the team
|
||||
*
|
||||
* @return an unmodifiable {@link Set} of registered players
|
||||
*/
|
||||
public Set<String> getMembers() {
|
||||
return Collections.unmodifiableSet(members);
|
||||
}
|
||||
|
||||
private void sendUpdatePacket() {
|
||||
TeamsPacket updatePacket = new TeamsPacket();
|
||||
updatePacket.teamName = teamName;
|
||||
/**
|
||||
* Gets the display name of the team
|
||||
*
|
||||
* @return the display name
|
||||
*/
|
||||
public ColoredText getTeamDisplayName() {
|
||||
return teamDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the friendly flags of the team
|
||||
*
|
||||
* @return the friendly flags
|
||||
*/
|
||||
public byte getFriendlyFlags() {
|
||||
return friendlyFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tag visibility of the team
|
||||
*
|
||||
* @return the tag visibility
|
||||
*/
|
||||
public NameTagVisibility getNameTagVisibility() {
|
||||
return nameTagVisibility;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the collision rule of the team
|
||||
*
|
||||
* @return the collision rule
|
||||
*/
|
||||
public CollisionRule getCollisionRule() {
|
||||
return collisionRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color of the team
|
||||
*
|
||||
* @return the team color
|
||||
*/
|
||||
public ChatColor getTeamColor() {
|
||||
return teamColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the prefix of the team
|
||||
*
|
||||
* @return the team prefix
|
||||
*/
|
||||
public ColoredText getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the suffix of the team
|
||||
*
|
||||
* @return the suffix team
|
||||
*/
|
||||
public ColoredText getSuffix() {
|
||||
return suffix;
|
||||
}
|
||||
|
||||
public String[] getEntities() {
|
||||
return entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an {@link TeamsPacket.Action#UPDATE_TEAM_INFO} packet
|
||||
*/
|
||||
public void sendUpdatePacket() {
|
||||
final TeamsPacket updatePacket = new TeamsPacket();
|
||||
updatePacket.teamName = this.teamName;
|
||||
updatePacket.action = TeamsPacket.Action.UPDATE_TEAM_INFO;
|
||||
updatePacket.teamDisplayName = teamDisplayName.toString();
|
||||
updatePacket.friendlyFlags = friendlyFlags;
|
||||
updatePacket.nameTagVisibility = nameTagVisibility;
|
||||
updatePacket.collisionRule = collisionRule;
|
||||
updatePacket.teamColor = teamColor.getId();
|
||||
updatePacket.teamPrefix = prefix.toString();
|
||||
updatePacket.teamSuffix = suffix.toString();
|
||||
updatePacket.teamDisplayName = this.teamDisplayName.toString();
|
||||
updatePacket.friendlyFlags = this.friendlyFlags;
|
||||
updatePacket.nameTagVisibility = this.nameTagVisibility;
|
||||
updatePacket.collisionRule = this.collisionRule;
|
||||
updatePacket.teamColor = this.teamColor.getId();
|
||||
updatePacket.teamPrefix = this.prefix.toString();
|
||||
updatePacket.teamSuffix = this.suffix.toString();
|
||||
ByteBuf buffer = PacketUtils.writePacket(updatePacket);
|
||||
players.forEach(p -> p.getPlayerConnection().sendPacket(buffer, true));
|
||||
for (Player onlinePlayer : MinecraftServer.getConnectionManager().getOnlinePlayers()) {
|
||||
onlinePlayer.getPlayerConnection().sendPacket(buffer, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
347
src/main/java/net/minestom/server/scoreboard/TeamBuilder.java
Normal file
347
src/main/java/net/minestom/server/scoreboard/TeamBuilder.java
Normal file
@ -0,0 +1,347 @@
|
||||
package net.minestom.server.scoreboard;
|
||||
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.network.packet.server.play.TeamsPacket.CollisionRule;
|
||||
import net.minestom.server.network.packet.server.play.TeamsPacket.NameTagVisibility;
|
||||
|
||||
/**
|
||||
* A builder which represents a fluent Object to built teams
|
||||
*/
|
||||
public class TeamBuilder {
|
||||
|
||||
/**
|
||||
* The management for the teams
|
||||
*/
|
||||
private final TeamManager teamManager;
|
||||
/**
|
||||
* The team to create
|
||||
*/
|
||||
private final Team team;
|
||||
/**
|
||||
* True, if it should send an update packet
|
||||
*/
|
||||
private boolean updateTeam;
|
||||
|
||||
/**
|
||||
* Creates an team builder
|
||||
*
|
||||
* @param name The name of the new team
|
||||
* @param teamManager The manager for the team
|
||||
*/
|
||||
public TeamBuilder(String name, TeamManager teamManager) {
|
||||
this(teamManager.exists(name) ? teamManager.getTeam(name) : new Team(name), teamManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an team builder
|
||||
*
|
||||
* @param team The new team
|
||||
* @param teamManager The manager for the team
|
||||
*/
|
||||
private TeamBuilder(Team team, TeamManager teamManager) {
|
||||
this.team = team;
|
||||
this.teamManager = teamManager;
|
||||
this.updateTeam = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the prefix of the {@link Team}
|
||||
*
|
||||
* @param prefix The new prefix
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updatePrefix(String prefix) {
|
||||
return this.updatePrefix(ColoredText.of(prefix));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the prefix of the {@link Team}
|
||||
*
|
||||
* @param prefix The new prefix
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updatePrefix(ColoredText prefix) {
|
||||
this.team.updatePrefix(prefix);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the color of the {@link Team}
|
||||
*
|
||||
* @param color The new color
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updateTeamColor(ChatColor color) {
|
||||
this.team.updateTeamColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the suffix of the {@link Team}
|
||||
*
|
||||
* @param suffix The new suffix
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updateSuffix(String suffix) {
|
||||
return updateSuffix(ColoredText.of(suffix));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the suffix of the {@link Team}
|
||||
*
|
||||
* @param suffix The new suffix
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updateSuffix(ColoredText suffix) {
|
||||
this.team.updateSuffix(suffix);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the display name of the {@link Team}
|
||||
*
|
||||
* @param displayName The new display name
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updateTeamDisplayName(String displayName) {
|
||||
return this.updateTeamDisplayName(ColoredText.of(displayName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the display name of the {@link Team}
|
||||
*
|
||||
* @param displayName The new display name
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updateTeamDisplayName(ColoredText displayName) {
|
||||
this.team.updateTeamDisplayName(displayName);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the {@link CollisionRule} of the {@link Team}
|
||||
*
|
||||
* @param rule The new rule
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updateCollisionRule(CollisionRule rule) {
|
||||
this.team.updateCollisionRule(rule);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the {@link NameTagVisibility} of the {@link Team}
|
||||
*
|
||||
* @param visibility The new tag visibility
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updateNameTagVisibility(NameTagVisibility visibility) {
|
||||
this.team.updateNameTagVisibility(visibility);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the friendly flags of the {@link Team}
|
||||
*
|
||||
* @param flag The new friendly flag
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updateFriendlyFlags(byte flag) {
|
||||
this.team.updateFriendlyFlags(flag);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the friendly flags for allow friendly fire
|
||||
*
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updateAllowFriendlyFire() {
|
||||
return this.updateFriendlyFlags((byte) 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the friendly flags to sees invisible players of own team
|
||||
*
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updateSeeInvisiblePlayers() {
|
||||
return this.updateFriendlyFlags((byte) 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the prefix of the {@link Team} without an update packet
|
||||
* <br><br>
|
||||
* <b>Warning: </b> If you do not call {@link #updateTeamPacket()}, this is only changed of the <b>server side</b>
|
||||
*
|
||||
* @param prefix The new prefix
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder prefix(String prefix) {
|
||||
return this.prefix(ColoredText.of(prefix));
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the prefix of the {@link Team} without an update packet
|
||||
* <br><br>
|
||||
* <b>Warning: </b> If you do not call {@link #updateTeamPacket()}, this is only changed of the <b>server side</b>
|
||||
*
|
||||
* @param prefix The new prefix
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder prefix(ColoredText prefix) {
|
||||
this.team.setPrefix(prefix);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the suffix of the {@link Team} without an update packet
|
||||
* <br><br>
|
||||
* <b>Warning: </b> If you do not call {@link #updateTeamPacket()}, this is only changed of the <b>server side</b>
|
||||
*
|
||||
* @param suffix The new suffix
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder suffix(String suffix) {
|
||||
this.team.setSuffix(ColoredText.of(suffix));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the suffix of the {@link Team} without an update packet
|
||||
* <br><br>
|
||||
* <b>Warning: </b> If you do not call {@link #updateTeamPacket()}, this is only changed of the <b>server side</b>
|
||||
*
|
||||
* @param suffix The new suffix
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder suffix(ColoredText suffix) {
|
||||
this.team.setSuffix(suffix);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the color of the {@link Team} without an update packet
|
||||
* <br><br>
|
||||
* <b>Warning: </b> If you do not call {@link #updateTeamPacket()}, this is only changed of the <b>server side</b>
|
||||
*
|
||||
* @param color The new team color
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder teamColor(ChatColor color) {
|
||||
this.team.setTeamColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the display name of the {@link Team} without an update packet
|
||||
* <br><br>
|
||||
* <b>Warning: </b> If you do not call {@link #updateTeamPacket()}, this is only changed of the <b>server side</b>
|
||||
*
|
||||
* @param displayName The new display name
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder teamDisplayName(String displayName) {
|
||||
return this.teamDisplayName(ColoredText.of(displayName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the display name of the {@link Team} without an update packet
|
||||
* <br><br>
|
||||
* <b>Warning: </b> If you do not call {@link #updateTeamPacket()}, this is only changed of the <b>server side</b>
|
||||
*
|
||||
* @param displayName The new display name
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder teamDisplayName(ColoredText displayName) {
|
||||
this.team.setTeamDisplayName(displayName);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the {@link CollisionRule} of the {@link Team} without an update packet
|
||||
* <br><br>
|
||||
* <b>Warning: </b> If you do not call {@link #updateTeamPacket()}, this is only changed of the <b>server side</b>
|
||||
*
|
||||
* @param rule The new rule
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder collisionRule(CollisionRule rule) {
|
||||
this.team.setCollisionRule(rule);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the {@link NameTagVisibility} of the {@link Team} without an update packet
|
||||
* <br><br>
|
||||
* <b>Warning: </b> If you do not call {@link #updateTeamPacket()}, this is only changed of the <b>server side</b>
|
||||
*
|
||||
* @param visibility The new tag visibility
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder nameTagVisibility(NameTagVisibility visibility) {
|
||||
this.team.setNameTagVisibility(visibility);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the friendly flags of the {@link Team} without an update packet
|
||||
* <br><br>
|
||||
* <b>Warning: </b> If you do not call {@link #updateTeamPacket()}, this is only changed of the <b>server side</b>
|
||||
*
|
||||
* @param flag The new flag
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder friendlyFlags(byte flag) {
|
||||
this.team.setFriendlyFlags(flag);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the friendly flags for allow friendly fire without an update packet
|
||||
* <br><br>
|
||||
* <b>Warning: </b> If you do not call {@link #updateTeamPacket()}, this is only changed of the <b>server side</b>
|
||||
*
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder allowFriendlyFire() {
|
||||
return this.friendlyFlags((byte) 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the friendly flags to sees invisible players of own team without an update packet
|
||||
* <br><br>
|
||||
* <b>Warning: </b> If you do not call {@link #updateTeamPacket()}, this is only changed of the <b>server side</b>
|
||||
*
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder seeInvisiblePlayers() {
|
||||
return this.friendlyFlags((byte) 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to send an update packet when the team is built
|
||||
*
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
public TeamBuilder updateTeamPacket() {
|
||||
this.updateTeam = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Built a team
|
||||
*
|
||||
* @return the built team
|
||||
*/
|
||||
public Team build() {
|
||||
if (!this.teamManager.exists(this.team)) this.teamManager.registerNewTeam(this.team);
|
||||
if (this.updateTeam) {
|
||||
this.team.sendUpdatePacket();
|
||||
this.updateTeam = false;
|
||||
}
|
||||
return this.team;
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +1,216 @@
|
||||
package net.minestom.server.scoreboard;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.entity.LivingEntity;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.PacketWriterUtils;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.utils.UniqueIdUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
// TODO
|
||||
/**
|
||||
* An object which manages all the {@link Team}'s
|
||||
*/
|
||||
public final class TeamManager {
|
||||
|
||||
// Represents all registered teams
|
||||
private Set<Team> teams = new CopyOnWriteArraySet<>();
|
||||
/**
|
||||
* Represents all registered teams
|
||||
*/
|
||||
private final Set<Team> teams;
|
||||
|
||||
public Team createTeam(String teamName) {
|
||||
Team team = new Team(teamName);
|
||||
this.teams.add(team);
|
||||
return team;
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public TeamManager() {
|
||||
this.teams = new CopyOnWriteArraySet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new {@link Team}
|
||||
*
|
||||
* @param team The team to be registered
|
||||
*/
|
||||
protected void registerNewTeam(Team team) {
|
||||
this.teams.add(team);
|
||||
this.broadcastPacket(team.getTeamsCreationPacket());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a {@link Team}
|
||||
*
|
||||
* @param registryName The registry name of team
|
||||
* @return {@code true} if the team was deleted, otherwise {@code false}
|
||||
*/
|
||||
public boolean deleteTeam(String registryName) {
|
||||
Team team = this.getTeam(registryName);
|
||||
if (team == null) return false;
|
||||
return this.deleteTeam(team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a {@link Team}
|
||||
*
|
||||
* @param team The team to be deleted
|
||||
* @return {@code true} if the team was deleted, otherwise {@code false}
|
||||
*/
|
||||
public boolean deleteTeam(Team team) {
|
||||
// Sends to all online players a team destroy packet
|
||||
this.broadcastBuffer(team.getTeamsDestroyPacket());
|
||||
return this.teams.remove(team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new {@link TeamBuilder} for creating a team
|
||||
*
|
||||
* @param name The registry name of the team
|
||||
* @return the team builder
|
||||
*/
|
||||
public TeamBuilder createBuilder(String name) {
|
||||
return new TeamBuilder(name, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Team} with only the registry name
|
||||
*
|
||||
* @param name The registry name
|
||||
* @return the created {@link Team}
|
||||
*/
|
||||
public Team createTeam(String name) {
|
||||
return this.createBuilder(name).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Team} with the registry name, prefix, suffix and the team color
|
||||
*
|
||||
* @param name The registry name
|
||||
* @param prefix The team prefix
|
||||
* @param teamColor The team color
|
||||
* @param suffix The team suffix
|
||||
* @return the created {@link Team} with a prefix, teamColor and suffix
|
||||
*/
|
||||
public Team createTeam(String name, ColoredText prefix, ChatColor teamColor, ColoredText suffix) {
|
||||
return this.createBuilder(name).prefix(prefix).teamColor(teamColor).suffix(suffix).updateTeamPacket().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Team} with the registry name, display name, prefix, suffix and the team colro
|
||||
*
|
||||
* @param name The registry name
|
||||
* @param displayName The display name
|
||||
* @param prefix The team prefix
|
||||
* @param teamColor The team color
|
||||
* @param suffix The team suffix
|
||||
* @return the created {@link Team} with a prefix, teamColor, suffix and the display name
|
||||
*/
|
||||
public Team createTeam(String name, ColoredText displayName, ColoredText prefix, ChatColor teamColor, ColoredText suffix) {
|
||||
return this.createBuilder(name).teamDisplayName(displayName).prefix(prefix).teamColor(teamColor).suffix(suffix).updateTeamPacket().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Team} with the given name
|
||||
*
|
||||
* @param teamName The registry name of the team
|
||||
* @return a registered {@link Team} or {@code null}
|
||||
*/
|
||||
public Team getTeam(String teamName) {
|
||||
for (Team team : this.teams) {
|
||||
if (team.getTeamName().equals(teamName)) return team;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given name a registry name of a registered {@link Team}
|
||||
*
|
||||
* @param teamName The name of the team
|
||||
* @return {@code true} if the team is registered, otherwise {@code false}
|
||||
*/
|
||||
public boolean exists(String teamName) {
|
||||
for (Team team : this.teams) {
|
||||
if (team.getTeamName().equals(teamName)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given {@link Team} registered
|
||||
*
|
||||
* @param team The searched team
|
||||
* @return {@code true} if the team is registered, otherwise {@code false}
|
||||
*/
|
||||
public boolean exists(Team team) {
|
||||
return this.exists(team.getTeamName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link List} with all registered {@link Player} in the team
|
||||
* <br>
|
||||
* <b>Note:</b> The list exclude all entities. To get all entities of the team, you can use {@link #getEntities(Team)}
|
||||
*
|
||||
* @param team The team
|
||||
* @return a {@link List} with all registered {@link Player}
|
||||
*/
|
||||
public List<String> getPlayers(Team team) {
|
||||
List<String> players = new ArrayList<>();
|
||||
for (String member : team.getMembers()) {
|
||||
boolean match = UniqueIdUtils.isUniqueId(member);
|
||||
|
||||
if (!match) players.add(member);
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link List} with all registered {@link LivingEntity} in the team
|
||||
* <br>
|
||||
* <b>Note:</b> The list exclude all players. To get all players of the team, you can use {@link #getPlayers(Team)}
|
||||
*
|
||||
* @param team The team
|
||||
* @return a {@link List} with all registered {@link LivingEntity}
|
||||
*/
|
||||
public List<String> getEntities(Team team) {
|
||||
List<String> entities = new ArrayList<>();
|
||||
for (String member : team.getMembers()) {
|
||||
boolean match = UniqueIdUtils.isUniqueId(member);
|
||||
|
||||
if (match) entities.add(member);
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Set} with all registered {@link Team}'s
|
||||
*
|
||||
* @return a {@link Set} with all registered {@link Team}'s
|
||||
*/
|
||||
public Set<Team> getTeams() {
|
||||
return teams;
|
||||
return this.teams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts to all online {@link Player}'s a {@link ServerPacket}
|
||||
*
|
||||
* @param packet The packet to broadcast
|
||||
*/
|
||||
private void broadcastPacket(ServerPacket packet) {
|
||||
PacketWriterUtils.writeAndSend(MinecraftServer.getConnectionManager().getOnlinePlayers(), packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts to all online {@link Player}'s a buffer
|
||||
*
|
||||
* @param buffer The buffer to broadcast
|
||||
*/
|
||||
private void broadcastBuffer(ByteBuf buffer) {
|
||||
for (Player onlinePlayer : MinecraftServer.getConnectionManager().getOnlinePlayers()) {
|
||||
onlinePlayer.getPlayerConnection().sendPacket(buffer, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
23
src/main/java/net/minestom/server/utils/UniqueIdUtils.java
Normal file
23
src/main/java/net/minestom/server/utils/UniqueIdUtils.java
Normal file
@ -0,0 +1,23 @@
|
||||
package net.minestom.server.utils;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* An utilities class for {@link UUID}
|
||||
*/
|
||||
public final class UniqueIdUtils {
|
||||
|
||||
public static final Pattern UNIQUE_ID_PATTERN = Pattern.compile("\\b[0-9a-f]{8}\\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\\b[0-9a-f]{12}\\b");
|
||||
|
||||
/**
|
||||
* Checks whether the {@code input} string is an {@link UUID}
|
||||
*
|
||||
* @param input The input string to be checked
|
||||
* @return {@code true} if the input an unique identifier, otherwise {@code false}
|
||||
*/
|
||||
public static boolean isUniqueId(String input) {
|
||||
return input.matches(UNIQUE_ID_PATTERN.pattern());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user