mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-04 23:47:59 +01:00
new scoreboard protocol number format conformance (#98)
* new scoreboard protocol conformance * fix: pass number format through when reading scoreboard packet --------- Co-authored-by: mworzala <mattheworzala@gmail.com>
This commit is contained in:
parent
6d5b1ea77e
commit
2003f75f1f
@ -64,6 +64,7 @@ public class Main {
|
||||
commandManager.register(new NotificationCommand());
|
||||
commandManager.register(new TestCommand2());
|
||||
commandManager.register(new ConfigCommand());
|
||||
commandManager.register(new SidebarCommand());
|
||||
|
||||
commandManager.setUnknownCommandCallback((sender, command) -> sender.sendMessage(Component.text("Unknown command", NamedTextColor.RED)));
|
||||
|
||||
|
@ -0,0 +1,99 @@
|
||||
package net.minestom.demo.commands;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import net.minestom.server.command.CommandSender;
|
||||
import net.minestom.server.command.builder.Command;
|
||||
import net.minestom.server.command.builder.CommandContext;
|
||||
import net.minestom.server.command.builder.arguments.ArgumentType;
|
||||
import net.minestom.server.command.builder.condition.Conditions;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.scoreboard.Sidebar;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SidebarCommand extends Command {
|
||||
private final Sidebar sidebar = new Sidebar(Component.text("DEMO").decorate(TextDecoration.BOLD));
|
||||
private int currentLine = 0;
|
||||
|
||||
public SidebarCommand() {
|
||||
super("sidebar");
|
||||
|
||||
addLine("BLANK ", Sidebar.NumberFormat.blank());
|
||||
addLine("STYLE ", Sidebar.NumberFormat.styled(Component.empty().decorate(TextDecoration.STRIKETHROUGH).color(NamedTextColor.GRAY)));
|
||||
addLine("FIXED ", Sidebar.NumberFormat.fixed(Component.text("FIXED").color(NamedTextColor.GRAY)));
|
||||
addLine("NULL ", null);
|
||||
|
||||
setDefaultExecutor((source, args) -> source.sendMessage(Component.text("Unknown syntax (note: title must be quoted)")));
|
||||
setCondition(Conditions::playerOnly);
|
||||
|
||||
var option = ArgumentType.Word("option").from("add-line", "remove-line", "set-title", "toggle", "update-content", "update-score");
|
||||
var content = ArgumentType.String("content").setDefaultValue("");
|
||||
var targetLine = ArgumentType.Integer("target line").setDefaultValue(-1);
|
||||
|
||||
addSyntax(this::handleSidebar, option);
|
||||
addSyntax(this::handleSidebar, option, content);
|
||||
addSyntax(this::handleSidebar, option, content, targetLine);
|
||||
}
|
||||
|
||||
|
||||
private void handleSidebar(CommandSender source, CommandContext context) {
|
||||
Player player = (Player) source;
|
||||
String option = context.get("option");
|
||||
String content = context.get("content");
|
||||
int targetLine = context.get("target line");
|
||||
if (targetLine == -1) targetLine = currentLine;
|
||||
switch (option) {
|
||||
case "add-line":
|
||||
addLine(content, null);
|
||||
break;
|
||||
case "remove-line":
|
||||
removeLine();
|
||||
break;
|
||||
case "set-title":
|
||||
setTitle(content);
|
||||
break;
|
||||
case "toggle":
|
||||
toggleSidebar(player);
|
||||
break;
|
||||
case "update-content":
|
||||
updateLineContent(content, String.valueOf(targetLine));
|
||||
break;
|
||||
case "update-score":
|
||||
updateLineScore(Integer.parseInt(content), String.valueOf(targetLine));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void addLine(@NotNull String content, @Nullable Sidebar.NumberFormat numberFormat) {
|
||||
if (currentLine < 16) {
|
||||
sidebar.createLine(new Sidebar.ScoreboardLine(String.valueOf(currentLine), Component.text(content).color(NamedTextColor.WHITE), currentLine, numberFormat));
|
||||
currentLine++;
|
||||
}
|
||||
}
|
||||
|
||||
private void removeLine() {
|
||||
if (currentLine > 0) {
|
||||
sidebar.removeLine(String.valueOf(currentLine));
|
||||
currentLine--;
|
||||
}
|
||||
}
|
||||
|
||||
private void setTitle(@NotNull String title) {
|
||||
sidebar.setTitle(Component.text(title).decorate(TextDecoration.BOLD));
|
||||
}
|
||||
|
||||
private void toggleSidebar(Player player) {
|
||||
if (sidebar.getViewers().contains(player)) sidebar.removeViewer(player);
|
||||
else sidebar.addViewer(player);
|
||||
}
|
||||
|
||||
private void updateLineContent(@NotNull String content, @NotNull String lineId) {
|
||||
sidebar.updateLineContent(lineId, Component.text(content).color(NamedTextColor.WHITE));
|
||||
}
|
||||
|
||||
private void updateLineScore(int score, @NotNull String lineId) {
|
||||
sidebar.updateLineScore(lineId, score);
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import net.minestom.server.network.NetworkBuffer;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.scoreboard.Sidebar;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -18,25 +19,28 @@ import static net.minestom.server.network.NetworkBuffer.*;
|
||||
|
||||
public record ScoreboardObjectivePacket(@NotNull String objectiveName, byte mode,
|
||||
@Nullable Component objectiveValue,
|
||||
@Nullable Type type) implements ComponentHoldingServerPacket {
|
||||
@Nullable Type type,
|
||||
@Nullable Sidebar.NumberFormat numberFormat) implements ComponentHoldingServerPacket {
|
||||
public ScoreboardObjectivePacket(@NotNull NetworkBuffer reader) {
|
||||
this(read(reader));
|
||||
}
|
||||
|
||||
private ScoreboardObjectivePacket(ScoreboardObjectivePacket packet) {
|
||||
this(packet.objectiveName, packet.mode, packet.objectiveValue, packet.type);
|
||||
this(packet.objectiveName, packet.mode, packet.objectiveValue, packet.type, packet.numberFormat);
|
||||
}
|
||||
|
||||
private static ScoreboardObjectivePacket read(@NotNull NetworkBuffer reader) {
|
||||
var objectiveName = reader.read(STRING);
|
||||
var mode = reader.read(BYTE);
|
||||
String objectiveName = reader.read(STRING);
|
||||
byte mode = reader.read(BYTE);
|
||||
Component objectiveValue = null;
|
||||
Type type = null;
|
||||
Sidebar.NumberFormat numberFormat = null;
|
||||
if (mode == 0 || mode == 2) {
|
||||
objectiveValue = reader.read(COMPONENT);
|
||||
type = Type.values()[reader.read(VAR_INT)];
|
||||
numberFormat = reader.readOptional(Sidebar.NumberFormat::new);
|
||||
}
|
||||
return new ScoreboardObjectivePacket(objectiveName, mode, objectiveValue, type);
|
||||
return new ScoreboardObjectivePacket(objectiveName, mode, objectiveValue, type, numberFormat);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -48,6 +52,7 @@ public record ScoreboardObjectivePacket(@NotNull String objectiveName, byte mode
|
||||
writer.write(COMPONENT, objectiveValue);
|
||||
assert type != null;
|
||||
writer.write(VAR_INT, type.ordinal());
|
||||
writer.writeOptional(numberFormat);
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +73,7 @@ public record ScoreboardObjectivePacket(@NotNull String objectiveName, byte mode
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
return mode == 0 || mode == 2 ? new ScoreboardObjectivePacket(objectiveName, mode,
|
||||
operator.apply(objectiveValue), type) : this;
|
||||
operator.apply(objectiveValue), type, numberFormat) : this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,6 +5,7 @@ import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.NetworkBuffer;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.scoreboard.Sidebar;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -20,11 +21,11 @@ public record UpdateScorePacket(
|
||||
@NotNull String objectiveName,
|
||||
int score,
|
||||
@Nullable Component displayName,
|
||||
@Nullable NumberFormat numberFormat
|
||||
@Nullable Sidebar.NumberFormat numberFormat
|
||||
) implements ServerPacket {
|
||||
public UpdateScorePacket(@NotNull NetworkBuffer reader) {
|
||||
this(reader.read(STRING), reader.read(STRING), reader.read(VAR_INT),
|
||||
reader.readOptional(COMPONENT), new NumberFormat(reader));
|
||||
reader.readOptional(COMPONENT), reader.readOptional(Sidebar.NumberFormat::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -43,17 +44,4 @@ public record UpdateScorePacket(
|
||||
default -> PacketUtils.invalidPacketState(getClass(), state, ConnectionState.PLAY);
|
||||
};
|
||||
}
|
||||
|
||||
public record NumberFormat() implements Writer {
|
||||
|
||||
public NumberFormat(@NotNull NetworkBuffer reader) {
|
||||
this();
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull NetworkBuffer writer) {
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import net.minestom.server.adventure.audience.PacketGroupingAudience;
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
@ -38,7 +37,7 @@ public interface Scoreboard extends Viewable, PacketGroupingAudience {
|
||||
* @return the creation objective packet
|
||||
*/
|
||||
default @NotNull ScoreboardObjectivePacket getCreationObjectivePacket(Component value, ScoreboardObjectivePacket.Type type) {
|
||||
return new ScoreboardObjectivePacket(getObjectiveName(), (byte) 0, value, type);
|
||||
return new ScoreboardObjectivePacket(getObjectiveName(), (byte) 0, value, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,7 +46,7 @@ public interface Scoreboard extends Viewable, PacketGroupingAudience {
|
||||
* @return the destruction objective packet
|
||||
*/
|
||||
default @NotNull ScoreboardObjectivePacket getDestructionObjectivePacket() {
|
||||
return new ScoreboardObjectivePacket(getObjectiveName(), (byte) 1, null, null);
|
||||
return new ScoreboardObjectivePacket(getObjectiveName(), (byte) 1, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4,10 +4,8 @@ import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
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.TeamsPacket;
|
||||
import net.minestom.server.network.packet.server.play.UpdateScorePacket;
|
||||
import net.minestom.server.network.NetworkBuffer;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -98,7 +96,7 @@ public class Sidebar implements Scoreboard {
|
||||
public void setTitle(@NotNull Component title) {
|
||||
this.title = title;
|
||||
sendPacketToViewers(new ScoreboardObjectivePacket(objectiveName, (byte) 2, title,
|
||||
ScoreboardObjectivePacket.Type.INTEGER));
|
||||
ScoreboardObjectivePacket.Type.INTEGER, null));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -260,6 +258,10 @@ public class Sidebar implements Scoreboard {
|
||||
* The score of the line
|
||||
*/
|
||||
private int line;
|
||||
/**
|
||||
* The number format of the line
|
||||
*/
|
||||
private NumberFormat numberFormat;
|
||||
|
||||
private final String teamName;
|
||||
/**
|
||||
@ -273,9 +275,14 @@ public class Sidebar implements Scoreboard {
|
||||
private SidebarTeam sidebarTeam;
|
||||
|
||||
public ScoreboardLine(@NotNull String id, @NotNull Component content, int line) {
|
||||
this(id, content, line, null);
|
||||
}
|
||||
|
||||
public ScoreboardLine(@NotNull String id, @NotNull Component content, int line, @Nullable NumberFormat numberFormat) {
|
||||
this.id = id;
|
||||
this.content = content;
|
||||
this.line = line;
|
||||
this.numberFormat = numberFormat;
|
||||
|
||||
this.teamName = TEAM_PREFIX + COUNTER.incrementAndGet();
|
||||
}
|
||||
@ -335,9 +342,8 @@ public class Sidebar implements Scoreboard {
|
||||
* @return a {@link UpdateScorePacket}
|
||||
*/
|
||||
private UpdateScorePacket getScoreCreationPacket(String objectiveName) {
|
||||
//todo
|
||||
throw new UnsupportedOperationException();
|
||||
// return new UpdateScorePacket(entityName, (byte) 0, objectiveName, line);
|
||||
//TODO displayName acts as a suffix to the objective name, find way to handle elegantly
|
||||
return new UpdateScorePacket(entityName, objectiveName, line, Component.empty(), numberFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -346,10 +352,8 @@ public class Sidebar implements Scoreboard {
|
||||
* @param objectiveName The objective name to be destroyed
|
||||
* @return a {@link UpdateScorePacket}
|
||||
*/
|
||||
private UpdateScorePacket getScoreDestructionPacket(String objectiveName) {
|
||||
//todo
|
||||
throw new UnsupportedOperationException();
|
||||
// return new UpdateScorePacket(entityName, (byte) 1, objectiveName, 0);
|
||||
private ResetScorePacket getScoreDestructionPacket(String objectiveName) {
|
||||
return new ResetScorePacket(entityName, objectiveName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -360,9 +364,8 @@ public class Sidebar implements Scoreboard {
|
||||
* @return a {@link UpdateScorePacket}
|
||||
*/
|
||||
private UpdateScorePacket getLineScoreUpdatePacket(String objectiveName, int score) {
|
||||
//todo
|
||||
throw new UnsupportedOperationException();
|
||||
// return new UpdateScorePacket(entityName, (byte) 0, objectiveName, score);
|
||||
//TODO displayName acts as a suffix to the objective name, find way to handle elegantly
|
||||
return new UpdateScorePacket(entityName, objectiveName, score, Component.empty(), numberFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -466,4 +469,70 @@ public class Sidebar implements Scoreboard {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class NumberFormat implements NetworkBuffer.Writer {
|
||||
private final FormatType formatType;
|
||||
private final Component content;
|
||||
|
||||
private NumberFormat() {
|
||||
this.content = null;
|
||||
this.formatType = FormatType.BLANK;
|
||||
}
|
||||
|
||||
private NumberFormat(@NotNull Component content, @NotNull FormatType formatType) {
|
||||
this.content = content;
|
||||
this.formatType = formatType;
|
||||
}
|
||||
|
||||
public NumberFormat(NetworkBuffer reader) {
|
||||
this.formatType = FormatType.values()[reader.read(NetworkBuffer.VAR_INT)];
|
||||
if (formatType != FormatType.BLANK) this.content = reader.read(NetworkBuffer.COMPONENT);
|
||||
else this.content = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull NetworkBuffer writer) {
|
||||
writer.write(NetworkBuffer.VAR_INT, formatType.ordinal());
|
||||
if (formatType == FormatType.STYLED) {
|
||||
assert content != null;
|
||||
writer.write(NetworkBuffer.COMPONENT, content);
|
||||
}
|
||||
else if (formatType == FormatType.FIXED) {
|
||||
assert content != null;
|
||||
writer.write(NetworkBuffer.COMPONENT, content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A number format which has no sidebar score displayed
|
||||
*
|
||||
* @return a blank number format
|
||||
*/
|
||||
public static @NotNull NumberFormat blank() {
|
||||
return new NumberFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
* A number format which lets the sidebar scores be styled
|
||||
*
|
||||
* @param style a styled component
|
||||
*/
|
||||
public static @NotNull NumberFormat styled(@NotNull Component style) {
|
||||
return new NumberFormat(style, FormatType.STYLED);
|
||||
}
|
||||
|
||||
/**
|
||||
* A number format which lets the sidebar scores be styled with explicit text
|
||||
*
|
||||
* @param content the fixed component
|
||||
*/
|
||||
public static @NotNull NumberFormat fixed(@NotNull Component content) {
|
||||
return new NumberFormat(content, FormatType.FIXED);
|
||||
}
|
||||
|
||||
private enum FormatType {
|
||||
BLANK, STYLED, FIXED
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user