mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-21 07:31:47 +01:00
Merge pull request #36 from R0bbyYT/feature/scoreboard
Feature/scoreboard
This commit is contained in:
commit
cbf06e6963
@ -13,6 +13,7 @@ import net.minestom.server.item.ItemStack;
|
|||||||
import net.minestom.server.network.packet.PacketWriter;
|
import net.minestom.server.network.packet.PacketWriter;
|
||||||
import net.minestom.server.network.packet.server.play.*;
|
import net.minestom.server.network.packet.server.play.*;
|
||||||
import net.minestom.server.network.player.PlayerConnection;
|
import net.minestom.server.network.player.PlayerConnection;
|
||||||
|
import net.minestom.server.scoreboard.Team;
|
||||||
import net.minestom.server.sound.Sound;
|
import net.minestom.server.sound.Sound;
|
||||||
import net.minestom.server.sound.SoundCategory;
|
import net.minestom.server.sound.SoundCategory;
|
||||||
import net.minestom.server.utils.Position;
|
import net.minestom.server.utils.Position;
|
||||||
@ -55,6 +56,8 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
|||||||
*/
|
*/
|
||||||
private long fireDamagePeriod = 1000L;
|
private long fireDamagePeriod = 1000L;
|
||||||
|
|
||||||
|
private Team team;
|
||||||
|
|
||||||
public LivingEntity(EntityType entityType, Position spawnPosition) {
|
public LivingEntity(EntityType entityType, Position spawnPosition) {
|
||||||
super(entityType, spawnPosition);
|
super(entityType, spawnPosition);
|
||||||
setupAttributes();
|
setupAttributes();
|
||||||
@ -522,4 +525,40 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
|||||||
fireDamagePeriod = timeUnit.toMilliseconds(fireDamagePeriod);
|
fireDamagePeriod = timeUnit.toMilliseconds(fireDamagePeriod);
|
||||||
this.fireDamagePeriod = 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ import net.minestom.server.network.player.PlayerConnection;
|
|||||||
import net.minestom.server.recipe.Recipe;
|
import net.minestom.server.recipe.Recipe;
|
||||||
import net.minestom.server.recipe.RecipeManager;
|
import net.minestom.server.recipe.RecipeManager;
|
||||||
import net.minestom.server.resourcepack.ResourcePack;
|
import net.minestom.server.resourcepack.ResourcePack;
|
||||||
import net.minestom.server.scoreboard.BelowNameScoreboard;
|
import net.minestom.server.scoreboard.BelowNameTag;
|
||||||
import net.minestom.server.scoreboard.Team;
|
import net.minestom.server.scoreboard.Team;
|
||||||
import net.minestom.server.sound.Sound;
|
import net.minestom.server.sound.Sound;
|
||||||
import net.minestom.server.sound.SoundCategory;
|
import net.minestom.server.sound.SoundCategory;
|
||||||
@ -107,8 +107,7 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
private byte targetLastStage;
|
private byte targetLastStage;
|
||||||
private int blockBreakTime;
|
private int blockBreakTime;
|
||||||
|
|
||||||
private Team team;
|
private BelowNameTag belowNameTag;
|
||||||
private BelowNameScoreboard belowNameScoreboard;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Last damage source to hit this player, used to display the death message.
|
* Last damage source to hit this player, used to display the death message.
|
||||||
@ -524,8 +523,8 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
viewerConnection.sendPacket(getRemovePlayerToList());
|
viewerConnection.sendPacket(getRemovePlayerToList());
|
||||||
|
|
||||||
// Team
|
// Team
|
||||||
if (team != null && team.getPlayers().size() == 1) // If team only contains "this" player
|
if (this.getTeam() != null && this.getTeam().getMembers().size() == 1) // If team only contains "this" player
|
||||||
viewerConnection.sendPacket(team.createTeamDestructionPacket());
|
viewerConnection.sendPacket(this.getTeam().createTeamDestructionPacket());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1370,34 +1369,24 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setTeam(Team team) {
|
public void setTeam(Team team) {
|
||||||
if (this.team == team)
|
super.setTeam(team);
|
||||||
return;
|
if(team != null)
|
||||||
|
getPlayerConnection().sendPacket(team.getTeamsCreationPacket());
|
||||||
if (this.team != null) {
|
|
||||||
this.team.removePlayer(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.team = team;
|
|
||||||
if (team != null) {
|
|
||||||
team.addPlayer(this);
|
|
||||||
sendPacketToViewers(team.getTeamsCreationPacket()); // FIXME: only if viewer hasn't already register this team
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBelowNameScoreboard(BelowNameScoreboard belowNameScoreboard) {
|
/**
|
||||||
if (this.belowNameScoreboard == belowNameScoreboard)
|
* Change the tag below the name
|
||||||
return;
|
*
|
||||||
|
* @param belowNameTag The new below name tag
|
||||||
|
*/
|
||||||
|
public void setBelowNameTag(BelowNameTag belowNameTag) {
|
||||||
|
if (this.belowNameTag == belowNameTag) return;
|
||||||
|
|
||||||
if (this.belowNameScoreboard != null) {
|
if (this.belowNameTag != null) {
|
||||||
this.belowNameScoreboard.removeViewer(this);
|
this.belowNameTag.removeViewer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.belowNameScoreboard = belowNameScoreboard;
|
this.belowNameTag = belowNameTag;
|
||||||
if (belowNameScoreboard != null) {
|
|
||||||
belowNameScoreboard.addViewer(this);
|
|
||||||
belowNameScoreboard.displayScoreboard(this);
|
|
||||||
getViewers().forEach(player -> belowNameScoreboard.addViewer(player));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1969,8 +1958,8 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Team
|
// Team
|
||||||
if (team != null)
|
if (this.getTeam() != null)
|
||||||
connection.sendPacket(team.getTeamsCreationPacket());
|
connection.sendPacket(this.getTeam().getTeamsCreationPacket());
|
||||||
|
|
||||||
EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
|
EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
|
||||||
entityHeadLookPacket.entityId = getEntityId();
|
entityHeadLookPacket.entityId = getEntityId();
|
||||||
|
@ -7,10 +7,24 @@ import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
|||||||
|
|
||||||
public class ScoreboardObjectivePacket implements ServerPacket {
|
public class ScoreboardObjectivePacket implements ServerPacket {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An unique name for the objective
|
||||||
|
*/
|
||||||
public String objectiveName;
|
public String objectiveName;
|
||||||
|
/**
|
||||||
|
* 0 = create the scoreboard <br>
|
||||||
|
* 1 = to remove the scoreboard<br>
|
||||||
|
* 2 = to update the display text
|
||||||
|
*/
|
||||||
public byte mode;
|
public byte mode;
|
||||||
|
/**
|
||||||
|
* The text to be displayed for the score
|
||||||
|
*/
|
||||||
public ColoredText objectiveValue;
|
public ColoredText objectiveValue;
|
||||||
public int type;
|
/**
|
||||||
|
* The type how the score is displayed
|
||||||
|
*/
|
||||||
|
public Type type;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(PacketWriter writer) {
|
public void write(PacketWriter writer) {
|
||||||
@ -19,7 +33,7 @@ public class ScoreboardObjectivePacket implements ServerPacket {
|
|||||||
|
|
||||||
if (mode == 0 || mode == 2) {
|
if (mode == 0 || mode == 2) {
|
||||||
writer.writeSizedString(objectiveValue.toString());
|
writer.writeSizedString(objectiveValue.toString());
|
||||||
writer.writeVarInt(type);
|
writer.writeVarInt(type.ordinal());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,4 +41,12 @@ public class ScoreboardObjectivePacket implements ServerPacket {
|
|||||||
public int getId() {
|
public int getId() {
|
||||||
return ServerPacketIdentifier.SCOREBOARD_OBJECTIVE;
|
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.ServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The packet creates or updates teams
|
||||||
|
*/
|
||||||
public class TeamsPacket implements ServerPacket {
|
public class TeamsPacket implements ServerPacket {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The registry name of the team
|
||||||
|
*/
|
||||||
public String teamName;
|
public String teamName;
|
||||||
|
/**
|
||||||
|
* The action of the packet
|
||||||
|
*/
|
||||||
public Action action;
|
public Action action;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The display name for the team
|
||||||
|
*/
|
||||||
public String teamDisplayName;
|
public String teamDisplayName;
|
||||||
|
/**
|
||||||
|
* The friendly flags to
|
||||||
|
*/
|
||||||
public byte friendlyFlags;
|
public byte friendlyFlags;
|
||||||
|
/**
|
||||||
|
* Visibility state for the name tag
|
||||||
|
*/
|
||||||
public NameTagVisibility nameTagVisibility;
|
public NameTagVisibility nameTagVisibility;
|
||||||
|
/**
|
||||||
|
* Rule for the collision
|
||||||
|
*/
|
||||||
public CollisionRule collisionRule;
|
public CollisionRule collisionRule;
|
||||||
|
/**
|
||||||
|
* The color of the team
|
||||||
|
*/
|
||||||
public int teamColor;
|
public int teamColor;
|
||||||
|
/**
|
||||||
|
* The prefix of the team
|
||||||
|
*/
|
||||||
public String teamPrefix;
|
public String teamPrefix;
|
||||||
|
/**
|
||||||
|
* The suffix of the team
|
||||||
|
*/
|
||||||
public String teamSuffix;
|
public String teamSuffix;
|
||||||
|
/**
|
||||||
|
* An array with all entities in the team
|
||||||
|
*/
|
||||||
public String[] entities;
|
public String[] entities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes data into the {@link PacketWriter}
|
||||||
|
*
|
||||||
|
* @param writer The writer to writes
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(PacketWriter writer) {
|
public void write(PacketWriter writer) {
|
||||||
writer.writeSizedString(teamName);
|
writer.writeSizedString(this.teamName);
|
||||||
writer.writeByte((byte) action.ordinal());
|
writer.writeByte((byte) this.action.ordinal());
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case CREATE_TEAM:
|
case CREATE_TEAM:
|
||||||
case UPDATE_TEAM_INFO:
|
case UPDATE_TEAM_INFO:
|
||||||
writer.writeSizedString(teamDisplayName);
|
writer.writeSizedString(this.teamDisplayName);
|
||||||
writer.writeByte(friendlyFlags);
|
writer.writeByte(this.friendlyFlags);
|
||||||
writer.writeSizedString(nameTagVisibility.getIdentifier());
|
writer.writeSizedString(this.nameTagVisibility.getIdentifier());
|
||||||
writer.writeSizedString(collisionRule.getIdentifier());
|
writer.writeSizedString(this.collisionRule.getIdentifier());
|
||||||
writer.writeVarInt(teamColor);
|
writer.writeVarInt(this.teamColor);
|
||||||
writer.writeSizedString(teamPrefix);
|
writer.writeSizedString(this.teamPrefix);
|
||||||
writer.writeSizedString(teamSuffix);
|
writer.writeSizedString(this.teamSuffix);
|
||||||
break;
|
break;
|
||||||
case REMOVE_TEAM:
|
case REMOVE_TEAM:
|
||||||
|
|
||||||
@ -45,48 +83,127 @@ public class TeamsPacket implements ServerPacket {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the identifier of the packet
|
||||||
|
*
|
||||||
|
* @return the identifier
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return ServerPacketIdentifier.TEAMS;
|
return ServerPacketIdentifier.TEAMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enumeration which representing all actions for the packet
|
||||||
|
*/
|
||||||
public enum Action {
|
public enum Action {
|
||||||
|
/**
|
||||||
|
* An action to create a new team
|
||||||
|
*/
|
||||||
CREATE_TEAM,
|
CREATE_TEAM,
|
||||||
|
/**
|
||||||
|
* An action to remove a team
|
||||||
|
*/
|
||||||
REMOVE_TEAM,
|
REMOVE_TEAM,
|
||||||
|
/**
|
||||||
|
* An action to update the team information
|
||||||
|
*/
|
||||||
UPDATE_TEAM_INFO,
|
UPDATE_TEAM_INFO,
|
||||||
|
/**
|
||||||
|
* An action to add player to the team
|
||||||
|
*/
|
||||||
ADD_PLAYERS_TEAM,
|
ADD_PLAYERS_TEAM,
|
||||||
|
/**
|
||||||
|
* An action to remove player from the team
|
||||||
|
*/
|
||||||
REMOVE_PLAYERS_TEAM
|
REMOVE_PLAYERS_TEAM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enumeration which representing all visibility states for the name tags
|
||||||
|
*/
|
||||||
public enum NameTagVisibility {
|
public enum NameTagVisibility {
|
||||||
|
/**
|
||||||
|
* The name tag is visible
|
||||||
|
*/
|
||||||
ALWAYS("always"),
|
ALWAYS("always"),
|
||||||
|
/**
|
||||||
|
* Hides the name tag for other teams
|
||||||
|
*/
|
||||||
HIDE_FOR_OTHER_TEAMS("hideForOtherTeams"),
|
HIDE_FOR_OTHER_TEAMS("hideForOtherTeams"),
|
||||||
|
/**
|
||||||
|
* Hides the name tag for the own team
|
||||||
|
*/
|
||||||
HIDE_FOR_OWN_TEAM("hideForOwnTeam"),
|
HIDE_FOR_OWN_TEAM("hideForOwnTeam"),
|
||||||
|
/**
|
||||||
|
* The name tag is invisible
|
||||||
|
*/
|
||||||
NEVER("never");
|
NEVER("never");
|
||||||
|
|
||||||
private String identifier;
|
/**
|
||||||
|
* The identifier for the client
|
||||||
|
*/
|
||||||
|
private final String identifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*
|
||||||
|
* @param identifier The client identifier
|
||||||
|
*/
|
||||||
NameTagVisibility(String identifier) {
|
NameTagVisibility(String identifier) {
|
||||||
this.identifier = identifier;
|
this.identifier = identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the client identifier
|
||||||
|
*
|
||||||
|
* @return the identifier
|
||||||
|
*/
|
||||||
public String getIdentifier() {
|
public String getIdentifier() {
|
||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enumeration which representing all rules for the collision
|
||||||
|
*/
|
||||||
public enum CollisionRule {
|
public enum CollisionRule {
|
||||||
|
/**
|
||||||
|
* Can push all objects and can be pushed by all objects
|
||||||
|
*/
|
||||||
ALWAYS("always"),
|
ALWAYS("always"),
|
||||||
|
/**
|
||||||
|
* Can push objects of other teams, but teammates cannot
|
||||||
|
*/
|
||||||
PUSH_OTHER_TEAMS("pushOtherTeams"),
|
PUSH_OTHER_TEAMS("pushOtherTeams"),
|
||||||
|
/**
|
||||||
|
* Can only push objects of the same team
|
||||||
|
*/
|
||||||
PUSH_OWN_TEAM("pushOwnTeam"),
|
PUSH_OWN_TEAM("pushOwnTeam"),
|
||||||
|
/**
|
||||||
|
* Cannot push an object, but neither can they be pushed
|
||||||
|
*/
|
||||||
NEVER("never");
|
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) {
|
CollisionRule(String identifier) {
|
||||||
this.identifier = identifier;
|
this.identifier = identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the identifier of the rule
|
||||||
|
*
|
||||||
|
* @return the identifier
|
||||||
|
*/
|
||||||
public String getIdentifier() {
|
public String getIdentifier() {
|
||||||
return identifier;
|
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;
|
package net.minestom.server.scoreboard;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet;
|
import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet;
|
||||||
import net.minestom.server.Viewable;
|
|
||||||
import net.minestom.server.chat.ChatParser;
|
import net.minestom.server.chat.ChatParser;
|
||||||
import net.minestom.server.chat.ColoredText;
|
import net.minestom.server.chat.ColoredText;
|
||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
@ -18,30 +17,42 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
|||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
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 SCOREBOARD_PREFIX = "sb-";
|
||||||
private static final String TEAM_PREFIX = "sbt-";
|
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 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 final ConcurrentLinkedQueue<ScoreboardLine> lines = new ConcurrentLinkedQueue<>();
|
||||||
private IntLinkedOpenHashSet availableColors = new IntLinkedOpenHashSet();
|
private final IntLinkedOpenHashSet availableColors = new IntLinkedOpenHashSet();
|
||||||
|
|
||||||
private String objectiveName;
|
private final String objectiveName;
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new sidebar
|
||||||
|
*
|
||||||
|
* @param title The title of the sidebar
|
||||||
|
*/
|
||||||
public Sidebar(String title) {
|
public Sidebar(String title) {
|
||||||
this.title = 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
|
// Fill available colors for entities name showed in scoreboard
|
||||||
for (int i = 0; i < 16; i++) {
|
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) {
|
public void setTitle(String title) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
|
|
||||||
@ -56,11 +72,16 @@ public class Sidebar implements Viewable {
|
|||||||
scoreboardObjectivePacket.objectiveName = objectiveName;
|
scoreboardObjectivePacket.objectiveName = objectiveName;
|
||||||
scoreboardObjectivePacket.mode = 2; // Update display text
|
scoreboardObjectivePacket.mode = 2; // Update display text
|
||||||
scoreboardObjectivePacket.objectiveValue = ColoredText.of(title);
|
scoreboardObjectivePacket.objectiveValue = ColoredText.of(title);
|
||||||
scoreboardObjectivePacket.type = 0;
|
scoreboardObjectivePacket.type = ScoreboardObjectivePacket.Type.INTEGER;
|
||||||
|
|
||||||
sendPacketToViewers(scoreboardObjectivePacket);
|
sendPacketToViewers(scoreboardObjectivePacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ScoreboardLine}
|
||||||
|
*
|
||||||
|
* @param scoreboardLine The new scoreboard line
|
||||||
|
*/
|
||||||
public void createLine(ScoreboardLine scoreboardLine) {
|
public void createLine(ScoreboardLine scoreboardLine) {
|
||||||
synchronized (lines) {
|
synchronized (lines) {
|
||||||
Check.stateCondition(lines.size() >= MAX_LINES_COUNT, "You cannot have more than " + MAX_LINES_COUNT + " 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) {
|
public void updateLineContent(String id, ColoredText content) {
|
||||||
final ScoreboardLine scoreboardLine = getLine(id);
|
final ScoreboardLine scoreboardLine = getLine(id);
|
||||||
if (scoreboardLine != null) {
|
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) {
|
public void updateLineScore(String id, int score) {
|
||||||
final ScoreboardLine scoreboardLine = getLine(id);
|
final ScoreboardLine scoreboardLine = getLine(id);
|
||||||
if (scoreboardLine != null) {
|
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) {
|
public ScoreboardLine getLine(String id) {
|
||||||
for (ScoreboardLine line : lines) {
|
for (ScoreboardLine line : lines) {
|
||||||
if (line.id.equals(id))
|
if (line.id.equals(id))
|
||||||
@ -108,6 +147,11 @@ public class Sidebar implements Viewable {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a {@link ScoreboardLine} through the given identifier
|
||||||
|
*
|
||||||
|
* @param id The identifier of the line
|
||||||
|
*/
|
||||||
public void removeLine(String id) {
|
public void removeLine(String id) {
|
||||||
synchronized (lines) {
|
synchronized (lines) {
|
||||||
Iterator<ScoreboardLine> iterator = lines.iterator();
|
Iterator<ScoreboardLine> iterator = lines.iterator();
|
||||||
@ -130,15 +174,8 @@ public class Sidebar implements Viewable {
|
|||||||
final boolean result = this.viewers.add(player);
|
final boolean result = this.viewers.add(player);
|
||||||
PlayerConnection playerConnection = player.getPlayerConnection();
|
PlayerConnection playerConnection = player.getPlayerConnection();
|
||||||
|
|
||||||
ScoreboardObjectivePacket scoreboardObjectivePacket = new ScoreboardObjectivePacket();
|
ScoreboardObjectivePacket scoreboardObjectivePacket = this.getCreationObjectivePacket(this.title, ScoreboardObjectivePacket.Type.INTEGER);
|
||||||
scoreboardObjectivePacket.objectiveName = objectiveName;
|
DisplayScoreboardPacket displayScoreboardPacket = this.getDisplayScoreboardPacket((byte) 1);
|
||||||
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;
|
|
||||||
|
|
||||||
playerConnection.sendPacket(scoreboardObjectivePacket); // Creative objective
|
playerConnection.sendPacket(scoreboardObjectivePacket); // Creative objective
|
||||||
playerConnection.sendPacket(displayScoreboardPacket); // Show sidebar scoreboard (wait for scores packet)
|
playerConnection.sendPacket(displayScoreboardPacket); // Show sidebar scoreboard (wait for scores packet)
|
||||||
@ -154,9 +191,7 @@ public class Sidebar implements Viewable {
|
|||||||
public boolean removeViewer(Player player) {
|
public boolean removeViewer(Player player) {
|
||||||
boolean result = this.viewers.remove(player);
|
boolean result = this.viewers.remove(player);
|
||||||
PlayerConnection playerConnection = player.getPlayerConnection();
|
PlayerConnection playerConnection = player.getPlayerConnection();
|
||||||
ScoreboardObjectivePacket scoreboardObjectivePacket = new ScoreboardObjectivePacket();
|
ScoreboardObjectivePacket scoreboardObjectivePacket = this.getDestructionObjectivePacket();
|
||||||
scoreboardObjectivePacket.objectiveName = objectiveName;
|
|
||||||
scoreboardObjectivePacket.mode = 1; // Remove
|
|
||||||
playerConnection.sendPacket(scoreboardObjectivePacket);
|
playerConnection.sendPacket(scoreboardObjectivePacket);
|
||||||
|
|
||||||
for (ScoreboardLine line : lines) {
|
for (ScoreboardLine line : lines) {
|
||||||
@ -171,15 +206,38 @@ public class Sidebar implements Viewable {
|
|||||||
return viewers;
|
return viewers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getObjectiveName() {
|
||||||
|
return this.objectiveName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to create a line for the sidebar.
|
||||||
|
*/
|
||||||
public static class ScoreboardLine {
|
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;
|
private ColoredText content;
|
||||||
|
/**
|
||||||
|
* The score of the line
|
||||||
|
*/
|
||||||
private int line;
|
private int line;
|
||||||
|
|
||||||
private String teamName;
|
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;
|
private String entityName;
|
||||||
|
/**
|
||||||
|
* The sidebar team of the line
|
||||||
|
*/
|
||||||
private SidebarTeam sidebarTeam;
|
private SidebarTeam sidebarTeam;
|
||||||
|
|
||||||
public ScoreboardLine(String id, ColoredText content, int line) {
|
public ScoreboardLine(String id, ColoredText content, int line) {
|
||||||
@ -187,17 +245,32 @@ public class Sidebar implements Viewable {
|
|||||||
this.content = content;
|
this.content = content;
|
||||||
this.line = line;
|
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() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the content of the line
|
||||||
|
*
|
||||||
|
* @return The line content
|
||||||
|
*/
|
||||||
public ColoredText getContent() {
|
public ColoredText getContent() {
|
||||||
return sidebarTeam == null ? content : sidebarTeam.getPrefix();
|
return sidebarTeam == null ? content : sidebarTeam.getPrefix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the position of the line
|
||||||
|
*
|
||||||
|
* @return the line position
|
||||||
|
*/
|
||||||
public int getLine() {
|
public int getLine() {
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
@ -208,6 +281,9 @@ public class Sidebar implements Viewable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link SidebarTeam}
|
||||||
|
*/
|
||||||
private void createTeam() {
|
private void createTeam() {
|
||||||
this.entityName = ChatParser.COLOR_CHAR + Integer.toHexString(colorName);
|
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) {
|
private UpdateScorePacket getScoreCreationPacket(String objectiveName) {
|
||||||
UpdateScorePacket updateScorePacket = new UpdateScorePacket();
|
UpdateScorePacket updateScorePacket = new UpdateScorePacket();
|
||||||
updateScorePacket.entityName = entityName;
|
updateScorePacket.entityName = entityName;
|
||||||
@ -229,6 +311,12 @@ public class Sidebar implements Viewable {
|
|||||||
return updateScorePacket;
|
return updateScorePacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a score destruction packet
|
||||||
|
*
|
||||||
|
* @param objectiveName The objective name to be destroyed
|
||||||
|
* @return a {@link UpdateScorePacket}
|
||||||
|
*/
|
||||||
private UpdateScorePacket getScoreDestructionPacket(String objectiveName) {
|
private UpdateScorePacket getScoreDestructionPacket(String objectiveName) {
|
||||||
UpdateScorePacket updateScorePacket = new UpdateScorePacket();
|
UpdateScorePacket updateScorePacket = new UpdateScorePacket();
|
||||||
updateScorePacket.entityName = entityName;
|
updateScorePacket.entityName = entityName;
|
||||||
@ -237,18 +325,33 @@ public class Sidebar implements Viewable {
|
|||||||
return updateScorePacket;
|
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) {
|
private UpdateScorePacket getLineScoreUpdatePacket(String objectiveName, int score) {
|
||||||
UpdateScorePacket updateScorePacket = getScoreCreationPacket(objectiveName);
|
UpdateScorePacket updateScorePacket = getScoreCreationPacket(objectiveName);
|
||||||
updateScorePacket.value = score;
|
updateScorePacket.value = score;
|
||||||
return updateScorePacket;
|
return updateScorePacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the prefix of the {@link SidebarTeam}
|
||||||
|
*
|
||||||
|
* @param content The new content
|
||||||
|
*/
|
||||||
private void refreshContent(ColoredText content) {
|
private void refreshContent(ColoredText content) {
|
||||||
this.sidebarTeam.refreshPrefix(content);
|
this.sidebarTeam.refreshPrefix(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to create a team for the sidebar
|
||||||
|
*/
|
||||||
private static class SidebarTeam {
|
private static class SidebarTeam {
|
||||||
|
|
||||||
private String teamName;
|
private String teamName;
|
||||||
@ -262,6 +365,14 @@ public class Sidebar implements Viewable {
|
|||||||
private int teamColor = 2;
|
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) {
|
private SidebarTeam(String teamName, ColoredText prefix, ColoredText suffix, String entityName) {
|
||||||
this.teamName = teamName;
|
this.teamName = teamName;
|
||||||
this.prefix = prefix;
|
this.prefix = prefix;
|
||||||
@ -269,6 +380,11 @@ public class Sidebar implements Viewable {
|
|||||||
this.entityName = entityName;
|
this.entityName = entityName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a team creation packet
|
||||||
|
*
|
||||||
|
* @return a {@link TeamsPacket} which creates a new team
|
||||||
|
*/
|
||||||
private TeamsPacket getCreationPacket() {
|
private TeamsPacket getCreationPacket() {
|
||||||
TeamsPacket teamsPacket = new TeamsPacket();
|
TeamsPacket teamsPacket = new TeamsPacket();
|
||||||
teamsPacket.teamName = teamName;
|
teamsPacket.teamName = teamName;
|
||||||
@ -284,6 +400,11 @@ public class Sidebar implements Viewable {
|
|||||||
return teamsPacket;
|
return teamsPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a team destruction packet
|
||||||
|
*
|
||||||
|
* @return a {@link TeamsPacket} which destroyed a team
|
||||||
|
*/
|
||||||
private TeamsPacket getDestructionPacket() {
|
private TeamsPacket getDestructionPacket() {
|
||||||
TeamsPacket teamsPacket = new TeamsPacket();
|
TeamsPacket teamsPacket = new TeamsPacket();
|
||||||
teamsPacket.teamName = teamName;
|
teamsPacket.teamName = teamName;
|
||||||
@ -291,6 +412,12 @@ public class Sidebar implements Viewable {
|
|||||||
return teamsPacket;
|
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) {
|
private TeamsPacket updatePrefix(ColoredText prefix) {
|
||||||
TeamsPacket teamsPacket = new TeamsPacket();
|
TeamsPacket teamsPacket = new TeamsPacket();
|
||||||
teamsPacket.teamName = teamName;
|
teamsPacket.teamName = teamName;
|
||||||
@ -305,14 +432,29 @@ public class Sidebar implements Viewable {
|
|||||||
return teamsPacket;
|
return teamsPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the entity name of the team
|
||||||
|
*
|
||||||
|
* @return the entity name
|
||||||
|
*/
|
||||||
private String getEntityName() {
|
private String getEntityName() {
|
||||||
return entityName;
|
return entityName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the prefix of the team
|
||||||
|
*
|
||||||
|
* @return the prefix
|
||||||
|
*/
|
||||||
private ColoredText getPrefix() {
|
private ColoredText getPrefix() {
|
||||||
return prefix;
|
return prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the prefix of the {@link SidebarTeam}
|
||||||
|
*
|
||||||
|
* @param prefix The refreshed prefix
|
||||||
|
*/
|
||||||
private void refreshPrefix(ColoredText prefix) {
|
private void refreshPrefix(ColoredText prefix) {
|
||||||
this.prefix = 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;
|
package net.minestom.server.scoreboard;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.chat.ChatColor;
|
import net.minestom.server.chat.ChatColor;
|
||||||
import net.minestom.server.chat.ColoredText;
|
import net.minestom.server.chat.ColoredText;
|
||||||
|
import net.minestom.server.entity.LivingEntity;
|
||||||
import net.minestom.server.entity.Player;
|
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;
|
||||||
|
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 net.minestom.server.utils.PacketUtils;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
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 {
|
public class Team {
|
||||||
|
|
||||||
private String teamName;
|
/**
|
||||||
private ColoredText teamDisplayName = ColoredText.of("");
|
* A collection of all registered entities who are on the team
|
||||||
private byte friendlyFlags = 0x00;
|
*/
|
||||||
private TeamsPacket.NameTagVisibility nameTagVisibility = TeamsPacket.NameTagVisibility.ALWAYS;
|
private final Set<String> members;
|
||||||
private TeamsPacket.CollisionRule collisionRule = TeamsPacket.CollisionRule.NEVER;
|
/**
|
||||||
private ChatColor teamColor = ChatColor.WHITE;
|
* 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) {
|
protected Team(String teamName) {
|
||||||
this.teamName = teamName;
|
this.teamName = teamName;
|
||||||
|
|
||||||
teamsCreationPacket = new TeamsPacket();
|
this.teamDisplayName = ColoredText.of("");
|
||||||
teamsCreationPacket.teamName = teamName;
|
this.friendlyFlags = 0x00;
|
||||||
teamsCreationPacket.action = TeamsPacket.Action.CREATE_TEAM;
|
this.nameTagVisibility = NameTagVisibility.ALWAYS;
|
||||||
teamsCreationPacket.teamDisplayName = teamDisplayName.toString();
|
this.collisionRule = CollisionRule.ALWAYS;
|
||||||
teamsCreationPacket.friendlyFlags = friendlyFlags;
|
|
||||||
teamsCreationPacket.nameTagVisibility = nameTagVisibility;
|
|
||||||
teamsCreationPacket.collisionRule = collisionRule;
|
|
||||||
teamsCreationPacket.teamColor = teamColor.getId();
|
|
||||||
teamsCreationPacket.teamPrefix = prefix.toString();
|
|
||||||
teamsCreationPacket.teamSuffix = suffix.toString();
|
|
||||||
teamsCreationPacket.entities = entities;
|
|
||||||
|
|
||||||
TeamsPacket destroyPacket = new TeamsPacket();
|
this.teamColor = ChatColor.WHITE;
|
||||||
destroyPacket.teamName = teamName;
|
this.prefix = ColoredText.of("");
|
||||||
destroyPacket.action = TeamsPacket.Action.REMOVE_TEAM;
|
this.suffix = ColoredText.of("");
|
||||||
teamsDestroyPacket = PacketUtils.writePacket(destroyPacket); // Directly write packet since it will not change
|
|
||||||
|
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();
|
// Adds a new member to the team
|
||||||
addPlayerPacket.teamName = teamName;
|
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.action = TeamsPacket.Action.ADD_PLAYERS_TEAM;
|
||||||
addPlayerPacket.entities = new String[]{newElement};
|
addPlayerPacket.entities = new String[]{member};
|
||||||
for (Player p : players) {
|
// Sends to all online players the add player packet
|
||||||
p.getPlayerConnection().sendPacket(addPlayerPacket);
|
PacketWriterUtils.writeAndSend(MinecraftServer.getConnectionManager().getOnlinePlayers(), 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removePlayer(Player player) {
|
/**
|
||||||
TeamsPacket removePlayerPacket = new TeamsPacket();
|
* Removes a member from the {@link Team}
|
||||||
removePlayerPacket.teamName = teamName;
|
*
|
||||||
|
* @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.action = TeamsPacket.Action.REMOVE_PLAYERS_TEAM;
|
||||||
removePlayerPacket.entities = new String[]{player.getUsername()};
|
removePlayerPacket.entities = new String[]{member};
|
||||||
for (Player p : players) {
|
// Sends to all online player teh remove player packet
|
||||||
p.getPlayerConnection().sendPacket(removePlayerPacket);
|
PacketWriterUtils.writeAndSend(MinecraftServer.getConnectionManager().getOnlinePlayers(), removePlayerPacket);
|
||||||
}
|
|
||||||
|
|
||||||
this.players.remove(player);
|
// Removes the player from the
|
||||||
player.getPlayerConnection().sendPacket(teamsDestroyPacket, true); // TODO do not destroy, simply remove the player from the team
|
this.members.remove(member);
|
||||||
|
|
||||||
String[] entitiesCache = new String[entities.length - 1];
|
final String[] entitiesCache = new String[this.entities.length - 1];
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (Player p : players) {
|
for (String teamMember : this.members) {
|
||||||
entitiesCache[count++] = p.getUsername();
|
entitiesCache[count++] = teamMember;
|
||||||
}
|
}
|
||||||
this.entities = entitiesCache;
|
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) {
|
public void setTeamDisplayName(ColoredText teamDisplayName) {
|
||||||
this.teamDisplayName = teamDisplayName;
|
this.teamDisplayName = teamDisplayName;
|
||||||
this.teamsCreationPacket.teamDisplayName = teamDisplayName.toString();
|
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();
|
sendUpdatePacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNameTagVisibility(TeamsPacket.NameTagVisibility nameTagVisibility) {
|
/**
|
||||||
this.nameTagVisibility = nameTagVisibility;
|
* Change the {@link NameTagVisibility} of the team
|
||||||
this.teamsCreationPacket.nameTagVisibility = nameTagVisibility;
|
* <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();
|
sendUpdatePacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCollisionRule(TeamsPacket.CollisionRule collisionRule) {
|
/**
|
||||||
this.collisionRule = collisionRule;
|
* Change the {@link CollisionRule} of the team
|
||||||
this.teamsCreationPacket.collisionRule = collisionRule;
|
* <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();
|
sendUpdatePacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTeamColor(ChatColor teamColor) {
|
/**
|
||||||
this.teamColor = teamColor;
|
* Change the color of the team
|
||||||
this.teamsCreationPacket.teamColor = teamColor.getId();
|
* <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();
|
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) {
|
public void setPrefix(ColoredText prefix) {
|
||||||
this.prefix = prefix;
|
this.prefix = prefix;
|
||||||
this.teamsCreationPacket.teamPrefix = prefix.toString();
|
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();
|
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) {
|
public void setSuffix(ColoredText suffix) {
|
||||||
this.suffix = suffix;
|
this.suffix = suffix;
|
||||||
this.teamsCreationPacket.teamSuffix = suffix.toString();
|
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();
|
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() {
|
public String getTeamName() {
|
||||||
return teamName;
|
return teamName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the creation packet to add a team
|
||||||
|
*
|
||||||
|
* @return the packet to add the team
|
||||||
|
*/
|
||||||
public TeamsPacket getTeamsCreationPacket() {
|
public TeamsPacket getTeamsCreationPacket() {
|
||||||
return teamsCreationPacket;
|
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() {
|
public TeamsPacket createTeamDestructionPacket() {
|
||||||
TeamsPacket teamsPacket = new TeamsPacket();
|
TeamsPacket teamsPacket = new TeamsPacket();
|
||||||
teamsPacket.teamName = teamName;
|
teamsPacket.teamName = teamName;
|
||||||
@ -144,22 +352,99 @@ public class Team {
|
|||||||
return teamsPacket;
|
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();
|
* Gets the display name of the team
|
||||||
updatePacket.teamName = teamName;
|
*
|
||||||
|
* @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.action = TeamsPacket.Action.UPDATE_TEAM_INFO;
|
||||||
updatePacket.teamDisplayName = teamDisplayName.toString();
|
updatePacket.teamDisplayName = this.teamDisplayName.toString();
|
||||||
updatePacket.friendlyFlags = friendlyFlags;
|
updatePacket.friendlyFlags = this.friendlyFlags;
|
||||||
updatePacket.nameTagVisibility = nameTagVisibility;
|
updatePacket.nameTagVisibility = this.nameTagVisibility;
|
||||||
updatePacket.collisionRule = collisionRule;
|
updatePacket.collisionRule = this.collisionRule;
|
||||||
updatePacket.teamColor = teamColor.getId();
|
updatePacket.teamColor = this.teamColor.getId();
|
||||||
updatePacket.teamPrefix = prefix.toString();
|
updatePacket.teamPrefix = this.prefix.toString();
|
||||||
updatePacket.teamSuffix = suffix.toString();
|
updatePacket.teamSuffix = this.suffix.toString();
|
||||||
ByteBuf buffer = PacketUtils.writePacket(updatePacket);
|
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;
|
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.Set;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
// TODO
|
/**
|
||||||
|
* An object which manages all the {@link Team}'s
|
||||||
|
*/
|
||||||
public final class TeamManager {
|
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);
|
* Default constructor
|
||||||
this.teams.add(team);
|
*/
|
||||||
return team;
|
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() {
|
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