|
|
|
|
@@ -395,14 +395,40 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String getDisplayName() {
|
|
|
|
|
if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper
|
|
|
|
|
return this.getHandle().displayName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setDisplayName(final String name) {
|
|
|
|
|
this.getHandle().adventure$displayName = name != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(name) : net.kyori.adventure.text.Component.text(this.getName()); // Paper
|
|
|
|
|
this.getHandle().displayName = name == null ? this.getName() : name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Paper start
|
|
|
|
|
@Override
|
|
|
|
|
public void playerListName(net.kyori.adventure.text.Component name) {
|
|
|
|
|
getHandle().listName = name == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(name);
|
|
|
|
|
if (getHandle().connection == null) return; // Updates are possible before the player has fully joined
|
|
|
|
|
for (ServerPlayer player : server.getHandle().players) {
|
|
|
|
|
if (player.getBukkitEntity().canSee(this)) {
|
|
|
|
|
player.connection.send(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME, getHandle()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@Override
|
|
|
|
|
public net.kyori.adventure.text.Component playerListName() {
|
|
|
|
|
return getHandle().listName == null ? net.kyori.adventure.text.Component.text(getName()) : io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().listName);
|
|
|
|
|
}
|
|
|
|
|
@Override
|
|
|
|
|
public net.kyori.adventure.text.Component playerListHeader() {
|
|
|
|
|
return playerListHeader;
|
|
|
|
|
}
|
|
|
|
|
@Override
|
|
|
|
|
public net.kyori.adventure.text.Component playerListFooter() {
|
|
|
|
|
return playerListFooter;
|
|
|
|
|
}
|
|
|
|
|
// Paper end
|
|
|
|
|
@Override
|
|
|
|
|
public String getPlayerListName() {
|
|
|
|
|
return this.getHandle().listName == null ? this.getName() : CraftChatMessage.fromComponent(this.getHandle().listName);
|
|
|
|
|
@@ -414,6 +440,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
|
name = this.getName();
|
|
|
|
|
}
|
|
|
|
|
this.getHandle().listName = name.equals(this.getName()) ? null : CraftChatMessage.fromStringOrNull(name);
|
|
|
|
|
if (this.getHandle().connection == null) return; // Paper - Updates are possible before the player has fully joined
|
|
|
|
|
for (ServerPlayer player : (List<ServerPlayer>) this.server.getHandle().players) {
|
|
|
|
|
if (player.getBukkitEntity().canSee(this)) {
|
|
|
|
|
player.connection.send(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME, this.getHandle()));
|
|
|
|
|
@@ -433,42 +460,42 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
|
this.getHandle().listOrder = order;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Component playerListHeader;
|
|
|
|
|
private Component playerListFooter;
|
|
|
|
|
private net.kyori.adventure.text.Component playerListHeader; // Paper - Adventure
|
|
|
|
|
private net.kyori.adventure.text.Component playerListFooter; // Paper - Adventure
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String getPlayerListHeader() {
|
|
|
|
|
return (this.playerListHeader == null) ? null : CraftChatMessage.fromComponent(this.playerListHeader);
|
|
|
|
|
return (this.playerListHeader == null) ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.playerListHeader);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String getPlayerListFooter() {
|
|
|
|
|
return (this.playerListFooter == null) ? null : CraftChatMessage.fromComponent(this.playerListFooter);
|
|
|
|
|
return (this.playerListFooter == null) ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.playerListFooter); // Paper - Adventure
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setPlayerListHeader(String header) {
|
|
|
|
|
this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true);
|
|
|
|
|
this.playerListHeader = header == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(header); // Paper - Adventure
|
|
|
|
|
this.updatePlayerListHeaderFooter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setPlayerListFooter(String footer) {
|
|
|
|
|
this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true);
|
|
|
|
|
this.playerListFooter = footer == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(footer); // Paper - Adventure
|
|
|
|
|
this.updatePlayerListHeaderFooter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setPlayerListHeaderFooter(String header, String footer) {
|
|
|
|
|
this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true);
|
|
|
|
|
this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true);
|
|
|
|
|
this.playerListHeader = header == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(header); // Paper - Adventure
|
|
|
|
|
this.playerListFooter = footer == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(footer); // Paper - Adventure
|
|
|
|
|
this.updatePlayerListHeaderFooter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updatePlayerListHeaderFooter() {
|
|
|
|
|
if (this.getHandle().connection == null) return;
|
|
|
|
|
|
|
|
|
|
ClientboundTabListPacket packet = new ClientboundTabListPacket((this.playerListHeader == null) ? Component.empty() : this.playerListHeader, (this.playerListFooter == null) ? Component.empty() : this.playerListFooter);
|
|
|
|
|
ClientboundTabListPacket packet = new ClientboundTabListPacket(io.papermc.paper.adventure.PaperAdventure.asVanillaNullToEmpty(this.playerListHeader), io.papermc.paper.adventure.PaperAdventure.asVanillaNullToEmpty(this.playerListFooter)); // Paper - adventure
|
|
|
|
|
this.getHandle().connection.send(packet);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -498,6 +525,23 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
|
this.getHandle().transferCookieConnection.kickPlayer(CraftChatMessage.fromStringOrEmpty(message, true));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Paper start
|
|
|
|
|
private static final net.kyori.adventure.text.Component DEFAULT_KICK_COMPONENT = net.kyori.adventure.text.Component.translatable("multiplayer.disconnect.kicked");
|
|
|
|
|
@Override
|
|
|
|
|
public void kick() {
|
|
|
|
|
this.kick(DEFAULT_KICK_COMPONENT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void kick(final net.kyori.adventure.text.Component message) {
|
|
|
|
|
org.spigotmc.AsyncCatcher.catchOp("player kick");
|
|
|
|
|
final ServerGamePacketListenerImpl connection = this.getHandle().connection;
|
|
|
|
|
if (connection != null) {
|
|
|
|
|
connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Paper end
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setCompassTarget(Location loc) {
|
|
|
|
|
Preconditions.checkArgument(loc != null, "Location cannot be null");
|
|
|
|
|
@@ -794,6 +838,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
|
this.getHandle().connection.send(packet);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Paper start
|
|
|
|
|
@Override
|
|
|
|
|
public void sendSignChange(Location loc, @Nullable List<? extends net.kyori.adventure.text.Component> lines, DyeColor dyeColor, boolean hasGlowingText) {
|
|
|
|
|
if (getHandle().connection == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (lines == null) {
|
|
|
|
|
lines = new java.util.ArrayList<>(4);
|
|
|
|
|
}
|
|
|
|
|
Preconditions.checkArgument(loc != null, "Location cannot be null");
|
|
|
|
|
Preconditions.checkArgument(dyeColor != null, "DyeColor cannot be null");
|
|
|
|
|
if (lines.size() < 4) {
|
|
|
|
|
throw new IllegalArgumentException("Must have at least 4 lines");
|
|
|
|
|
}
|
|
|
|
|
Component[] components = CraftSign.sanitizeLines(lines);
|
|
|
|
|
this.sendSignChange0(components, loc, dyeColor, hasGlowingText);
|
|
|
|
|
}
|
|
|
|
|
// Paper end
|
|
|
|
|
@Override
|
|
|
|
|
public void sendSignChange(Location loc, String[] lines) {
|
|
|
|
|
this.sendSignChange(loc, lines, DyeColor.BLACK);
|
|
|
|
|
@@ -817,6 +879,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
|
if (this.getHandle().connection == null) return;
|
|
|
|
|
|
|
|
|
|
Component[] components = CraftSign.sanitizeLines(lines);
|
|
|
|
|
// Paper start - adventure
|
|
|
|
|
this.sendSignChange0(components, loc, dyeColor, hasGlowingText);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void sendSignChange0(Component[] components, Location loc, DyeColor dyeColor, boolean hasGlowingText) {
|
|
|
|
|
// Paper end
|
|
|
|
|
SignBlockEntity sign = new SignBlockEntity(CraftLocation.toBlockPosition(loc), Blocks.OAK_SIGN.defaultBlockState());
|
|
|
|
|
SignText text = sign.getFrontText();
|
|
|
|
|
text = text.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData()));
|
|
|
|
|
@@ -1843,7 +1911,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setResourcePack(String url) {
|
|
|
|
|
this.setResourcePack(url, null);
|
|
|
|
|
this.setResourcePack(url, (byte[]) null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@@ -1858,7 +1926,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setResourcePack(String url, byte[] hash, boolean force) {
|
|
|
|
|
this.setResourcePack(url, hash, null, force);
|
|
|
|
|
this.setResourcePack(url, hash, (String) null, force);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@@ -1895,6 +1963,59 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
|
this.handlePushResourcePack(new ClientboundResourcePackPushPacket(id, url, hashStr, force, CraftChatMessage.fromStringOrOptional(prompt, true)), false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Paper start - adventure
|
|
|
|
|
@Override
|
|
|
|
|
public void setResourcePack(final UUID uuid, final String url, final byte[] hashBytes, final net.kyori.adventure.text.Component prompt, final boolean force) {
|
|
|
|
|
Preconditions.checkArgument(uuid != null, "Resource pack UUID cannot be null");
|
|
|
|
|
Preconditions.checkArgument(url != null, "Resource pack URL cannot be null");
|
|
|
|
|
final String hash;
|
|
|
|
|
if (hashBytes != null) {
|
|
|
|
|
Preconditions.checkArgument(hashBytes.length == 20, "Resource pack hash should be 20 bytes long but was " + hashBytes.length);
|
|
|
|
|
hash = BaseEncoding.base16().lowerCase().encode(hashBytes);
|
|
|
|
|
} else {
|
|
|
|
|
hash = "";
|
|
|
|
|
}
|
|
|
|
|
this.getHandle().connection.send(new ClientboundResourcePackPopPacket(Optional.empty()));
|
|
|
|
|
this.getHandle().connection.send(new ClientboundResourcePackPushPacket(uuid, url, hash, force, Optional.ofNullable(prompt).map(io.papermc.paper.adventure.PaperAdventure::asVanilla)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
|
|
|
|
void sendBundle(final List<? extends net.minecraft.network.protocol.Packet<? extends net.minecraft.network.protocol.common.ClientCommonPacketListener>> packet) {
|
|
|
|
|
this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundBundlePacket((List) packet));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void sendResourcePacks(final net.kyori.adventure.resource.ResourcePackRequest request) {
|
|
|
|
|
if (this.getHandle().connection == null) return;
|
|
|
|
|
final List<ClientboundResourcePackPushPacket> packs = new java.util.ArrayList<>(request.packs().size());
|
|
|
|
|
if (request.replace()) {
|
|
|
|
|
this.clearResourcePacks();
|
|
|
|
|
}
|
|
|
|
|
final Component prompt = io.papermc.paper.adventure.PaperAdventure.asVanilla(request.prompt());
|
|
|
|
|
for (final java.util.Iterator<net.kyori.adventure.resource.ResourcePackInfo> iter = request.packs().iterator(); iter.hasNext();) {
|
|
|
|
|
final net.kyori.adventure.resource.ResourcePackInfo pack = iter.next();
|
|
|
|
|
packs.add(new ClientboundResourcePackPushPacket(pack.id(), pack.uri().toASCIIString(), pack.hash(), request.required(), iter.hasNext() ? Optional.empty() : Optional.ofNullable(prompt)));
|
|
|
|
|
if (request.callback() != net.kyori.adventure.resource.ResourcePackCallback.noOp()) {
|
|
|
|
|
this.getHandle().connection.packCallbacks.put(pack.id(), request.callback()); // just override if there is a previously existing callback
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.sendBundle(packs);
|
|
|
|
|
super.sendResourcePacks(request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void removeResourcePacks(final UUID id, final UUID ... others) {
|
|
|
|
|
if (this.getHandle().connection == null) return;
|
|
|
|
|
this.sendBundle(net.kyori.adventure.util.MonkeyBars.nonEmptyArrayToList(pack -> new ClientboundResourcePackPopPacket(Optional.of(pack)), id, others));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void clearResourcePacks() {
|
|
|
|
|
if (this.getHandle().connection == null) return;
|
|
|
|
|
this.getHandle().connection.send(new ClientboundResourcePackPopPacket(Optional.empty()));
|
|
|
|
|
}
|
|
|
|
|
// Paper end - adventure
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void removeResourcePack(UUID id) {
|
|
|
|
|
Preconditions.checkArgument(id != null, "Resource pack id cannot be null");
|
|
|
|
|
@@ -2300,6 +2421,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
|
return (this.getHandle().requestedViewDistance() == 0) ? Bukkit.getViewDistance() : this.getHandle().requestedViewDistance();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Paper start
|
|
|
|
|
@Override
|
|
|
|
|
public java.util.Locale locale() {
|
|
|
|
|
return getHandle().adventure$locale;
|
|
|
|
|
}
|
|
|
|
|
// Paper end
|
|
|
|
|
@Override
|
|
|
|
|
public int getPing() {
|
|
|
|
|
return this.getHandle().connection.latency();
|
|
|
|
|
@@ -2350,6 +2477,248 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
|
return this.getHandle().allowsListing();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Paper start
|
|
|
|
|
@Override
|
|
|
|
|
public net.kyori.adventure.text.Component displayName() {
|
|
|
|
|
return this.getHandle().adventure$displayName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void displayName(final net.kyori.adventure.text.Component displayName) {
|
|
|
|
|
this.getHandle().adventure$displayName = displayName != null ? displayName : net.kyori.adventure.text.Component.text(this.getName());
|
|
|
|
|
this.getHandle().displayName = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void deleteMessage(net.kyori.adventure.chat.SignedMessage.Signature signature) {
|
|
|
|
|
if (getHandle().connection == null) return;
|
|
|
|
|
net.minecraft.network.chat.MessageSignature sig = new net.minecraft.network.chat.MessageSignature(signature.bytes());
|
|
|
|
|
|
|
|
|
|
this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundDeleteChatPacket(new net.minecraft.network.chat.MessageSignature.Packed(sig)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private net.minecraft.network.chat.ChatType.Bound toHandle(net.kyori.adventure.chat.ChatType.Bound boundChatType) {
|
|
|
|
|
net.minecraft.core.Registry<net.minecraft.network.chat.ChatType> chatTypeRegistry = this.getHandle().level().registryAccess().lookupOrThrow(net.minecraft.core.registries.Registries.CHAT_TYPE);
|
|
|
|
|
|
|
|
|
|
return new net.minecraft.network.chat.ChatType.Bound(
|
|
|
|
|
chatTypeRegistry.getOrThrow(net.minecraft.resources.ResourceKey.create(net.minecraft.core.registries.Registries.CHAT_TYPE, io.papermc.paper.adventure.PaperAdventure.asVanilla(boundChatType.type().key()))),
|
|
|
|
|
io.papermc.paper.adventure.PaperAdventure.asVanilla(boundChatType.name()),
|
|
|
|
|
Optional.ofNullable(io.papermc.paper.adventure.PaperAdventure.asVanilla(boundChatType.target()))
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void sendMessage(net.kyori.adventure.text.Component message, net.kyori.adventure.chat.ChatType.Bound boundChatType) {
|
|
|
|
|
if (getHandle().connection == null) return;
|
|
|
|
|
|
|
|
|
|
net.minecraft.network.chat.Component component = io.papermc.paper.adventure.PaperAdventure.asVanilla(message);
|
|
|
|
|
this.getHandle().sendChatMessage(new net.minecraft.network.chat.OutgoingChatMessage.Disguised(component), this.getHandle().isTextFilteringEnabled(), this.toHandle(boundChatType));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void sendMessage(net.kyori.adventure.chat.SignedMessage signedMessage, net.kyori.adventure.chat.ChatType.Bound boundChatType) {
|
|
|
|
|
if (getHandle().connection == null) return;
|
|
|
|
|
|
|
|
|
|
if (signedMessage instanceof PlayerChatMessage.AdventureView view) {
|
|
|
|
|
this.getHandle().sendChatMessage(net.minecraft.network.chat.OutgoingChatMessage.create(view.playerChatMessage()), this.getHandle().isTextFilteringEnabled(), this.toHandle(boundChatType));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
net.kyori.adventure.text.Component message = signedMessage.unsignedContent() == null ? net.kyori.adventure.text.Component.text(signedMessage.message()) : signedMessage.unsignedContent();
|
|
|
|
|
if (signedMessage.isSystem()) {
|
|
|
|
|
this.sendMessage(message, boundChatType);
|
|
|
|
|
} else {
|
|
|
|
|
super.sendMessage(signedMessage, boundChatType);
|
|
|
|
|
}
|
|
|
|
|
// net.minecraft.network.chat.PlayerChatMessage playerChatMessage = new net.minecraft.network.chat.PlayerChatMessage(
|
|
|
|
|
// null, // TODO:
|
|
|
|
|
// new net.minecraft.network.chat.MessageSignature(signedMessage.signature().bytes()),
|
|
|
|
|
// null, // TODO
|
|
|
|
|
// io.papermc.paper.adventure.PaperAdventure.asVanilla(signedMessage.unsignedContent()),
|
|
|
|
|
// net.minecraft.network.chat.FilterMask.PASS_THROUGH
|
|
|
|
|
// );
|
|
|
|
|
//
|
|
|
|
|
// this.getHandle().sendChatMessage(net.minecraft.network.chat.OutgoingChatMessage.create(playerChatMessage), this.getHandle().isTextFilteringEnabled(), this.toHandle(boundChatType));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Deprecated(forRemoval = true)
|
|
|
|
|
@Override
|
|
|
|
|
public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) {
|
|
|
|
|
if (getHandle().connection == null) return;
|
|
|
|
|
final net.minecraft.core.Registry<net.minecraft.network.chat.ChatType> chatTypeRegistry = this.getHandle().level().registryAccess().lookupOrThrow(net.minecraft.core.registries.Registries.CHAT_TYPE);
|
|
|
|
|
this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSystemChatPacket(message, false));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void sendActionBar(final net.kyori.adventure.text.Component message) {
|
|
|
|
|
final net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket packet = new net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket(io.papermc.paper.adventure.PaperAdventure.asVanillaNullToEmpty(message));
|
|
|
|
|
this.getHandle().connection.send(packet);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void sendPlayerListHeader(final net.kyori.adventure.text.Component header) {
|
|
|
|
|
this.playerListHeader = header;
|
|
|
|
|
this.adventure$sendPlayerListHeaderAndFooter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void sendPlayerListFooter(final net.kyori.adventure.text.Component footer) {
|
|
|
|
|
this.playerListFooter = footer;
|
|
|
|
|
this.adventure$sendPlayerListHeaderAndFooter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void sendPlayerListHeaderAndFooter(final net.kyori.adventure.text.Component header, final net.kyori.adventure.text.Component footer) {
|
|
|
|
|
this.playerListHeader = header;
|
|
|
|
|
this.playerListFooter = footer;
|
|
|
|
|
this.adventure$sendPlayerListHeaderAndFooter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void adventure$sendPlayerListHeaderAndFooter() {
|
|
|
|
|
final ServerGamePacketListenerImpl connection = this.getHandle().connection;
|
|
|
|
|
if (connection == null) return;
|
|
|
|
|
final ClientboundTabListPacket packet = new ClientboundTabListPacket(
|
|
|
|
|
io.papermc.paper.adventure.PaperAdventure.asVanillaNullToEmpty(this.playerListHeader),
|
|
|
|
|
io.papermc.paper.adventure.PaperAdventure.asVanillaNullToEmpty(this.playerListFooter)
|
|
|
|
|
);
|
|
|
|
|
connection.send(packet);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void showTitle(final net.kyori.adventure.title.Title title) {
|
|
|
|
|
final ServerGamePacketListenerImpl connection = this.getHandle().connection;
|
|
|
|
|
final net.kyori.adventure.title.Title.Times times = title.times();
|
|
|
|
|
if (times != null) {
|
|
|
|
|
connection.send(new ClientboundSetTitlesAnimationPacket(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut())));
|
|
|
|
|
}
|
|
|
|
|
final ClientboundSetSubtitleTextPacket sp = new ClientboundSetSubtitleTextPacket(io.papermc.paper.adventure.PaperAdventure.asVanilla(title.subtitle()));
|
|
|
|
|
connection.send(sp);
|
|
|
|
|
final ClientboundSetTitleTextPacket tp = new ClientboundSetTitleTextPacket(io.papermc.paper.adventure.PaperAdventure.asVanilla(title.title()));
|
|
|
|
|
connection.send(tp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public <T> void sendTitlePart(final net.kyori.adventure.title.TitlePart<T> part, T value) {
|
|
|
|
|
java.util.Objects.requireNonNull(part, "part");
|
|
|
|
|
java.util.Objects.requireNonNull(value, "value");
|
|
|
|
|
if (part == net.kyori.adventure.title.TitlePart.TITLE) {
|
|
|
|
|
final ClientboundSetTitleTextPacket tp = new ClientboundSetTitleTextPacket(io.papermc.paper.adventure.PaperAdventure.asVanilla((net.kyori.adventure.text.Component)value));
|
|
|
|
|
this.getHandle().connection.send(tp);
|
|
|
|
|
} else if (part == net.kyori.adventure.title.TitlePart.SUBTITLE) {
|
|
|
|
|
final ClientboundSetSubtitleTextPacket sp = new ClientboundSetSubtitleTextPacket(io.papermc.paper.adventure.PaperAdventure.asVanilla((net.kyori.adventure.text.Component)value));
|
|
|
|
|
this.getHandle().connection.send(sp);
|
|
|
|
|
} else if (part == net.kyori.adventure.title.TitlePart.TIMES) {
|
|
|
|
|
final net.kyori.adventure.title.Title.Times times = (net.kyori.adventure.title.Title.Times) value;
|
|
|
|
|
this.getHandle().connection.send(new ClientboundSetTitlesAnimationPacket(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut())));
|
|
|
|
|
} else {
|
|
|
|
|
throw new IllegalArgumentException("Unknown TitlePart");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static int ticks(final java.time.Duration duration) {
|
|
|
|
|
if (duration == null) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return (int) (duration.toMillis() / 50L);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void clearTitle() {
|
|
|
|
|
this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundClearTitlesPacket(false));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// resetTitle implemented above
|
|
|
|
|
|
|
|
|
|
private @Nullable Set<net.kyori.adventure.bossbar.BossBar> activeBossBars;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public @NotNull Iterable<? extends net.kyori.adventure.bossbar.BossBar> activeBossBars() {
|
|
|
|
|
if (this.activeBossBars != null) {
|
|
|
|
|
return java.util.Collections.unmodifiableSet(this.activeBossBars);
|
|
|
|
|
}
|
|
|
|
|
return Set.of();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void showBossBar(final net.kyori.adventure.bossbar.BossBar bar) {
|
|
|
|
|
net.kyori.adventure.bossbar.BossBarImplementation.get(bar, io.papermc.paper.adventure.BossBarImplementationImpl.class).playerShow(this);
|
|
|
|
|
if (this.activeBossBars == null) {
|
|
|
|
|
this.activeBossBars = new HashSet<>();
|
|
|
|
|
}
|
|
|
|
|
this.activeBossBars.add(bar);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void hideBossBar(final net.kyori.adventure.bossbar.BossBar bar) {
|
|
|
|
|
net.kyori.adventure.bossbar.BossBarImplementation.get(bar, io.papermc.paper.adventure.BossBarImplementationImpl.class).playerHide(this);
|
|
|
|
|
if (this.activeBossBars != null) {
|
|
|
|
|
this.activeBossBars.remove(bar);
|
|
|
|
|
if (this.activeBossBars.isEmpty()) {
|
|
|
|
|
this.activeBossBars = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void playSound(final net.kyori.adventure.sound.Sound sound) {
|
|
|
|
|
final net.minecraft.world.phys.Vec3 pos = this.getHandle().position();
|
|
|
|
|
this.playSound(sound, pos.x, pos.y, pos.z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void playSound(final net.kyori.adventure.sound.Sound sound, final double x, final double y, final double z) {
|
|
|
|
|
this.getHandle().connection.send(io.papermc.paper.adventure.PaperAdventure.asSoundPacket(sound, x, y, z, sound.seed().orElseGet(this.getHandle().getRandom()::nextLong), null));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void playSound(final net.kyori.adventure.sound.Sound sound, final net.kyori.adventure.sound.Sound.Emitter emitter) {
|
|
|
|
|
final Entity entity;
|
|
|
|
|
if (emitter == net.kyori.adventure.sound.Sound.Emitter.self()) {
|
|
|
|
|
entity = this.getHandle();
|
|
|
|
|
} else if (emitter instanceof CraftEntity craftEntity) {
|
|
|
|
|
entity = craftEntity.getHandle();
|
|
|
|
|
} else {
|
|
|
|
|
throw new IllegalArgumentException("Sound emitter must be an Entity or self(), but was: " + emitter);
|
|
|
|
|
}
|
|
|
|
|
this.getHandle().connection.send(io.papermc.paper.adventure.PaperAdventure.asSoundPacket(sound, entity, sound.seed().orElseGet(this.getHandle().getRandom()::nextLong), null));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void stopSound(final net.kyori.adventure.sound.SoundStop stop) {
|
|
|
|
|
this.getHandle().connection.send(new ClientboundStopSoundPacket(
|
|
|
|
|
io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.sound()),
|
|
|
|
|
io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.source())
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void openBook(final net.kyori.adventure.inventory.Book book) {
|
|
|
|
|
final java.util.Locale locale = this.getHandle().adventure$locale;
|
|
|
|
|
final net.minecraft.world.item.ItemStack item = io.papermc.paper.adventure.PaperAdventure.asItemStack(book, locale);
|
|
|
|
|
final ServerPlayer player = this.getHandle();
|
|
|
|
|
final ServerGamePacketListenerImpl connection = player.connection;
|
|
|
|
|
final net.minecraft.world.entity.player.Inventory inventory = player.getInventory();
|
|
|
|
|
final int slot = inventory.items.size() + inventory.selected;
|
|
|
|
|
final int stateId = getHandle().containerMenu.getStateId();
|
|
|
|
|
connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, stateId, slot, item));
|
|
|
|
|
connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND));
|
|
|
|
|
connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, stateId, slot, inventory.getSelected()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public net.kyori.adventure.pointer.Pointers pointers() {
|
|
|
|
|
if (this.adventure$pointers == null) {
|
|
|
|
|
this.adventure$pointers = net.kyori.adventure.pointer.Pointers.builder()
|
|
|
|
|
.withDynamic(net.kyori.adventure.identity.Identity.DISPLAY_NAME, this::displayName)
|
|
|
|
|
.withDynamic(net.kyori.adventure.identity.Identity.NAME, this::getName)
|
|
|
|
|
.withDynamic(net.kyori.adventure.identity.Identity.UUID, this::getUniqueId)
|
|
|
|
|
.withStatic(net.kyori.adventure.permission.PermissionChecker.POINTER, this::permissionValue)
|
|
|
|
|
.withDynamic(net.kyori.adventure.identity.Identity.LOCALE, this::locale)
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this.adventure$pointers;
|
|
|
|
|
}
|
|
|
|
|
// Paper end
|
|
|
|
|
// Spigot start
|
|
|
|
|
private final Player.Spigot spigot = new Player.Spigot()
|
|
|
|
|
{
|
|
|
|
|
|