Support for all living entities / Added team builder / Comments

This commit is contained in:
R0bbyYT 2020-08-04 12:44:07 +02:00
parent 981d247f02
commit 4127eea401
6 changed files with 1016 additions and 118 deletions

View File

@ -13,6 +13,7 @@ import net.minestom.server.item.ItemStack;
import net.minestom.server.network.packet.PacketWriter;
import net.minestom.server.network.packet.server.play.*;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.scoreboard.Team;
import net.minestom.server.sound.Sound;
import net.minestom.server.sound.SoundCategory;
import net.minestom.server.utils.Position;
@ -54,6 +55,8 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
*/
private long fireDamagePeriod = 1000L;
private Team team;
public LivingEntity(EntityType entityType, Position spawnPosition) {
super(entityType, spawnPosition);
setupAttributes();
@ -505,4 +508,40 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
fireDamagePeriod = timeUnit.toMilliseconds(fireDamagePeriod);
this.fireDamagePeriod = fireDamagePeriod;
}
/**
* Change the {@link Team} for the entity
*
* @param team The new team
*/
public void setTeam(Team team) {
if (this.team == team) return;
String member;
if (this instanceof Player) {
Player player = (Player) this;
member = player.getUsername();
} else {
member = this.uuid.toString();
}
if (this.team != null) {
this.team.removeMember(member);
}
this.team = team;
if (team != null) {
team.addMember(member);
}
}
/**
* Gets the {@link Team} of the entity
*
* @return the {@link Team}
*/
public Team getTeam() {
return team;
}
}

View File

@ -109,7 +109,6 @@ public class Player extends LivingEntity implements CommandSender {
private int blockBreakTime;
private Set<BossBar> bossBars = new CopyOnWriteArraySet<>();
private Team team;
private BelowNameScoreboard belowNameScoreboard;
/**
@ -527,8 +526,8 @@ public class Player extends LivingEntity implements CommandSender {
viewerConnection.sendPacket(getRemovePlayerToList());
// Team
if (team != null && team.getPlayers().size() == 1) // If team only contains "this" player
viewerConnection.sendPacket(team.createTeamDestructionPacket());
if (this.getTeam() != null && this.getTeam().getMembers().size() == 1) // If team only contains "this" player
viewerConnection.sendPacket(this.getTeam().createTeamDestructionPacket());
return result;
}
@ -1371,21 +1370,6 @@ public class Player extends LivingEntity implements CommandSender {
return heldSlot;
}
public void setTeam(Team team) {
if (this.team == team)
return;
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)
return;
@ -1402,6 +1386,13 @@ public class Player extends LivingEntity implements CommandSender {
}
}
@Override
public void setTeam(Team team) {
super.setTeam(team);
if(team != null)
getPlayerConnection().sendPacket(team.getTeamsCreationPacket());
}
/**
* Used to get the {@link CustomBlock} that the player is currently mining
*
@ -2005,8 +1996,8 @@ public class Player extends LivingEntity implements CommandSender {
}
// Team
if (team != null)
connection.sendPacket(team.getTeamsCreationPacket());
if (this.getTeam() != null)
connection.sendPacket(this.getTeam().getTeamsCreationPacket());
EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
entityHeadLookPacket.entityId = getEntityId();

View File

@ -4,35 +4,73 @@ import net.minestom.server.network.packet.PacketWriter;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
/**
* The packet creates or updates teams
*/
public class TeamsPacket implements ServerPacket {
/**
* The registry name of the team
*/
public String teamName;
/**
* The action of the packet
*/
public Action action;
/**
* The display name for the team
*/
public String teamDisplayName;
/**
* The friendly flags to
*/
public byte friendlyFlags;
/**
* Visibility state for the name tag
*/
public NameTagVisibility nameTagVisibility;
/**
* Rule for the collision
*/
public CollisionRule collisionRule;
/**
* The color of the team
*/
public int teamColor;
/**
* The prefix of the team
*/
public String teamPrefix;
/**
* The suffix of the team
*/
public String teamSuffix;
/**
* An array with all entities in the team
*/
public String[] entities;
/**
* Writes data into the {@link PacketWriter}
*
* @param writer The writer to writes
*/
@Override
public void write(PacketWriter writer) {
writer.writeSizedString(teamName);
writer.writeByte((byte) action.ordinal());
writer.writeSizedString(this.teamName);
writer.writeByte((byte) this.action.ordinal());
switch (action) {
case CREATE_TEAM:
case UPDATE_TEAM_INFO:
writer.writeSizedString(teamDisplayName);
writer.writeByte(friendlyFlags);
writer.writeSizedString(nameTagVisibility.getIdentifier());
writer.writeSizedString(collisionRule.getIdentifier());
writer.writeVarInt(teamColor);
writer.writeSizedString(teamPrefix);
writer.writeSizedString(teamSuffix);
writer.writeSizedString(this.teamDisplayName);
writer.writeByte(this.friendlyFlags);
writer.writeSizedString(this.nameTagVisibility.getIdentifier());
writer.writeSizedString(this.collisionRule.getIdentifier());
writer.writeVarInt(this.teamColor);
writer.writeSizedString(this.teamPrefix);
writer.writeSizedString(this.teamSuffix);
break;
case REMOVE_TEAM:
@ -45,48 +83,127 @@ public class TeamsPacket implements ServerPacket {
}
/**
* Gets the identifier of the packet
*
* @return the identifier
*/
@Override
public int getId() {
return ServerPacketIdentifier.TEAMS;
}
/**
* An enumeration which representing all actions for the packet
*/
public enum Action {
/**
* An action to create a new team
*/
CREATE_TEAM,
/**
* An action to remove a team
*/
REMOVE_TEAM,
/**
* An action to update the team information
*/
UPDATE_TEAM_INFO,
/**
* An action to add player to the team
*/
ADD_PLAYERS_TEAM,
/**
* An action to remove player from the team
*/
REMOVE_PLAYERS_TEAM
}
/**
* An enumeration which representing all visibility states for the name tags
*/
public enum NameTagVisibility {
/**
* The name tag is visible
*/
ALWAYS("always"),
/**
* Hides the name tag for other teams
*/
HIDE_FOR_OTHER_TEAMS("hideForOtherTeams"),
/**
* Hides the name tag for the own team
*/
HIDE_FOR_OWN_TEAM("hideForOwnTeam"),
/**
* The name tag is invisible
*/
NEVER("never");
private String identifier;
/**
* The identifier for the client
*/
private final String identifier;
/**
* Default constructor
*
* @param identifier The client identifier
*/
NameTagVisibility(String identifier) {
this.identifier = identifier;
}
/**
* Gets the client identifier
*
* @return the identifier
*/
public String getIdentifier() {
return identifier;
}
}
/**
* An enumeration which representing all rules for the collision
*/
public enum CollisionRule {
/**
* Can push all objects and can be pushed by all objects
*/
ALWAYS("always"),
/**
* Can push objects of other teams, but teammates cannot
*/
PUSH_OTHER_TEAMS("pushOtherTeams"),
/**
* Can only push objects of the same team
*/
PUSH_OWN_TEAM("pushOwnTeam"),
/**
* Cannot push an object, but neither can they be pushed
*/
NEVER("never");
private String identifier;
/**
* The identifier for the client
*/
private final String identifier;
/**
* Default constructor
*
* @param identifier The identifier for the client
*/
CollisionRule(String identifier) {
this.identifier = identifier;
}
/**
* Gets the identifier of the rule
*
* @return the identifier
*/
public String getIdentifier() {
return identifier;
}

View File

@ -1,142 +1,350 @@
package net.minestom.server.scoreboard;
import io.netty.buffer.ByteBuf;
import net.minestom.server.MinecraftServer;
import net.minestom.server.chat.ChatColor;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.entity.LivingEntity;
import net.minestom.server.entity.Player;
import net.minestom.server.network.PacketWriterUtils;
import net.minestom.server.network.packet.server.play.TeamsPacket;
import net.minestom.server.network.packet.server.play.TeamsPacket.CollisionRule;
import net.minestom.server.network.packet.server.play.TeamsPacket.NameTagVisibility;
import net.minestom.server.utils.PacketUtils;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* This object represents a team on a scoreboard that has a common display theme and other properties.
*/
public class Team {
private String teamName;
private ColoredText teamDisplayName = ColoredText.of("");
private byte friendlyFlags = 0x00;
private TeamsPacket.NameTagVisibility nameTagVisibility = TeamsPacket.NameTagVisibility.ALWAYS;
private TeamsPacket.CollisionRule collisionRule = TeamsPacket.CollisionRule.NEVER;
private ChatColor teamColor = ChatColor.WHITE;
/**
* A collection of all registered entities who are on the team
*/
private final Set<String> members;
/**
* Creation packet for the team to create
*/
private final TeamsPacket teamsCreationPacket;
/**
* A byte buf to destroy the team
*/
private final ByteBuf teamsDestroyPacket;
private ColoredText prefix = ColoredText.of("");
private ColoredText suffix = ColoredText.of("");
/**
* The registry name of the team
*/
private final String teamName;
/**
* The display name of the team
*/
private ColoredText teamDisplayName;
/**
* A BitMask
*/
private byte friendlyFlags;
/**
* The visibility of the team
*/
private NameTagVisibility nameTagVisibility;
/**
* The collision rule of the team
*/
private CollisionRule collisionRule;
private String[] entities = new String[0];
private Set<Player> players = new CopyOnWriteArraySet<>();
/**
* Used to color the name of players on the team <br>
* The color of a team defines how the names of the team members are visualized
*/
private ChatColor teamColor;
private TeamsPacket teamsCreationPacket;
/**
* Shown before the names of the players who belong to this team
*/
private ColoredText prefix;
/**
* Shown after the names of the player who belong to this team
*/
private ColoredText suffix;
private ByteBuf teamsDestroyPacket;
/**
* Identifiers for the entities in this team
*/
private String[] entities;
/**
* Default constructor to creates a team
*
* @param teamName The registry name for the team
*/
protected Team(String teamName) {
this.teamName = teamName;
teamsCreationPacket = new TeamsPacket();
teamsCreationPacket.teamName = teamName;
teamsCreationPacket.action = TeamsPacket.Action.CREATE_TEAM;
teamsCreationPacket.teamDisplayName = teamDisplayName.toString();
teamsCreationPacket.friendlyFlags = friendlyFlags;
teamsCreationPacket.nameTagVisibility = nameTagVisibility;
teamsCreationPacket.collisionRule = collisionRule;
teamsCreationPacket.teamColor = teamColor.getId();
teamsCreationPacket.teamPrefix = prefix.toString();
teamsCreationPacket.teamSuffix = suffix.toString();
teamsCreationPacket.entities = entities;
this.teamDisplayName = ColoredText.of("");
this.friendlyFlags = 0x00;
this.nameTagVisibility = NameTagVisibility.ALWAYS;
this.collisionRule = CollisionRule.ALWAYS;
TeamsPacket destroyPacket = new TeamsPacket();
destroyPacket.teamName = teamName;
destroyPacket.action = TeamsPacket.Action.REMOVE_TEAM;
teamsDestroyPacket = PacketUtils.writePacket(destroyPacket); // Directly write packet since it will not change
this.teamColor = ChatColor.WHITE;
this.prefix = ColoredText.of("");
this.suffix = ColoredText.of("");
this.entities = new String[0];
this.members = new CopyOnWriteArraySet<>();
// Initializes creation packet
this.teamsCreationPacket = new TeamsPacket();
this.teamsCreationPacket.teamName = teamName;
this.teamsCreationPacket.action = TeamsPacket.Action.CREATE_TEAM;
this.teamsCreationPacket.teamDisplayName = this.teamDisplayName.toString();
this.teamsCreationPacket.friendlyFlags = this.friendlyFlags;
this.teamsCreationPacket.nameTagVisibility = this.nameTagVisibility;
this.teamsCreationPacket.collisionRule = this.collisionRule;
this.teamsCreationPacket.teamColor = this.teamColor.getId();
this.teamsCreationPacket.teamPrefix = this.prefix.toString();
this.teamsCreationPacket.teamSuffix = this.suffix.toString();
this.teamsCreationPacket.entities = this.entities;
// Directly write packet since it will not change
this.teamsDestroyPacket = PacketUtils.writePacket(this.createTeamDestructionPacket());
}
public void addPlayer(Player player) {
final String newElement = player.getUsername();
/**
* Adds a member to the {@link Team}
* <br>
* This member can be a {@link Player} or an {@link LivingEntity}
*
* @param member The member to be added
*/
public void addMember(String member) {
final String[] entitiesCache = new String[this.entities.length + 1];
System.arraycopy(this.entities, 0, entitiesCache, 0, this.entities.length);
entitiesCache[this.entities.length] = member;
this.entities = entitiesCache;
this.teamsCreationPacket.entities = this.entities;
TeamsPacket addPlayerPacket = new TeamsPacket();
addPlayerPacket.teamName = teamName;
// Adds a new member to the team
this.members.add(member);
// Initializes add player packet
final TeamsPacket addPlayerPacket = new TeamsPacket();
addPlayerPacket.teamName = this.teamName;
addPlayerPacket.action = TeamsPacket.Action.ADD_PLAYERS_TEAM;
addPlayerPacket.entities = new String[]{newElement};
for (Player p : players) {
p.getPlayerConnection().sendPacket(addPlayerPacket);
}
String[] entitiesCache = new String[entities.length + 1];
System.arraycopy(entities, 0, entitiesCache, 0, entities.length);
entitiesCache[entities.length] = newElement;
this.entities = entitiesCache;
this.teamsCreationPacket.entities = entities;
this.players.add(player);
player.getPlayerConnection().sendPacket(teamsCreationPacket);
addPlayerPacket.entities = new String[]{member};
// Sends to all online players the add player packet
PacketWriterUtils.writeAndSend(MinecraftServer.getConnectionManager().getOnlinePlayers(), addPlayerPacket);
}
public void removePlayer(Player player) {
TeamsPacket removePlayerPacket = new TeamsPacket();
removePlayerPacket.teamName = teamName;
/**
* Removes a member from the {@link Team}
*
* @param member The member to be removed
*/
public void removeMember(String member) {
// Initializes remove player packet
final TeamsPacket removePlayerPacket = new TeamsPacket();
removePlayerPacket.teamName = this.teamName;
removePlayerPacket.action = TeamsPacket.Action.REMOVE_PLAYERS_TEAM;
removePlayerPacket.entities = new String[]{player.getUsername()};
for (Player p : players) {
p.getPlayerConnection().sendPacket(removePlayerPacket);
}
removePlayerPacket.entities = new String[]{member};
// Sends to all online player teh remove player packet
PacketWriterUtils.writeAndSend(MinecraftServer.getConnectionManager().getOnlinePlayers(), removePlayerPacket);
this.players.remove(player);
player.getPlayerConnection().sendPacket(teamsDestroyPacket, true); // TODO do not destroy, simply remove the player from the team
// Removes the player from the
this.members.remove(member);
String[] entitiesCache = new String[entities.length - 1];
final String[] entitiesCache = new String[this.entities.length - 1];
int count = 0;
for (Player p : players) {
entitiesCache[count++] = p.getUsername();
for (String teamMember : this.members) {
entitiesCache[count++] = teamMember;
}
this.entities = entitiesCache;
this.teamsCreationPacket.entities = entities;
this.teamsCreationPacket.entities = this.entities;
}
/**
* Change the display name of the team
* <br><br>
* <b>Warning:</b> This is only changed on the <b>server side</b>
*
* @param teamDisplayName The new display name
*/
public void setTeamDisplayName(ColoredText teamDisplayName) {
this.teamDisplayName = teamDisplayName;
this.teamsCreationPacket.teamDisplayName = teamDisplayName.toString();
}
/**
* Change the display name of the team and sends an update packet
*
* @param teamDisplayName The new display name
*/
public void updateTeamDisplayName(ColoredText teamDisplayName) {
this.setTeamDisplayName(teamDisplayName);
sendUpdatePacket();
}
public void setNameTagVisibility(TeamsPacket.NameTagVisibility nameTagVisibility) {
this.nameTagVisibility = nameTagVisibility;
this.teamsCreationPacket.nameTagVisibility = nameTagVisibility;
/**
* Change the {@link NameTagVisibility} of the team
* <br><br>
* <b>Warning:</b> This is only changed on the <b>server side</b>
*
* @param visibility The new tag visibility
*/
public void setNameTagVisibility(NameTagVisibility visibility) {
this.nameTagVisibility = visibility;
this.teamsCreationPacket.nameTagVisibility = visibility;
}
/**
* Change the {@link NameTagVisibility} of the team and sends an update packet
*
* @param nameTagVisibility The new tag visibility
*/
public void updateNameTagVisibility(NameTagVisibility nameTagVisibility) {
this.setNameTagVisibility(nameTagVisibility);
sendUpdatePacket();
}
public void setCollisionRule(TeamsPacket.CollisionRule collisionRule) {
this.collisionRule = collisionRule;
this.teamsCreationPacket.collisionRule = collisionRule;
/**
* Change the {@link CollisionRule} of the team
* <br><br>
* <b>Warning:</b> This is only changed on the <b>server side</b>
*
* @param rule The new rule
*/
public void setCollisionRule(CollisionRule rule) {
this.collisionRule = rule;
this.teamsCreationPacket.collisionRule = rule;
}
/**
* Change the collision rule of the team and sends an update packet
*
* @param collisionRule The new collision rule
*/
public void updateCollisionRule(CollisionRule collisionRule) {
this.setCollisionRule(collisionRule);
sendUpdatePacket();
}
public void setTeamColor(ChatColor teamColor) {
this.teamColor = teamColor;
this.teamsCreationPacket.teamColor = teamColor.getId();
/**
* Change the color of the team
* <br><br>
* <b>Warning:</b> This is only changed on the <b>server side</b>
*
* @param color The new team color
*/
public void setTeamColor(ChatColor color) {
this.teamColor = color;
this.teamsCreationPacket.teamColor = color.getId();
}
/**
* Change the color of the team and sends an update packet
*
* @param teamColor The new team color
*/
public void updateTeamColor(ChatColor teamColor) {
this.setTeamColor(teamColor);
sendUpdatePacket();
}
/**
* Change the prefix of the team
* <br><br>
* <b>Warning:</b> This is only changed on the <b>server side</b>
*
* @param prefix The new prefix
*/
public void setPrefix(ColoredText prefix) {
this.prefix = prefix;
this.teamsCreationPacket.teamPrefix = prefix.toString();
}
/**
* Change the prefix of the team and sends an update packet
*
* @param prefix The new prefix
*/
public void updatePrefix(ColoredText prefix) {
this.setPrefix(prefix);
sendUpdatePacket();
}
/**
* Change the suffix of the team
* <br><br>
* <b>Warning:</b> This is only changed on the <b>server side</b>
*
* @param suffix The new suffix
*/
public void setSuffix(ColoredText suffix) {
this.suffix = suffix;
this.teamsCreationPacket.teamSuffix = suffix.toString();
}
/**
* Change the suffix of the team and sends an update packet
*
* @param suffix The new suffix
*/
public void updateSuffix(ColoredText suffix) {
this.setSuffix(suffix);
sendUpdatePacket();
}
/**
* Change the friendly flags of the team
* <br><br>
* <b>Warning:</b> This is only changed on the <b>server side</b>
*
* @param flag The new friendly flag
*/
public void setFriendlyFlags(byte flag) {
this.friendlyFlags = flag;
this.teamsCreationPacket.friendlyFlags = flag;
}
/**
* Change the friendly flags of the team and sends an update packet
*
* @param flag The new friendly flag
*/
public void updateFriendlyFlags(byte flag) {
this.setFriendlyFlags(flag);
this.sendUpdatePacket();
}
/**
* Gets the registry name of the team
*
* @return the registry name
*/
public String getTeamName() {
return teamName;
}
/**
* Gets the creation packet to add a team
*
* @return the packet to add the team
*/
public TeamsPacket getTeamsCreationPacket() {
return teamsCreationPacket;
}
public ByteBuf getTeamsDestroyPacket() {
return teamsDestroyPacket;
}
/**
* Creates an destruction packet to remove the team
*
* @return the packet to remove the team
*/
public TeamsPacket createTeamDestructionPacket() {
TeamsPacket teamsPacket = new TeamsPacket();
teamsPacket.teamName = teamName;
@ -144,22 +352,99 @@ public class Team {
return teamsPacket;
}
public Set<Player> getPlayers() {
return Collections.unmodifiableSet(players);
/**
* Obtains an unmodifiable {@link Set} of registered players who are on the team
*
* @return an unmodifiable {@link Set} of registered players
*/
public Set<String> getMembers() {
return Collections.unmodifiableSet(members);
}
private void sendUpdatePacket() {
TeamsPacket updatePacket = new TeamsPacket();
updatePacket.teamName = teamName;
/**
* Gets the display name of the team
*
* @return the display name
*/
public ColoredText getTeamDisplayName() {
return teamDisplayName;
}
/**
* Gets the friendly flags of the team
*
* @return the friendly flags
*/
public byte getFriendlyFlags() {
return friendlyFlags;
}
/**
* Gets the tag visibility of the team
*
* @return the tag visibility
*/
public NameTagVisibility getNameTagVisibility() {
return nameTagVisibility;
}
/**
* Gets the collision rule of the team
*
* @return the collision rule
*/
public CollisionRule getCollisionRule() {
return collisionRule;
}
/**
* Gets the color of the team
*
* @return the team color
*/
public ChatColor getTeamColor() {
return teamColor;
}
/**
* Gets the prefix of the team
*
* @return the team prefix
*/
public ColoredText getPrefix() {
return prefix;
}
/**
* Gets the suffix of the team
*
* @return the suffix team
*/
public ColoredText getSuffix() {
return suffix;
}
public String[] getEntities() {
return entities;
}
/**
* Sends an {@link TeamsPacket.Action#UPDATE_TEAM_INFO} packet
*/
public void sendUpdatePacket() {
final TeamsPacket updatePacket = new TeamsPacket();
updatePacket.teamName = this.teamName;
updatePacket.action = TeamsPacket.Action.UPDATE_TEAM_INFO;
updatePacket.teamDisplayName = teamDisplayName.toString();
updatePacket.friendlyFlags = friendlyFlags;
updatePacket.nameTagVisibility = nameTagVisibility;
updatePacket.collisionRule = collisionRule;
updatePacket.teamColor = teamColor.getId();
updatePacket.teamPrefix = prefix.toString();
updatePacket.teamSuffix = suffix.toString();
updatePacket.teamDisplayName = this.teamDisplayName.toString();
updatePacket.friendlyFlags = this.friendlyFlags;
updatePacket.nameTagVisibility = this.nameTagVisibility;
updatePacket.collisionRule = this.collisionRule;
updatePacket.teamColor = this.teamColor.getId();
updatePacket.teamPrefix = this.prefix.toString();
updatePacket.teamSuffix = this.suffix.toString();
ByteBuf buffer = PacketUtils.writePacket(updatePacket);
players.forEach(p -> p.getPlayerConnection().sendPacket(buffer, true));
for (Player onlinePlayer : MinecraftServer.getConnectionManager().getOnlinePlayers()) {
onlinePlayer.getPlayerConnection().sendPacket(buffer, true);
}
}
}

View 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;
}
}

View File

@ -1,21 +1,140 @@
package net.minestom.server.scoreboard;
import net.minestom.server.MinecraftServer;
import net.minestom.server.chat.ChatColor;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.entity.Player;
import net.minestom.server.network.PacketWriterUtils;
import net.minestom.server.network.packet.server.ServerPacket;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
// TODO
/**
* An object which manages all the {@link Team}'s
*/
public final class TeamManager {
// Represents all registered teams
private Set<Team> teams = new CopyOnWriteArraySet<>();
/**
* Represents all registered teams
*/
private final Set<Team> teams;
public Team createTeam(String teamName) {
Team team = new Team(teamName);
this.teams.add(team);
return team;
/**
* Default constructor
*/
public TeamManager() {
this.teams = new CopyOnWriteArraySet<>();
}
/**
* Registers a new {@link Team}
*
* @param team The team to be registered
*/
protected void registerNewTeam(Team team) {
this.teams.add(team);
this.broadcastPacket(team.getTeamsCreationPacket());
}
/**
* 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 Set} with all registered {@link Team}'s
*
* @return a {@link Set} with all registered {@link Team}'s
*/
public Set<Team> getTeams() {
return teams;
return this.teams;
}
/**
* Broadcasts to all online {@link Player}'s a {@link ServerPacket}
*
* @param packet The packet to broadcast
*/
private void broadcastPacket(ServerPacket packet) {
PacketWriterUtils.writeAndSend(MinecraftServer.getConnectionManager().getOnlinePlayers(), packet);
}
}