merge upstream
This commit is contained in:
@@ -19,7 +19,8 @@ import javax.tools.StandardLocation;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.*;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@SupportedAnnotationTypes({"com.velocitypowered.api.plugin.Plugin"})
|
||||
public class PluginAnnotationProcessor extends AbstractProcessor {
|
||||
|
@@ -26,4 +26,19 @@ public interface Command {
|
||||
default List<String> suggest(@NonNull CommandSource source, @NonNull String[] currentArgs) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to check if the {@code source} has permission to use this command
|
||||
* with the provided {@code args}.
|
||||
*
|
||||
* <p>If this method returns false, the handling will be forwarded onto
|
||||
* the players current server.</p>
|
||||
*
|
||||
* @param source the source of the command
|
||||
* @param args the arguments for this command
|
||||
* @return whether the source has permission
|
||||
*/
|
||||
default boolean hasPermission(@NonNull CommandSource source, @NonNull String[] args) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,105 @@
|
||||
package com.velocitypowered.api.event.connection;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.velocitypowered.api.event.ResultedEvent;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSource;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This event is fired when a plugin message is sent to the proxy, either from a client ({@link com.velocitypowered.api.proxy.Player})
|
||||
* or a server ({@link com.velocitypowered.api.proxy.ServerConnection}).
|
||||
*/
|
||||
public class PluginMessageEvent implements ResultedEvent<PluginMessageEvent.ForwardResult> {
|
||||
private final ChannelMessageSource source;
|
||||
private final ChannelMessageSink target;
|
||||
private final ChannelIdentifier identifier;
|
||||
private final byte[] data;
|
||||
private ForwardResult result;
|
||||
|
||||
public PluginMessageEvent(ChannelMessageSource source, ChannelMessageSink target, ChannelIdentifier identifier, byte[] data) {
|
||||
this.source = Preconditions.checkNotNull(source, "source");
|
||||
this.target = Preconditions.checkNotNull(target, "target");
|
||||
this.identifier = Preconditions.checkNotNull(identifier, "identifier");
|
||||
this.data = Preconditions.checkNotNull(data, "data");
|
||||
this.result = ForwardResult.forward();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForwardResult getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResult(@NonNull ForwardResult result) {
|
||||
this.result = Preconditions.checkNotNull(result, "result");
|
||||
}
|
||||
|
||||
public ChannelMessageSource getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public ChannelMessageSink getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public ChannelIdentifier getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return Arrays.copyOf(data, data.length);
|
||||
}
|
||||
|
||||
public ByteArrayDataInput dataAsDataStream() {
|
||||
return ByteStreams.newDataInput(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PluginMessageEvent{" +
|
||||
"source=" + source +
|
||||
", target=" + target +
|
||||
", identifier=" + identifier +
|
||||
", data=" + Arrays.toString(data) +
|
||||
", result=" + result +
|
||||
'}';
|
||||
}
|
||||
|
||||
/**
|
||||
* A result determining whether or not to forward this message on.
|
||||
*/
|
||||
public static class ForwardResult implements ResultedEvent.Result {
|
||||
private static final ForwardResult ALLOWED = new ForwardResult(true);
|
||||
private static final ForwardResult DENIED = new ForwardResult(false);
|
||||
|
||||
private final boolean allowed;
|
||||
|
||||
private ForwardResult(boolean b) {
|
||||
this.allowed = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowed() {
|
||||
return allowed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return allowed ? "forward to sink" : "handled message at proxy";
|
||||
}
|
||||
|
||||
public static ForwardResult forward() {
|
||||
return ALLOWED;
|
||||
}
|
||||
|
||||
public static ForwardResult handled() {
|
||||
return DENIED;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package com.velocitypowered.api.event.connection;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
|
||||
/**
|
||||
* This event is fired once the player has been successfully authenticated and
|
||||
* fully initialized and player will be connected to server after this event
|
||||
*/
|
||||
public class PostLoginEvent {
|
||||
|
||||
private final Player player;
|
||||
|
||||
public PostLoginEvent(Player player) {
|
||||
this.player = Preconditions.checkNotNull(player, "player");
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PostLoginEvent{"
|
||||
+ "player=" + player
|
||||
+ '}';
|
||||
}
|
||||
}
|
@@ -3,12 +3,13 @@ package com.velocitypowered.api.event.connection;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.event.ResultedEvent;
|
||||
import com.velocitypowered.api.proxy.InboundConnection;
|
||||
|
||||
import net.kyori.text.Component;
|
||||
|
||||
import net.kyori.text.serializer.ComponentSerializers;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* This event is fired when a player has initiated a connection with the proxy but before the proxy authenticates the
|
||||
* player with Mojang or before the player's proxy connection is fully established (for offline mode).
|
||||
@@ -52,44 +53,59 @@ public class PreLoginEvent implements ResultedEvent<PreLoginEvent.PreLoginCompon
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an "allowed/allowed with online mode/denied" result with a reason allowed for denial.
|
||||
* Represents an "allowed/allowed with forced online\offline mode/denied" result with a reason allowed for denial.
|
||||
*/
|
||||
public static class PreLoginComponentResult extends ResultedEvent.ComponentResult {
|
||||
private static final PreLoginComponentResult ALLOWED = new PreLoginComponentResult((Component) null);
|
||||
private static final PreLoginComponentResult FORCE_ONLINEMODE = new PreLoginComponentResult(true);
|
||||
public static class PreLoginComponentResult implements ResultedEvent.Result {
|
||||
|
||||
private final boolean onlineMode;
|
||||
private static final PreLoginComponentResult ALLOWED = new PreLoginComponentResult(Result.ALLOWED, null);
|
||||
private static final PreLoginComponentResult FORCE_ONLINEMODE = new PreLoginComponentResult(Result.FORCE_ONLINE, null);
|
||||
private static final PreLoginComponentResult FORCE_OFFLINEMODE = new PreLoginComponentResult(Result.FORCE_OFFLINE, null);
|
||||
|
||||
/**
|
||||
* Allows online mode to be enabled for the player connection, if Velocity is running in offline mode.
|
||||
* @param allowedOnlineMode if true, online mode will be used for the connection
|
||||
*/
|
||||
private PreLoginComponentResult(boolean allowedOnlineMode) {
|
||||
super(true, null);
|
||||
this.onlineMode = allowedOnlineMode;
|
||||
private final Result result;
|
||||
private final Optional<Component> reason;
|
||||
|
||||
private PreLoginComponentResult(Result result, @Nullable Component reason) {
|
||||
this.result = result;
|
||||
this.reason = Optional.ofNullable(reason);
|
||||
}
|
||||
|
||||
private PreLoginComponentResult(@Nullable Component reason) {
|
||||
super(reason == null, reason);
|
||||
// Don't care about this
|
||||
this.onlineMode = false;
|
||||
@Override
|
||||
public boolean isAllowed() {
|
||||
return result != Result.DISALLOWED;
|
||||
}
|
||||
|
||||
public Optional<Component> getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public boolean isOnlineModeAllowed() {
|
||||
return this.onlineMode;
|
||||
return result == Result.FORCE_ONLINE;
|
||||
}
|
||||
|
||||
public boolean isForceOfflineMode() {
|
||||
return result == Result.FORCE_OFFLINE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isForceOfflineMode()) {
|
||||
return "allowed with force offline mode";
|
||||
}
|
||||
if (isOnlineModeAllowed()) {
|
||||
return "allowed with online mode";
|
||||
}
|
||||
|
||||
return super.toString();
|
||||
if (isAllowed()) {
|
||||
return "allowed";
|
||||
}
|
||||
if (reason.isPresent()) {
|
||||
return "denied: " + ComponentSerializers.PLAIN.serialize(reason.get());
|
||||
}
|
||||
return "denied";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a result indicating the connection will be allowed through the proxy.
|
||||
* Returns a result indicating the connection will be allowed through
|
||||
* the proxy.
|
||||
* @return the allowed result
|
||||
*/
|
||||
public static PreLoginComponentResult allowed() {
|
||||
@@ -97,23 +113,41 @@ public class PreLoginEvent implements ResultedEvent<PreLoginEvent.PreLoginCompon
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a result indicating the connection will be allowed through the proxy, but the connection will be
|
||||
* forced to use online mode provided that the proxy is in offline mode. This acts similarly to {@link #allowed()}
|
||||
* on an online-mode proxy.
|
||||
* Returns a result indicating the connection will be allowed through
|
||||
* the proxy, but the connection will be forced to use online mode
|
||||
* provided that the proxy is in offline mode. This acts similarly to
|
||||
* {@link #allowed()} on an online-mode proxy.
|
||||
* @return the result
|
||||
*/
|
||||
public static PreLoginComponentResult forceOnlineMode() {
|
||||
return FORCE_ONLINEMODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a result indicating the connection will be allowed through
|
||||
* the proxy, but the connection will be forced to use offline mode even
|
||||
* when proxy running in online mode
|
||||
* @return the result
|
||||
*/
|
||||
public static PreLoginComponentResult forceOfflineMode() {
|
||||
return FORCE_OFFLINEMODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Denies the login with the specified reason.
|
||||
* @param reason the reason for disallowing the connection
|
||||
* @return a new result
|
||||
*/
|
||||
public static PreLoginComponentResult denied(@NonNull Component reason) {
|
||||
public static PreLoginComponentResult denied(Component reason) {
|
||||
Preconditions.checkNotNull(reason, "reason");
|
||||
return new PreLoginComponentResult(reason);
|
||||
return new PreLoginComponentResult(Result.DISALLOWED, reason);
|
||||
}
|
||||
|
||||
private enum Result {
|
||||
ALLOWED,
|
||||
FORCE_ONLINE,
|
||||
FORCE_OFFLINE,
|
||||
DISALLOWED
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,9 @@
|
||||
package com.velocitypowered.api.event.player;
|
||||
|
||||
import com.velocitypowered.api.proxy.InboundConnection;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.proxy.InboundConnection;
|
||||
import com.velocitypowered.api.util.GameProfile;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* This event is fired after the {@link com.velocitypowered.api.event.connection.PreLoginEvent} in order to set up the
|
||||
|
@@ -3,7 +3,7 @@ package com.velocitypowered.api.event.player;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.event.ResultedEvent;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import net.kyori.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
@@ -13,12 +13,12 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
*/
|
||||
public class KickedFromServerEvent implements ResultedEvent<KickedFromServerEvent.ServerKickResult> {
|
||||
private final Player player;
|
||||
private final ServerInfo server;
|
||||
private final RegisteredServer server;
|
||||
private final Component originalReason;
|
||||
private final boolean duringLogin;
|
||||
private ServerKickResult result;
|
||||
|
||||
public KickedFromServerEvent(Player player, ServerInfo server, Component originalReason, boolean duringLogin, Component fancyReason) {
|
||||
public KickedFromServerEvent(Player player, RegisteredServer server, Component originalReason, boolean duringLogin, Component fancyReason) {
|
||||
this.player = Preconditions.checkNotNull(player, "player");
|
||||
this.server = Preconditions.checkNotNull(server, "server");
|
||||
this.originalReason = Preconditions.checkNotNull(originalReason, "originalReason");
|
||||
@@ -40,7 +40,7 @@ public class KickedFromServerEvent implements ResultedEvent<KickedFromServerEven
|
||||
return player;
|
||||
}
|
||||
|
||||
public ServerInfo getServer() {
|
||||
public RegisteredServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@@ -91,9 +91,9 @@ public class KickedFromServerEvent implements ResultedEvent<KickedFromServerEven
|
||||
* when this result is used.
|
||||
*/
|
||||
public static class RedirectPlayer implements ServerKickResult {
|
||||
private final ServerInfo server;
|
||||
private final RegisteredServer server;
|
||||
|
||||
private RedirectPlayer(ServerInfo server) {
|
||||
private RedirectPlayer(RegisteredServer server) {
|
||||
this.server = Preconditions.checkNotNull(server, "server");
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public class KickedFromServerEvent implements ResultedEvent<KickedFromServerEven
|
||||
return false;
|
||||
}
|
||||
|
||||
public ServerInfo getServer() {
|
||||
public RegisteredServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public class KickedFromServerEvent implements ResultedEvent<KickedFromServerEven
|
||||
* @param server the server to send the player to
|
||||
* @return the redirect result
|
||||
*/
|
||||
public static RedirectPlayer create(ServerInfo server) {
|
||||
public static RedirectPlayer create(RegisteredServer server) {
|
||||
return new RedirectPlayer(server);
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
package com.velocitypowered.api.event.player;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.proxy.player.PlayerSettings;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.player.PlayerSettings;
|
||||
|
||||
public class PlayerSettingsChangedEvent {
|
||||
private final Player player;
|
||||
|
@@ -2,7 +2,7 @@ package com.velocitypowered.api.event.player;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
|
||||
/**
|
||||
* This event is fired once the player has successfully connected to the target server and the connection to the previous
|
||||
@@ -10,9 +10,9 @@ import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
*/
|
||||
public class ServerConnectedEvent {
|
||||
private final Player player;
|
||||
private final ServerInfo server;
|
||||
private final RegisteredServer server;
|
||||
|
||||
public ServerConnectedEvent(Player player, ServerInfo server) {
|
||||
public ServerConnectedEvent(Player player, RegisteredServer server) {
|
||||
this.player = Preconditions.checkNotNull(player, "player");
|
||||
this.server = Preconditions.checkNotNull(server, "server");
|
||||
}
|
||||
@@ -21,7 +21,7 @@ public class ServerConnectedEvent {
|
||||
return player;
|
||||
}
|
||||
|
||||
public ServerInfo getServer() {
|
||||
public RegisteredServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,7 @@ package com.velocitypowered.api.event.player;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.event.ResultedEvent;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
@@ -14,11 +14,13 @@ import java.util.Optional;
|
||||
*/
|
||||
public class ServerPreConnectEvent implements ResultedEvent<ServerPreConnectEvent.ServerResult> {
|
||||
private final Player player;
|
||||
private final RegisteredServer originalServer;
|
||||
private ServerResult result;
|
||||
|
||||
public ServerPreConnectEvent(Player player, ServerResult result) {
|
||||
public ServerPreConnectEvent(Player player, RegisteredServer originalServer) {
|
||||
this.player = Preconditions.checkNotNull(player, "player");
|
||||
this.result = Preconditions.checkNotNull(result, "result");
|
||||
this.originalServer = Preconditions.checkNotNull(originalServer, "originalServer");
|
||||
this.result = ServerResult.allowed(originalServer);
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
@@ -35,10 +37,15 @@ public class ServerPreConnectEvent implements ResultedEvent<ServerPreConnectEven
|
||||
this.result = Preconditions.checkNotNull(result, "result");
|
||||
}
|
||||
|
||||
public RegisteredServer getOriginalServer() {
|
||||
return originalServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ServerPreConnectEvent{" +
|
||||
"player=" + player +
|
||||
", originalServer=" + originalServer +
|
||||
", result=" + result +
|
||||
'}';
|
||||
}
|
||||
@@ -50,11 +57,11 @@ public class ServerPreConnectEvent implements ResultedEvent<ServerPreConnectEven
|
||||
private static final ServerResult DENIED = new ServerResult(false, null);
|
||||
|
||||
private final boolean allowed;
|
||||
private final ServerInfo info;
|
||||
private final RegisteredServer server;
|
||||
|
||||
private ServerResult(boolean allowed, @Nullable ServerInfo info) {
|
||||
private ServerResult(boolean allowed, @Nullable RegisteredServer server) {
|
||||
this.allowed = allowed;
|
||||
this.info = info;
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,8 +69,8 @@ public class ServerPreConnectEvent implements ResultedEvent<ServerPreConnectEven
|
||||
return allowed;
|
||||
}
|
||||
|
||||
public Optional<ServerInfo> getInfo() {
|
||||
return Optional.ofNullable(info);
|
||||
public Optional<RegisteredServer> getServer() {
|
||||
return Optional.ofNullable(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,14 +78,14 @@ public class ServerPreConnectEvent implements ResultedEvent<ServerPreConnectEven
|
||||
if (!allowed) {
|
||||
return "denied";
|
||||
}
|
||||
return "allowed: connect to " + info.getName();
|
||||
return "allowed: connect to " + server.getServerInfo().getName();
|
||||
}
|
||||
|
||||
public static ServerResult denied() {
|
||||
return DENIED;
|
||||
}
|
||||
|
||||
public static ServerResult allowed(ServerInfo server) {
|
||||
public static ServerResult allowed(RegisteredServer server) {
|
||||
Preconditions.checkNotNull(server, "server");
|
||||
return new ServerResult(true, server);
|
||||
}
|
||||
|
@@ -29,5 +29,5 @@ public interface PermissionFunction {
|
||||
* @param permission the permission
|
||||
* @return the value the permission is set to
|
||||
*/
|
||||
@NonNull Tristate getPermissionSetting(@NonNull String permission);
|
||||
@NonNull Tristate getPermissionValue(@NonNull String permission);
|
||||
}
|
||||
|
@@ -12,5 +12,15 @@ public interface PermissionSubject {
|
||||
* @param permission the permission to check for
|
||||
* @return whether or not the subject has the permission
|
||||
*/
|
||||
boolean hasPermission(@NonNull String permission);
|
||||
default boolean hasPermission(@NonNull String permission) {
|
||||
return getPermissionValue(permission).asBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the subjects setting for a particular permission.
|
||||
*
|
||||
* @param permission the permission
|
||||
* @return the value the permission is set to
|
||||
*/
|
||||
@NonNull Tristate getPermissionValue(@NonNull String permission);
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package com.velocitypowered.api.plugin.meta;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
|
@@ -1,29 +1,28 @@
|
||||
package com.velocitypowered.api.proxy;
|
||||
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import net.kyori.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Provides a fluent interface to compose and send a connection request to another server behind the proxy. A connection
|
||||
* request is created using {@link Player#createConnectionRequest(ServerInfo)}.
|
||||
* request is created using {@link Player#createConnectionRequest(RegisteredServer)}.
|
||||
*/
|
||||
public interface ConnectionRequestBuilder {
|
||||
/**
|
||||
* Returns the server that this connection request represents.
|
||||
* @return the server this request will connect to
|
||||
*/
|
||||
@NonNull ServerInfo getServer();
|
||||
RegisteredServer getServer();
|
||||
|
||||
/**
|
||||
* Initiates the connection to the remote server and emits a result on the {@link CompletableFuture} after the user
|
||||
* has logged on. No messages will be communicated to the client: the user is responsible for all error handling.
|
||||
* @return a {@link CompletableFuture} representing the status of this connection
|
||||
*/
|
||||
@NonNull CompletableFuture<Result> connect();
|
||||
CompletableFuture<Result> connect();
|
||||
|
||||
/**
|
||||
* Initiates the connection to the remote server without waiting for a result. Velocity will use generic error
|
||||
|
@@ -1,13 +1,15 @@
|
||||
package com.velocitypowered.api.proxy;
|
||||
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.proxy.player.PlayerSettings;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSource;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.api.proxy.player.PlayerSettings;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.util.GameProfile;
|
||||
import com.velocitypowered.api.util.MessagePosition;
|
||||
import com.velocitypowered.api.util.title.Title;
|
||||
import java.util.List;
|
||||
|
||||
import net.kyori.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
@@ -65,10 +67,10 @@ public interface Player extends CommandSource, InboundConnection, ChannelMessage
|
||||
|
||||
/**
|
||||
* Creates a new connection request so that the player can connect to another server.
|
||||
* @param info the server to connect to
|
||||
* @param server the server to connect to
|
||||
* @return a new connection request
|
||||
*/
|
||||
ConnectionRequestBuilder createConnectionRequest(@NonNull ServerInfo info);
|
||||
ConnectionRequestBuilder createConnectionRequest(@NonNull RegisteredServer server);
|
||||
|
||||
/**
|
||||
* Gets a game profile properties of player
|
||||
@@ -100,4 +102,17 @@ public interface Player extends CommandSource, InboundConnection, ChannelMessage
|
||||
* @param reason component with the reason
|
||||
*/
|
||||
void disconnect(Component reason);
|
||||
|
||||
/**
|
||||
* Sends the specified title to the client.
|
||||
* @param title the title to send
|
||||
*/
|
||||
void sendTitle(Title title);
|
||||
|
||||
/**
|
||||
* Sends chat input onto the players current server as if they typed it
|
||||
* into the client chat box.
|
||||
* @param input the chat input to send
|
||||
*/
|
||||
void spoofChatInput(String input);
|
||||
}
|
||||
|
@@ -1,12 +1,14 @@
|
||||
package com.velocitypowered.api.proxy;
|
||||
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.command.CommandManager;
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.event.EventManager;
|
||||
import com.velocitypowered.api.plugin.PluginManager;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelRegistrar;
|
||||
import com.velocitypowered.api.scheduler.Scheduler;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.api.scheduler.Scheduler;
|
||||
import net.kyori.text.Component;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collection;
|
||||
@@ -31,6 +33,12 @@ public interface ProxyServer {
|
||||
*/
|
||||
Optional<Player> getPlayer(UUID uuid);
|
||||
|
||||
/**
|
||||
* Broadcasts a message to all players currently online.
|
||||
* @param component the message to send
|
||||
*/
|
||||
void broadcast(Component component);
|
||||
|
||||
/**
|
||||
* Retrieves all players currently connected to this proxy. This call may or may not be a snapshot of all players
|
||||
* online.
|
||||
@@ -45,23 +53,24 @@ public interface ProxyServer {
|
||||
int getPlayerCount();
|
||||
|
||||
/**
|
||||
* Retrieves a registered {@link ServerInfo} instance by its name. The search is case-insensitive.
|
||||
* Retrieves a registered {@link RegisteredServer} instance by its name. The search is case-insensitive.
|
||||
* @param name the name of the server
|
||||
* @return the registered server, which may be empty
|
||||
*/
|
||||
Optional<ServerInfo> getServerInfo(String name);
|
||||
Optional<RegisteredServer> getServer(String name);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link ServerInfo}s registered with this proxy.
|
||||
* Retrieves all {@link RegisteredServer}s registered with this proxy.
|
||||
* @return the servers registered with this proxy
|
||||
*/
|
||||
Collection<ServerInfo> getAllServers();
|
||||
Collection<RegisteredServer> getAllServers();
|
||||
|
||||
/**
|
||||
* Registers a server with this proxy. A server with this name should not already exist.
|
||||
* @param server the server to register
|
||||
* @return the newly registered server
|
||||
*/
|
||||
void registerServer(ServerInfo server);
|
||||
RegisteredServer registerServer(ServerInfo server);
|
||||
|
||||
/**
|
||||
* Unregisters this server from the proxy.
|
||||
|
@@ -2,6 +2,7 @@ package com.velocitypowered.api.proxy;
|
||||
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSource;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
|
||||
/**
|
||||
@@ -12,6 +13,12 @@ public interface ServerConnection extends ChannelMessageSource, ChannelMessageSi
|
||||
* Returns the server that this connection is connected to.
|
||||
* @return the server this connection is connected to
|
||||
*/
|
||||
RegisteredServer getServer();
|
||||
|
||||
/**
|
||||
* Returns the server info for this connection.
|
||||
* @return the server info for this connection
|
||||
*/
|
||||
ServerInfo getServerInfo();
|
||||
|
||||
/**
|
||||
|
@@ -8,6 +8,7 @@ public interface ChannelMessageSink {
|
||||
* Sends a plugin message to this target.
|
||||
* @param identifier the channel identifier to send the message on
|
||||
* @param data the data to send
|
||||
* @return whether or not the message could be sent
|
||||
*/
|
||||
void sendPluginMessage(ChannelIdentifier identifier, byte[] data);
|
||||
boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data);
|
||||
}
|
||||
|
@@ -1,16 +1,14 @@
|
||||
package com.velocitypowered.api.proxy.messages;
|
||||
|
||||
/**
|
||||
* Represents an interface to register and unregister {@link MessageHandler} instances for handling plugin messages from
|
||||
* the client or the server.
|
||||
* Represents an interface to register and unregister {@link ChannelIdentifier}s for the proxy to listen on.
|
||||
*/
|
||||
public interface ChannelRegistrar {
|
||||
/**
|
||||
* Registers the specified message handler to listen for plugin messages on the specified channels.
|
||||
* @param handler the handler to register
|
||||
* Registers the specified message identifiers to listen on for the
|
||||
* @param identifiers the channel identifiers to register
|
||||
*/
|
||||
void register(MessageHandler handler, ChannelIdentifier... identifiers);
|
||||
void register(ChannelIdentifier... identifiers);
|
||||
|
||||
/**
|
||||
* Unregisters the handler for the specified channel.
|
||||
|
@@ -1,15 +0,0 @@
|
||||
package com.velocitypowered.api.proxy.messages;
|
||||
|
||||
/**
|
||||
* Represents from "which side" of the proxy the plugin message came from.
|
||||
*/
|
||||
public enum ChannelSide {
|
||||
/**
|
||||
* The plugin message came from a server that a client was connected to.
|
||||
*/
|
||||
FROM_SERVER,
|
||||
/**
|
||||
* The plugin message came from the client.
|
||||
*/
|
||||
FROM_CLIENT
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
package com.velocitypowered.api.proxy.messages;
|
||||
|
||||
/**
|
||||
* Represents a handler for handling plugin messages.
|
||||
*/
|
||||
public interface MessageHandler {
|
||||
/**
|
||||
* Handles an incoming plugin message.
|
||||
* @param source the source of the plugin message
|
||||
* @param side from where the plugin message originated
|
||||
* @param identifier the channel on which the message was sent
|
||||
* @param data the data inside the plugin message
|
||||
* @return a {@link ForwardStatus} indicating whether or not to forward this plugin message on
|
||||
*/
|
||||
ForwardStatus handle(ChannelMessageSource source, ChannelSide side, ChannelIdentifier identifier, byte[] data);
|
||||
|
||||
enum ForwardStatus {
|
||||
/**
|
||||
* Forwards this plugin message on to the client or server, depending on the {@link ChannelSide} it originated
|
||||
* from.
|
||||
*/
|
||||
FORWARD,
|
||||
/**
|
||||
* Discard the plugin message and do not forward it on.
|
||||
*/
|
||||
HANDLED
|
||||
}
|
||||
}
|
@@ -10,7 +10,7 @@ import java.util.regex.Pattern;
|
||||
* Represents a Minecraft 1.13+ channel identifier. This class is immutable and safe for multi-threaded use.
|
||||
*/
|
||||
public final class MinecraftChannelIdentifier implements ChannelIdentifier {
|
||||
private static final Pattern VALID_IDENTIFIER_REGEX = Pattern.compile("[a-z0-9\\-_]+", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern VALID_IDENTIFIER_REGEX = Pattern.compile("[a-z0-9\\-_]+");
|
||||
|
||||
private final String namespace;
|
||||
private final String name;
|
||||
|
@@ -0,0 +1,30 @@
|
||||
package com.velocitypowered.api.proxy.server;
|
||||
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Represents a server that has been registered with the proxy.
|
||||
*/
|
||||
public interface RegisteredServer extends ChannelMessageSink {
|
||||
/**
|
||||
* Returns the {@link ServerInfo} for this server.
|
||||
* @return the server info
|
||||
*/
|
||||
ServerInfo getServerInfo();
|
||||
|
||||
/**
|
||||
* Returns a list of all the players currently connected to this server on this proxy.
|
||||
* @return the players on this proxy
|
||||
*/
|
||||
Collection<Player> getPlayersConnected();
|
||||
|
||||
/**
|
||||
* Attempts to ping the remote server and return the server list ping result.
|
||||
* @return the server ping result from the server
|
||||
*/
|
||||
CompletableFuture<ServerPing> ping();
|
||||
}
|
@@ -16,13 +16,13 @@ public class ServerPing {
|
||||
private final Players players;
|
||||
private final Component description;
|
||||
private final @Nullable Favicon favicon;
|
||||
private final Modinfo modinfo;
|
||||
private final ModInfo modinfo;
|
||||
|
||||
public ServerPing(Version version, @Nullable Players players, Component description, @Nullable Favicon favicon) {
|
||||
this(version, players, description, favicon, Modinfo.DEFAULT);
|
||||
this(version, players, description, favicon, ModInfo.DEFAULT);
|
||||
}
|
||||
|
||||
public ServerPing(Version version, @Nullable Players players, Component description, @Nullable Favicon favicon, @Nullable Modinfo modinfo) {
|
||||
public ServerPing(Version version, @Nullable Players players, Component description, @Nullable Favicon favicon, ServerPing.@Nullable ModInfo modinfo) {
|
||||
this.version = Preconditions.checkNotNull(version, "version");
|
||||
this.players = players;
|
||||
this.description = Preconditions.checkNotNull(description, "description");
|
||||
@@ -46,7 +46,7 @@ public class ServerPing {
|
||||
return Optional.ofNullable(favicon);
|
||||
}
|
||||
|
||||
public Optional<Modinfo> getModinfo() {
|
||||
public Optional<ModInfo> getModinfo() {
|
||||
return Optional.ofNullable(modinfo);
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ public class ServerPing {
|
||||
builder.favicon = favicon;
|
||||
builder.nullOutModinfo = modinfo == null;
|
||||
if (modinfo != null) {
|
||||
builder.modType = modinfo.type;
|
||||
builder.mods.addAll(modinfo.modList);
|
||||
}
|
||||
return builder;
|
||||
@@ -91,6 +92,7 @@ public class ServerPing {
|
||||
private int onlinePlayers;
|
||||
private int maximumPlayers;
|
||||
private final List<SamplePlayer> samplePlayers = new ArrayList<>();
|
||||
private String modType;
|
||||
private final List<Mod> mods = new ArrayList<>();
|
||||
private Component description;
|
||||
private Favicon favicon;
|
||||
@@ -121,6 +123,11 @@ public class ServerPing {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder modType(String modType) {
|
||||
this.modType = Preconditions.checkNotNull(modType, "modType");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder mods(Mod... mods) {
|
||||
this.mods.addAll(Arrays.asList(mods));
|
||||
return this;
|
||||
@@ -158,7 +165,7 @@ public class ServerPing {
|
||||
|
||||
public ServerPing build() {
|
||||
return new ServerPing(version, nullOutPlayers ? null : new Players(onlinePlayers, maximumPlayers, samplePlayers), description, favicon,
|
||||
nullOutModinfo ? null : new Modinfo(mods));
|
||||
nullOutModinfo ? null : new ModInfo(modType, mods));
|
||||
}
|
||||
|
||||
public Version getVersion() {
|
||||
@@ -185,6 +192,10 @@ public class ServerPing {
|
||||
return favicon;
|
||||
}
|
||||
|
||||
public String getModType() {
|
||||
return modType;
|
||||
}
|
||||
|
||||
public List<Mod> getMods() {
|
||||
return mods;
|
||||
}
|
||||
@@ -196,6 +207,7 @@ public class ServerPing {
|
||||
", onlinePlayers=" + onlinePlayers +
|
||||
", maximumPlayers=" + maximumPlayers +
|
||||
", samplePlayers=" + samplePlayers +
|
||||
", modType=" + modType +
|
||||
", mods=" + mods +
|
||||
", description=" + description +
|
||||
", favicon=" + favicon +
|
||||
@@ -290,15 +302,24 @@ public class ServerPing {
|
||||
}
|
||||
}
|
||||
|
||||
public static class Modinfo {
|
||||
public static final Modinfo DEFAULT = new Modinfo(ImmutableList.of());
|
||||
public static class ModInfo {
|
||||
public static final ModInfo DEFAULT = new ModInfo("FML", ImmutableList.of());
|
||||
|
||||
private final String type = "FML";
|
||||
private final String type;
|
||||
private final List<Mod> modList;
|
||||
|
||||
public Modinfo(List<Mod> modList) {
|
||||
public ModInfo(String type, List<Mod> modList) {
|
||||
this.type = Preconditions.checkNotNull(type, "type");
|
||||
this.modList = ImmutableList.copyOf(modList);
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public List<Mod> getMods() {
|
||||
return modList;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Mod {
|
||||
@@ -309,5 +330,13 @@ public class ServerPing {
|
||||
this.id = Preconditions.checkNotNull(id, "id");
|
||||
this.version = Preconditions.checkNotNull(version, "version");
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ public interface Scheduler {
|
||||
* @param unit the unit of time for {@code time}
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
TaskBuilder delay(int time, TimeUnit unit);
|
||||
TaskBuilder delay(long time, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Specifies that the task should continue running after waiting for the specified amount, until it is cancelled.
|
||||
@@ -32,7 +32,7 @@ public interface Scheduler {
|
||||
* @param unit the unit of time for {@code time}
|
||||
* @return this builder, for chaining
|
||||
*/
|
||||
TaskBuilder repeat(int time, TimeUnit unit);
|
||||
TaskBuilder repeat(long time, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Clears the delay on this task.
|
||||
|
@@ -1,66 +0,0 @@
|
||||
package com.velocitypowered.api.util;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* LegacyChatColorUtils contains utilities for handling legacy Minecraft color codes. Generally, you should prefer
|
||||
* JSON-based components, but for convenience Velocity provides a limited set of tools to handle Minecraft color codes.
|
||||
*/
|
||||
public class LegacyChatColorUtils {
|
||||
private LegacyChatColorUtils() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the legacy Minecraft format character, the section symbol.
|
||||
*/
|
||||
public static final char FORMAT_CHAR = '\u00a7';
|
||||
|
||||
/**
|
||||
* Translates a string with Minecraft color codes prefixed with a different character than the section symbol into
|
||||
* a string that uses the section symbol.
|
||||
* @param originalChar the char the color codes are prefixed by
|
||||
* @param text the text to translate
|
||||
* @return the translated text
|
||||
*/
|
||||
public static String translate(char originalChar, @NonNull String text) {
|
||||
Preconditions.checkNotNull(text, "text");
|
||||
char[] textChars = text.toCharArray();
|
||||
int foundSectionIdx = -1;
|
||||
for (int i = 0; i < textChars.length; i++) {
|
||||
char textChar = textChars[i];
|
||||
if (textChar == originalChar) {
|
||||
foundSectionIdx = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (foundSectionIdx >= 0) {
|
||||
textChar = Character.toLowerCase(textChar);
|
||||
if ((textChar >= 'a' && textChar <= 'f') || (textChar >= '0' && textChar <= '9') ||
|
||||
(textChar >= 'l' && textChar <= 'o' || textChar == 'r')) {
|
||||
textChars[foundSectionIdx] = FORMAT_CHAR;
|
||||
}
|
||||
foundSectionIdx = -1;
|
||||
}
|
||||
}
|
||||
return new String(textChars);
|
||||
}
|
||||
|
||||
/**
|
||||
* A regex that matches all Minecraft color codes and removes them.
|
||||
*/
|
||||
private static final Pattern CHAT_COLOR_MATCHER = Pattern.compile("(?i)" + Character.toString(FORMAT_CHAR) + "[0-9A-FL-OR]");
|
||||
|
||||
/**
|
||||
* Removes all Minecraft color codes from the string.
|
||||
* @param text the text to remove color codes from
|
||||
* @return a new String without Minecraft color codes
|
||||
*/
|
||||
public static String removeFormatting(@NonNull String text) {
|
||||
Preconditions.checkNotNull(text, "text");
|
||||
return CHAT_COLOR_MATCHER.matcher(text).replaceAll("");
|
||||
}
|
||||
}
|
@@ -0,0 +1,236 @@
|
||||
package com.velocitypowered.api.util.title;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import net.kyori.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Represents a "full" title, including all components. This class is immutable.
|
||||
*/
|
||||
public class TextTitle implements Title {
|
||||
private final Component title;
|
||||
private final Component subtitle;
|
||||
private final int stay;
|
||||
private final int fadeIn;
|
||||
private final int fadeOut;
|
||||
private final boolean resetBeforeSend;
|
||||
|
||||
private TextTitle(Builder builder) {
|
||||
this.title = builder.title;
|
||||
this.subtitle = builder.subtitle;
|
||||
this.stay = builder.stay;
|
||||
this.fadeIn = builder.fadeIn;
|
||||
this.fadeOut = builder.fadeOut;
|
||||
this.resetBeforeSend = builder.resetBeforeSend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the main title this title has, if any.
|
||||
* @return the main title of this title
|
||||
*/
|
||||
public Optional<Component> getTitle() {
|
||||
return Optional.ofNullable(title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subtitle this title has, if any.
|
||||
* @return the subtitle
|
||||
*/
|
||||
public Optional<Component> getSubtitle() {
|
||||
return Optional.ofNullable(subtitle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of ticks this title will stay up.
|
||||
* @return how long the title will stay, in ticks
|
||||
*/
|
||||
public int getStay() {
|
||||
return stay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of ticks over which this title will fade in.
|
||||
* @return how long the title will fade in, in ticks
|
||||
*/
|
||||
public int getFadeIn() {
|
||||
return fadeIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of ticks over which this title will fade out.
|
||||
* @return how long the title will fade out, in ticks
|
||||
*/
|
||||
public int getFadeOut() {
|
||||
return fadeOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not a reset packet will be sent before this title is sent. By default, unless explicitly
|
||||
* disabled, this is enabled by default.
|
||||
* @return whether or not a reset packet will be sent before this title is sent
|
||||
*/
|
||||
public boolean isResetBeforeSend() {
|
||||
return resetBeforeSend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not this title has times set on it. If none are set, it will update the previous title
|
||||
* set on the client.
|
||||
* @return whether or not this title has times set on it
|
||||
*/
|
||||
public boolean areTimesSet() {
|
||||
return stay != 0 || fadeIn != 0 || fadeOut != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new builder from the contents of this title so that it may be changed.
|
||||
* @return a builder instance with the contents of this title
|
||||
*/
|
||||
public Builder toBuilder() {
|
||||
return new Builder(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
TextTitle textTitle = (TextTitle) o;
|
||||
return stay == textTitle.stay &&
|
||||
fadeIn == textTitle.fadeIn &&
|
||||
fadeOut == textTitle.fadeOut &&
|
||||
resetBeforeSend == textTitle.resetBeforeSend &&
|
||||
Objects.equals(title, textTitle.title) &&
|
||||
Objects.equals(subtitle, textTitle.subtitle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TextTitle{" +
|
||||
"title=" + title +
|
||||
", subtitle=" + subtitle +
|
||||
", stay=" + stay +
|
||||
", fadeIn=" + fadeIn +
|
||||
", fadeOut=" + fadeOut +
|
||||
", resetBeforeSend=" + resetBeforeSend +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(title, subtitle, stay, fadeIn, fadeOut, resetBeforeSend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new builder for constructing titles.
|
||||
* @return a builder for constructing titles
|
||||
*/
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private @Nullable Component title;
|
||||
private @Nullable Component subtitle;
|
||||
private int stay;
|
||||
private int fadeIn;
|
||||
private int fadeOut;
|
||||
private boolean resetBeforeSend = true;
|
||||
|
||||
private Builder() {}
|
||||
|
||||
private Builder(TextTitle copy) {
|
||||
this.title = copy.title;
|
||||
this.subtitle = copy.subtitle;
|
||||
this.stay = copy.stay;
|
||||
this.fadeIn = copy.fadeIn;
|
||||
this.fadeOut = copy.fadeOut;
|
||||
this.resetBeforeSend = copy.resetBeforeSend;
|
||||
}
|
||||
|
||||
public Builder title(Component title) {
|
||||
this.title = Preconditions.checkNotNull(title, "title");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder clearTitle() {
|
||||
this.title = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder subtitle(Component subtitle) {
|
||||
this.subtitle = Preconditions.checkNotNull(subtitle, "subtitle");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder clearSubtitle() {
|
||||
this.subtitle = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder stay(int ticks) {
|
||||
Preconditions.checkArgument(ticks >= 0, "ticks value %s is negative", ticks);
|
||||
this.stay = ticks;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder fadeIn(int ticks) {
|
||||
Preconditions.checkArgument(ticks >= 0, "ticks value %s is negative", ticks);
|
||||
this.fadeIn = ticks;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder fadeOut(int ticks) {
|
||||
Preconditions.checkArgument(ticks >= 0, "ticks value %s is negative", ticks);
|
||||
this.fadeOut = ticks;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resetBeforeSend(boolean b) {
|
||||
this.resetBeforeSend = b;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Component getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public Component getSubtitle() {
|
||||
return subtitle;
|
||||
}
|
||||
|
||||
public int getStay() {
|
||||
return stay;
|
||||
}
|
||||
|
||||
public int getFadeIn() {
|
||||
return fadeIn;
|
||||
}
|
||||
|
||||
public int getFadeOut() {
|
||||
return fadeOut;
|
||||
}
|
||||
|
||||
public boolean isResetBeforeSend() {
|
||||
return resetBeforeSend;
|
||||
}
|
||||
|
||||
public TextTitle build() {
|
||||
return new TextTitle(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Builder{" +
|
||||
"title=" + title +
|
||||
", subtitle=" + subtitle +
|
||||
", stay=" + stay +
|
||||
", fadeIn=" + fadeIn +
|
||||
", fadeOut=" + fadeOut +
|
||||
", resetBeforeSend=" + resetBeforeSend +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
package com.velocitypowered.api.util.title;
|
||||
|
||||
/**
|
||||
* Represents a title that can be sent to a Minecraft client.
|
||||
*/
|
||||
public interface Title {
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
package com.velocitypowered.api.util.title;
|
||||
|
||||
/**
|
||||
* Provides special-purpose titles.
|
||||
*/
|
||||
public class Titles {
|
||||
private Titles() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
private static final Title RESET = new Title() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "reset title";
|
||||
}
|
||||
};
|
||||
|
||||
private static final Title HIDE = new Title() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "hide title";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a title that, when sent to the client, will cause all title data to be reset and any existing title to be
|
||||
* hidden.
|
||||
* @return the reset title
|
||||
*/
|
||||
public static Title reset() {
|
||||
return RESET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a title that, when sent to the client, will cause any existing title to be hidden. The title may be
|
||||
* restored by a {@link TextTitle} with no title or subtitle (only a time).
|
||||
* @return the hide title
|
||||
*/
|
||||
public static Title hide() {
|
||||
return HIDE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a builder for {@link TextTitle}s.
|
||||
* @return a builder for text titles
|
||||
*/
|
||||
public static TextTitle.Builder text() {
|
||||
return TextTitle.builder();
|
||||
}
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Provides data structures for creating and manipulating titles.
|
||||
*/
|
||||
package com.velocitypowered.api.util.title;
|
@@ -1,62 +0,0 @@
|
||||
package com.velocitypowered.api.util;
|
||||
|
||||
import com.velocitypowered.api.util.LegacyChatColorUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class LegacyChatColorUtilsTest {
|
||||
private static final String NON_FORMATTED = "Velocity";
|
||||
private static final String FORMATTED = "\u00a7cVelocity";
|
||||
private static final String FORMATTED_MULTIPLE = "\u00a7c\u00a7lVelocity";
|
||||
private static final String FORMATTED_MULTIPLE_VARIED = "\u00a7c\u00a7lVelo\u00a7a\u00a7mcity";
|
||||
private static final String INVALID = "\u00a7gVelocity";
|
||||
private static final String RAW_SECTION = "\u00a7";
|
||||
|
||||
@Test
|
||||
void removeFormattingNonFormatted() {
|
||||
assertEquals(NON_FORMATTED, LegacyChatColorUtils.removeFormatting(NON_FORMATTED));
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeFormattingFormatted() {
|
||||
assertEquals(NON_FORMATTED, LegacyChatColorUtils.removeFormatting(FORMATTED));
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeFormattingFormattedMultiple() {
|
||||
assertEquals(NON_FORMATTED, LegacyChatColorUtils.removeFormatting(FORMATTED_MULTIPLE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeFormattingFormattedMultipleVaried() {
|
||||
assertEquals(NON_FORMATTED, LegacyChatColorUtils.removeFormatting(FORMATTED_MULTIPLE_VARIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeFormattingInvalidFormat() {
|
||||
assertEquals(INVALID, LegacyChatColorUtils.removeFormatting(INVALID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeFormattingRawSection() {
|
||||
assertEquals(RAW_SECTION, LegacyChatColorUtils.removeFormatting(RAW_SECTION));
|
||||
}
|
||||
|
||||
@Test
|
||||
void translate() {
|
||||
assertEquals(FORMATTED, LegacyChatColorUtils.translate('&', "&cVelocity"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void translateMultiple() {
|
||||
assertEquals(FORMATTED_MULTIPLE, LegacyChatColorUtils.translate('&', "&c&lVelocity"));
|
||||
assertEquals(FORMATTED_MULTIPLE_VARIED, LegacyChatColorUtils.translate('&', "&c&lVelo&a&mcity"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void translateDifferentChar() {
|
||||
assertEquals(FORMATTED, LegacyChatColorUtils.translate('$', "$cVelocity"));
|
||||
assertEquals(FORMATTED_MULTIPLE_VARIED, LegacyChatColorUtils.translate('$', "$c$lVelo$a$mcity"));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user