Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-16 21:10:30 +01:00
feat: Add basic API for server links (#1353)
* feat: add basic server links API * refactor: more precondition checking on links * refactor: remove whitespace * refactor: adjust method order, JDs in ServerLink * refactor: remove "throws" from constructors * refactor: add @NotNull annotations * refactor: requested changes * refactor: just use `List#copyOf`
Dieser Commit ist enthalten in:
Ursprung
e60e2063a8
Commit
9d25d309d3
@ -21,6 +21,7 @@ import com.velocitypowered.api.proxy.player.TabList;
|
|||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import com.velocitypowered.api.util.GameProfile;
|
import com.velocitypowered.api.util.GameProfile;
|
||||||
import com.velocitypowered.api.util.ModInfo;
|
import com.velocitypowered.api.util.ModInfo;
|
||||||
|
import com.velocitypowered.api.util.ServerLink;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -461,4 +462,16 @@ public interface Player extends
|
|||||||
* @sinceMinecraft 1.20.5
|
* @sinceMinecraft 1.20.5
|
||||||
*/
|
*/
|
||||||
void requestCookie(Key key);
|
void requestCookie(Key key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the player a list of custom links to display in their client's pause menu.
|
||||||
|
*
|
||||||
|
* <p>Note that later packets sent by the backend server may override links sent by the proxy.
|
||||||
|
*
|
||||||
|
* @param links an ordered list of {@link ServerLink}s to send to the player
|
||||||
|
* @throws IllegalArgumentException if the player is from a version lower than 1.21
|
||||||
|
* @since 3.3.0
|
||||||
|
* @sinceMinecraft 1.21
|
||||||
|
*/
|
||||||
|
void setServerLinks(@NotNull List<ServerLink> links);
|
||||||
}
|
}
|
101
api/src/main/java/com/velocitypowered/api/util/ServerLink.java
Normale Datei
101
api/src/main/java/com/velocitypowered/api/util/ServerLink.java
Normale Datei
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021-2024 Velocity Contributors
|
||||||
|
*
|
||||||
|
* The Velocity API is licensed under the terms of the MIT License. For more details,
|
||||||
|
* reference the LICENSE file in the api top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.velocitypowered.api.util;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Optional;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a custom URL servers can show in player pause menus.
|
||||||
|
* Links can be of a built-in type or use a custom component text label.
|
||||||
|
*/
|
||||||
|
public final class ServerLink {
|
||||||
|
|
||||||
|
private @Nullable Type type;
|
||||||
|
private @Nullable Component label;
|
||||||
|
private final URI url;
|
||||||
|
|
||||||
|
private ServerLink(Component label, String url) {
|
||||||
|
this.label = Preconditions.checkNotNull(label, "label");
|
||||||
|
this.url = URI.create(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServerLink(Type type, String url) {
|
||||||
|
this.type = Preconditions.checkNotNull(type, "type");
|
||||||
|
this.url = URI.create(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a server link with a custom component label.
|
||||||
|
*
|
||||||
|
* @param label a custom component label to display
|
||||||
|
* @param link the URL to open when clicked
|
||||||
|
*/
|
||||||
|
public static ServerLink serverLink(Component label, String link) {
|
||||||
|
return new ServerLink(label, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a server link with a built-in type.
|
||||||
|
*
|
||||||
|
* @param type the {@link Type built-in type} of link
|
||||||
|
* @param link the URL to open when clicked
|
||||||
|
*/
|
||||||
|
public static ServerLink serverLink(Type type, String link) {
|
||||||
|
return new ServerLink(type, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of the server link.
|
||||||
|
*
|
||||||
|
* @return the type of the server link
|
||||||
|
*/
|
||||||
|
public Optional<Type> getBuiltInType() {
|
||||||
|
return Optional.ofNullable(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the custom component label of the server link.
|
||||||
|
*
|
||||||
|
* @return the custom component label of the server link
|
||||||
|
*/
|
||||||
|
public Optional<Component> getCustomLabel() {
|
||||||
|
return Optional.ofNullable(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the link {@link URI}.
|
||||||
|
*
|
||||||
|
* @return the link {@link URI}
|
||||||
|
*/
|
||||||
|
public URI getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Built-in types of server links.
|
||||||
|
*
|
||||||
|
* @apiNote {@link Type#BUG_REPORT} links are shown on the connection error screen
|
||||||
|
*/
|
||||||
|
public enum Type {
|
||||||
|
BUG_REPORT,
|
||||||
|
COMMUNITY_GUIDELINES,
|
||||||
|
SUPPORT,
|
||||||
|
STATUS,
|
||||||
|
FEEDBACK,
|
||||||
|
COMMUNITY,
|
||||||
|
WEBSITE,
|
||||||
|
FORUMS,
|
||||||
|
NEWS,
|
||||||
|
ANNOUNCEMENTS
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -55,6 +55,7 @@ import com.velocitypowered.api.proxy.player.ResourcePackInfo;
|
|||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import com.velocitypowered.api.util.GameProfile;
|
import com.velocitypowered.api.util.GameProfile;
|
||||||
import com.velocitypowered.api.util.ModInfo;
|
import com.velocitypowered.api.util.ModInfo;
|
||||||
|
import com.velocitypowered.api.util.ServerLink;
|
||||||
import com.velocitypowered.proxy.VelocityServer;
|
import com.velocitypowered.proxy.VelocityServer;
|
||||||
import com.velocitypowered.proxy.adventure.VelocityBossBarImplementation;
|
import com.velocitypowered.proxy.adventure.VelocityBossBarImplementation;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||||
@ -83,6 +84,7 @@ import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
|
|||||||
import com.velocitypowered.proxy.protocol.packet.chat.PlayerChatCompletionPacket;
|
import com.velocitypowered.proxy.protocol.packet.chat.PlayerChatCompletionPacket;
|
||||||
import com.velocitypowered.proxy.protocol.packet.chat.builder.ChatBuilderFactory;
|
import com.velocitypowered.proxy.protocol.packet.chat.builder.ChatBuilderFactory;
|
||||||
import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChatPacket;
|
import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChatPacket;
|
||||||
|
import com.velocitypowered.proxy.protocol.packet.config.ClientboundServerLinksPacket;
|
||||||
import com.velocitypowered.proxy.protocol.packet.config.StartUpdatePacket;
|
import com.velocitypowered.proxy.protocol.packet.config.StartUpdatePacket;
|
||||||
import com.velocitypowered.proxy.protocol.packet.title.GenericTitlePacket;
|
import com.velocitypowered.proxy.protocol.packet.title.GenericTitlePacket;
|
||||||
import com.velocitypowered.proxy.protocol.util.ByteBufDataOutput;
|
import com.velocitypowered.proxy.protocol.util.ByteBufDataOutput;
|
||||||
@ -1059,6 +1061,22 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
|||||||
}, connection.eventLoop());
|
}, connection.eventLoop());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setServerLinks(final @NotNull List<ServerLink> links) {
|
||||||
|
Preconditions.checkNotNull(links, "links");
|
||||||
|
Preconditions.checkArgument(
|
||||||
|
this.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_21),
|
||||||
|
"Player version must be at least 1.21 to be able to set server links");
|
||||||
|
|
||||||
|
if (connection.getState() != StateRegistry.PLAY
|
||||||
|
&& connection.getState() != StateRegistry.CONFIG) {
|
||||||
|
throw new IllegalStateException("Can only send server links in CONFIGURATION or PLAY protocol");
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.write(new ClientboundServerLinksPacket(List.copyOf(links).stream()
|
||||||
|
.map(l -> new ClientboundServerLinksPacket.ServerLink(l, getProtocolVersion())).toList()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addCustomChatCompletions(@NotNull Collection<String> completions) {
|
public void addCustomChatCompletions(@NotNull Collection<String> completions) {
|
||||||
Preconditions.checkNotNull(completions, "completions");
|
Preconditions.checkNotNull(completions, "completions");
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
package com.velocitypowered.proxy.protocol.packet.config;
|
package com.velocitypowered.proxy.protocol.packet.config;
|
||||||
|
|
||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
import com.velocitypowered.api.network.ProtocolVersion;
|
||||||
|
import com.velocitypowered.api.util.ServerLink;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
@ -66,6 +67,13 @@ public class ClientboundServerLinksPacket implements MinecraftPacket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public record ServerLink(int id, ComponentHolder displayName, String url) {
|
public record ServerLink(int id, ComponentHolder displayName, String url) {
|
||||||
|
|
||||||
|
public ServerLink(com.velocitypowered.api.util.ServerLink link, ProtocolVersion protocolVersion) {
|
||||||
|
this(link.getBuiltInType().map(Enum::ordinal).orElse(-1),
|
||||||
|
link.getCustomLabel().map(c -> new ComponentHolder(protocolVersion, c)).orElse(null),
|
||||||
|
link.getUrl().toString());
|
||||||
|
}
|
||||||
|
|
||||||
private static ServerLink read(ByteBuf buf, ProtocolVersion version) {
|
private static ServerLink read(ByteBuf buf, ProtocolVersion version) {
|
||||||
if (buf.readBoolean()) {
|
if (buf.readBoolean()) {
|
||||||
return new ServerLink(ProtocolUtils.readVarInt(buf), null, ProtocolUtils.readString(buf));
|
return new ServerLink(ProtocolUtils.readVarInt(buf), null, ProtocolUtils.readString(buf));
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren