Revamp flag system (#789)

This commit is contained in:
Alex 2024-02-29 16:04:25 +01:00 committed by AlexProgrammerDE
parent 44b44d24ad
commit d74e292201
10 changed files with 89 additions and 64 deletions

View file

@ -63,7 +63,7 @@ public class MinecraftProtocolTest {
Server server = new TcpServer(HOST, PORT, MinecraftProtocol::new);
server.setGlobalFlag(MinecraftConstants.SESSION_SERVICE_KEY, sessionService);
server.setGlobalFlag(MinecraftConstants.VERIFY_USERS_KEY, VERIFY_USERS);
server.setGlobalFlag(MinecraftConstants.SERVER_INFO_BUILDER_KEY, (ServerInfoBuilder) session ->
server.setGlobalFlag(MinecraftConstants.SERVER_INFO_BUILDER_KEY, session ->
new ServerStatusInfo(
new VersionInfo(MinecraftCodec.CODEC.getMinecraftVersion(), MinecraftCodec.CODEC.getProtocolVersion()),
new PlayerInfo(100, 0, new ArrayList<>()),
@ -73,7 +73,7 @@ public class MinecraftProtocolTest {
)
);
server.setGlobalFlag(MinecraftConstants.SERVER_LOGIN_HANDLER_KEY, (ServerLoginHandler) session ->
server.setGlobalFlag(MinecraftConstants.SERVER_LOGIN_HANDLER_KEY, session ->
session.send(new ClientboundLoginPacket(
0,
false,
@ -153,7 +153,7 @@ public class MinecraftProtocolTest {
MinecraftProtocol protocol = new MinecraftProtocol();
Session client = new TcpClientSession(HOST, PORT, protocol, PROXY);
client.setFlag(MinecraftConstants.SESSION_SERVICE_KEY, sessionService);
client.setFlag(MinecraftConstants.SERVER_INFO_HANDLER_KEY, (ServerInfoHandler) (session, info) -> {
client.setFlag(MinecraftConstants.SERVER_INFO_HANDLER_KEY, (session, info) -> {
System.out.println("Version: " + info.getVersionInfo().getVersionName()
+ ", " + info.getVersionInfo().getProtocolVersion());
System.out.println("Player Count: " + info.getPlayerInfo().getOnlinePlayers()
@ -163,7 +163,7 @@ public class MinecraftProtocolTest {
System.out.println("Icon: " + new String(Base64.getEncoder().encode(info.getIconPng()), StandardCharsets.UTF_8));
});
client.setFlag(MinecraftConstants.SERVER_PING_TIME_HANDLER_KEY, (ServerPingTimeHandler) (session, pingTime) ->
client.setFlag(MinecraftConstants.SERVER_PING_TIME_HANDLER_KEY, (session, pingTime) ->
System.out.println("Server ping took " + pingTime + "ms"));
client.connect();

View file

@ -47,33 +47,32 @@ public abstract class AbstractServer implements Server {
}
@Override
public boolean hasGlobalFlag(String key) {
return this.flags.containsKey(key);
public boolean hasGlobalFlag(Flag<?> flag) {
return this.flags.containsKey(flag.key());
}
@Override
public <T> T getGlobalFlag(String key) {
return this.getGlobalFlag(key, null);
public <T> T getGlobalFlag(Flag<T> flag) {
return this.getGlobalFlag(flag, null);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getGlobalFlag(String key, T def) {
Object value = this.flags.get(key);
public <T> T getGlobalFlag(Flag<T> flag, T def) {
Object value = this.flags.get(flag.key());
if(value == null) {
return def;
}
try {
return (T) value;
return flag.cast(value);
} catch(ClassCastException e) {
throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName());
throw new IllegalStateException("Tried to get flag \"" + flag.key() + "\" as the wrong type. Actual type: " + value.getClass().getName());
}
}
@Override
public void setGlobalFlag(String key, Object value) {
this.flags.put(key, value);
public <T> void setGlobalFlag(Flag<T> flag, T value) {
this.flags.put(flag.key(), value);
}
@Override

View file

@ -1,5 +1,7 @@
package org.geysermc.mcprotocollib.network;
import java.net.InetSocketAddress;
/**
* Built-in PacketLib session flags.
*/
@ -7,16 +9,16 @@ public class BuiltinFlags {
/**
* When set to true, enables printing internal debug messages.
*/
public static final String PRINT_DEBUG = "print-packetlib-debug";
public static final Flag<Boolean> PRINT_DEBUG = new Flag<>("print-packetlib-debug", Boolean.class);
public static final String ENABLE_CLIENT_PROXY_PROTOCOL = "enable-client-proxy-protocol";
public static final Flag<Boolean> ENABLE_CLIENT_PROXY_PROTOCOL = new Flag<>("enable-client-proxy-protocol", Boolean.class);
public static final String CLIENT_PROXIED_ADDRESS = "client-proxied-address";
public static final Flag<InetSocketAddress> CLIENT_PROXIED_ADDRESS = new Flag<>("client-proxied-address", InetSocketAddress.class);
/**
* When set to false, an SRV record resolve is not attempted.
*/
public static final String ATTEMPT_SRV_RESOLVE = "attempt-srv-resolve";
public static final Flag<Boolean> ATTEMPT_SRV_RESOLVE = new Flag<>("attempt-srv-resolve", Boolean.class);
private BuiltinFlags() {
}

View file

@ -0,0 +1,17 @@
package org.geysermc.mcprotocollib.network;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public final class Flag<T> {
private final String key;
private final Class<T> type;
public T cast(Object obj) {
return type.cast(obj);
}
public String key() {
return key;
}
}

View file

@ -49,41 +49,42 @@ public interface Server {
/**
* Checks whether this server has a flag set.
*
* @param key Key of the flag to check for.
* @param flag Flag to check for.
* @return Whether this server has a flag set.
*/
boolean hasGlobalFlag(String key);
boolean hasGlobalFlag(Flag<?> flag);
/**
* Gets the value of the given flag as an instance of the given type.
*
* @param <T> Type of the flag.
* @param key Key of the flag.
* @param flag Flag to check for.
* @return Value of the flag.
* @throws IllegalStateException If the flag's value isn't of the required type.
*/
<T> T getGlobalFlag(String key);
<T> T getGlobalFlag(Flag<T> flag);
/**
* Gets the value of the given flag as an instance of the given type.
* If the flag is not set, the specified default value will be returned.
*
* @param <T> Type of the flag.
* @param key Key of the flag.
* @param flag Flag to check for.
* @param def Default value of the flag.
* @return Value of the flag.
* @throws IllegalStateException If the flag's value isn't of the required type.
*/
<T> T getGlobalFlag(String key, T def);
<T> T getGlobalFlag(Flag<T> flag, T def);
/**
* Sets the value of a flag. The flag will be used in sessions if a session does
* not contain a value for the flag.
*
* @param key Key of the flag.
* @param <T> Type of the flag.
* @param flag Flag to check for.
* @param value Value to set the flag to.
*/
void setGlobalFlag(String key, Object value);
<T> void setGlobalFlag(Flag<T> flag, T value);
/**
* Gets the listeners listening on this session.

View file

@ -92,10 +92,10 @@ public interface Session {
* Checks whether this session has a flag set. If this session belongs to a server,
* the server's flags will also be checked.
*
* @param key Key of the flag to check for.
* @param flag Flag to check for.
* @return Whether this session has a flag set.
*/
boolean hasFlag(String key);
boolean hasFlag(Flag<?> flag);
/**
* Gets the value of the given flag as an instance of the given type. If this
@ -103,11 +103,11 @@ public interface Session {
* as well.
*
* @param <T> Type of the flag.
* @param key Key of the flag.
* @param flag Flag to check for.
* @return Value of the flag.
* @throws IllegalStateException If the flag's value isn't of the required type.
*/
<T> T getFlag(String key);
<T> T getFlag(Flag<T> flag);
/**
* Gets the value of the given flag as an instance of the given type. If this
@ -115,21 +115,22 @@ public interface Session {
* as well. If the flag is not set, the specified default value will be returned.
*
* @param <T> Type of the flag.
* @param key Key of the flag.
* @param flag Flag to check for.
* @param def Default value of the flag.
* @return Value of the flag.
* @throws IllegalStateException If the flag's value isn't of the required type.
*/
<T> T getFlag(String key, T def);
<T> T getFlag(Flag<T> flag, T def);
/**
* Sets the value of a flag. This does not change a server's flags if this session
* belongs to a server.
*
* @param key Key of the flag.
* @param <T> Type of the flag.
* @param flag Flag to check for.
* @param value Value to set the flag to.
*/
void setFlag(String key, Object value);
<T> void setFlag(Flag<T> flag, T value);
/**
* Sets the values for a collection of flags.

View file

@ -3,6 +3,7 @@ package org.geysermc.mcprotocollib.network.tcp;
import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper;
import org.geysermc.mcprotocollib.network.packet.PacketProtocol;
import io.netty.channel.ChannelHandlerContext;
import org.geysermc.mcprotocollib.network.Flag;
import java.util.HashMap;
import java.util.Map;
@ -31,22 +32,22 @@ public class TcpServerSession extends TcpSession {
}
@Override
public boolean hasFlag(String key) {
if(super.hasFlag(key)) {
public boolean hasFlag(Flag<?> flag) {
if(super.hasFlag(flag)) {
return true;
}
return this.server.hasGlobalFlag(key);
return this.server.hasGlobalFlag(flag);
}
@Override
public <T> T getFlag(String key, T def) {
T ret = super.getFlag(key, null);
public <T> T getFlag(Flag<T> flag, T def) {
T ret = super.getFlag(flag, null);
if(ret != null) {
return ret;
}
return this.server.getGlobalFlag(key, def);
return this.server.getGlobalFlag(flag, def);
}
@Override

View file

@ -18,6 +18,7 @@ import io.netty.handler.timeout.WriteTimeoutHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.mcprotocollib.network.Flag;
import java.net.ConnectException;
import java.net.SocketAddress;
@ -104,33 +105,32 @@ public abstract class TcpSession extends SimpleChannelInboundHandler<Packet> imp
}
@Override
public boolean hasFlag(String key) {
return this.flags.containsKey(key);
public boolean hasFlag(Flag<?> flag) {
return this.flags.containsKey(flag.key());
}
@Override
public <T> T getFlag(String key) {
return this.getFlag(key, null);
public <T> T getFlag(Flag<T> flag) {
return this.getFlag(flag, null);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getFlag(String key, T def) {
Object value = this.flags.get(key);
public <T> T getFlag(Flag<T> flag, T def) {
Object value = this.flags.get(flag.key());
if (value == null) {
return def;
}
try {
return (T) value;
return flag.cast(value);
} catch (ClassCastException e) {
throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName());
throw new IllegalStateException("Tried to get flag \"" + flag.key() + "\" as the wrong type. Actual type: " + value.getClass().getName());
}
}
@Override
public void setFlag(String key, Object value) {
this.flags.put(key, value);
public <T> void setFlag(Flag<T> flag, T value) {
this.flags.put(flag.key(), value);
}
@Override

View file

@ -2,8 +2,12 @@ package org.geysermc.mcprotocollib.protocol;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.auth.service.SessionService;
import org.geysermc.mcprotocollib.network.Flag;
import org.geysermc.mcprotocollib.network.packet.DefaultPacketHeader;
import org.geysermc.mcprotocollib.network.packet.PacketHeader;
import org.geysermc.mcprotocollib.protocol.data.status.handler.ServerInfoBuilder;
import org.geysermc.mcprotocollib.protocol.data.status.handler.ServerInfoHandler;
import org.geysermc.mcprotocollib.protocol.data.status.handler.ServerPingTimeHandler;
/**
* Class containing various constants for Minecraft sessions.
@ -14,12 +18,12 @@ public final class MinecraftConstants {
/**
* Session flag where the user {@link GameProfile} is stored.
*/
public static final String PROFILE_KEY = "profile";
public static final Flag<GameProfile> PROFILE_KEY = new Flag<>("profile", GameProfile.class);
/**
* Session flag for providing a custom {@link SessionService} instance.
*/
public static final String SESSION_SERVICE_KEY = "session-service";
public static final Flag<SessionService> SESSION_SERVICE_KEY = new Flag<>("session-service", SessionService.class);
/**
* Session flag for whether to automatically send a keep alive packet. <br>
@ -27,31 +31,31 @@ public final class MinecraftConstants {
* For clients: determines if MCProtocolLib automatically sends back a packet
* when the server sends their keep alive packet.
*/
public static final String AUTOMATIC_KEEP_ALIVE_MANAGEMENT = "manage-keep-alive";
public static final Flag<Boolean> AUTOMATIC_KEEP_ALIVE_MANAGEMENT = new Flag<>("manage-keep-alive", Boolean.class);
// Client Key Constants
/**
* Session flag where the user's access token is stored. Client only.
*/
public static final String ACCESS_TOKEN_KEY = "access-token";
public static final Flag<String> ACCESS_TOKEN_KEY = new Flag<>("access-token", String.class);
/**
* Session flag for providing a custom server info response handler. Client only.
*/
public static final String SERVER_INFO_HANDLER_KEY = "server-info-handler";
public static final Flag<ServerInfoHandler> SERVER_INFO_HANDLER_KEY = new Flag<>("server-info-handler", ServerInfoHandler.class);
/**
* Session flag for providing a custom ping time response handler. Client only.
*/
public static final String SERVER_PING_TIME_HANDLER_KEY = "server-ping-time-handler";
public static final Flag<ServerPingTimeHandler> SERVER_PING_TIME_HANDLER_KEY = new Flag<>("server-ping-time-handler", ServerPingTimeHandler.class);
// Server Key Constants
/**
* Session flag for determining whether to verify users. Server only.
*/
public static final String VERIFY_USERS_KEY = "verify-users";
public static final Flag<Boolean> VERIFY_USERS_KEY = new Flag<>("verify-users", Boolean.class);
/**
* Session flag for determining whether to accept transferred connections. Server only.
@ -61,22 +65,22 @@ public final class MinecraftConstants {
/**
* Session flag for providing a custom server info response builder. Server only.
*/
public static final String SERVER_INFO_BUILDER_KEY = "info-builder";
public static final Flag<ServerInfoBuilder> SERVER_INFO_BUILDER_KEY = new Flag<>("info-builder", ServerInfoBuilder.class);
/**
* Session flag for providing a custom server login handler. Server only.
*/
public static final String SERVER_LOGIN_HANDLER_KEY = "login-handler";
public static final Flag<ServerLoginHandler> SERVER_LOGIN_HANDLER_KEY = new Flag<>("login-handler", ServerLoginHandler.class);
/**
* Session flag for storing the current ping time. Server only.
*/
public static final String PING_KEY = "ping";
public static final Flag<Long> PING_KEY = new Flag<>("ping", Long.class);
/**
* Session flag for determining the packet compression threshold. Server only.
*/
public static final String SERVER_COMPRESSION_THRESHOLD = "compression-threshold";
public static final Flag<Integer> SERVER_COMPRESSION_THRESHOLD = new Flag<>("compression-threshold", Integer.class);
/**
* The packet header used by Minecraft.

View file

@ -89,7 +89,7 @@ public class ServerListener extends SessionAdapter {
@Override
public void connected(ConnectedEvent event) {
event.getSession().setFlag(MinecraftConstants.PING_KEY, 0);
event.getSession().setFlag(MinecraftConstants.PING_KEY, 0L);
}
@Override