Support for velocity modern forwarding

This commit is contained in:
themode 2020-11-09 23:48:34 +01:00
parent 247a328a09
commit 7db94f3a65
26 changed files with 404 additions and 83 deletions

View File

@ -54,6 +54,7 @@ import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.Difficulty;
import net.minestom.server.world.DimensionTypeManager;
import net.minestom.server.world.biomes.BiomeManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -227,15 +228,18 @@ public class MinecraftServer {
*
* @return the server brand name
*/
@NotNull
public static String getBrandName() {
return brandName;
}
/**
* Changes the server brand name, update the name to all connected players.
* Changes the server brand name and send the change to all connected players.
*
* @param brandName the server brand name
* @throws NullPointerException if {@code brandName} is null
*/
@NotNull
public static void setBrandName(String brandName) {
Check.notNull(brandName, "The brand name cannot be null");
MinecraftServer.brandName = brandName;
@ -267,6 +271,7 @@ public class MinecraftServer {
*
* @return the server difficulty
*/
@NotNull
public static Difficulty getDifficulty() {
return difficulty;
}
@ -276,7 +281,9 @@ public class MinecraftServer {
*
* @param difficulty the new server difficulty
*/
public static void setDifficulty(Difficulty difficulty) {
@NotNull
public static void setDifficulty(@NotNull Difficulty difficulty) {
Check.notNull(difficulty, "The server difficulty cannot be null.");
MinecraftServer.difficulty = difficulty;
// The difficulty packet
@ -603,7 +610,7 @@ public class MinecraftServer {
* @param responseDataConsumer the response data consumer, can be null
* @throws IllegalStateException if called before {@link #init()} or if the server is already running
*/
public void start(String address, int port, ResponseDataConsumer responseDataConsumer) {
public void start(@NotNull String address, int port, @Nullable ResponseDataConsumer responseDataConsumer) {
Check.stateCondition(!initialized, "#start can only be called after #init");
Check.stateCondition(started, "The server is already started");
@ -632,7 +639,7 @@ public class MinecraftServer {
* @param port the server port
* @see #start(String, int, ResponseDataConsumer)
*/
public void start(String address, int port) {
public void start(@NotNull String address, int port) {
start(address, port, null);
}

View File

@ -15,7 +15,7 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class AdvancementManager {
// root identifier TO its advancement tab
// root identifier = its advancement tab
private final Map<String, AdvancementTab> advancementTabMap = new ConcurrentHashMap<>();
/**

View File

@ -3,6 +3,8 @@ package net.minestom.server.advancements;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents an {@link Advancement} which is the root of an {@link AdvancementTab}.
@ -12,18 +14,18 @@ import net.minestom.server.item.Material;
*/
public class AdvancementRoot extends Advancement {
public AdvancementRoot(ColoredText title, ColoredText description,
ItemStack icon, FrameType frameType,
public AdvancementRoot(@NotNull ColoredText title, @NotNull ColoredText description,
@NotNull ItemStack icon, @NotNull FrameType frameType,
float x, float y,
String background) {
@Nullable String background) {
super(title, description, icon, frameType, x, y);
setBackground(background);
}
public AdvancementRoot(ColoredText title, ColoredText description,
Material icon, FrameType frameType,
public AdvancementRoot(@NotNull ColoredText title, @NotNull ColoredText description,
@NotNull Material icon, FrameType frameType,
float x, float y,
String background) {
@Nullable String background) {
super(title, description, icon, frameType, x, y);
setBackground(background);
}

View File

@ -34,7 +34,6 @@ import net.minestom.server.network.PlayerProvider;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.play.ClientChatMessagePacket;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.login.JoinGamePacket;
import net.minestom.server.network.packet.server.play.*;
import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection;

View File

@ -0,0 +1,78 @@
package net.minestom.server.extras.velocity;
import net.minestom.server.utils.binary.BinaryReader;
import org.jetbrains.annotations.NotNull;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class VelocityProxy {
public static final String PLAYER_INFO_CHANNEL = "velocity:player_info";
private static boolean enabled;
private static byte[] secret;
/**
* Enables velocity modern forwarding.
*
* @param secret the forwarding secret,
* be sure to do not hardcode it in your code but to retrieve it from a file or anywhere else safe
*/
public static void enable(@NotNull String secret) {
VelocityProxy.enabled = true;
VelocityProxy.secret = secret.getBytes();
}
/**
* Gets if velocity modern forwarding is enabled.
*
* @return true if velocity modern forwarding is enabled
*/
public static boolean isEnabled() {
return enabled;
}
public static boolean checkIntegrity(@NotNull BinaryReader reader) {
if (!enabled) {
return false;
}
final byte[] signature = reader.readBytes(32);
final byte[] data = reader.getRemainingBytes();
try {
final Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret, "HmacSHA256"));
final byte[] mySignature = mac.doFinal(data);
if (!MessageDigest.isEqual(signature, mySignature)) {
return false;
}
} catch (final InvalidKeyException | NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
/*int version = buf.readVarInt();
if (version != SUPPORTED_FORWARDING_VERSION) {
throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted " + SUPPORTED_FORWARDING_VERSION);
}*/
return true;
}
private static void readProperties(final BinaryReader reader) {
final int properties = reader.readVarInt();
for (int i1 = 0; i1 < properties; i1++) {
final String name = reader.readSizedString();
final String value = reader.readSizedString();
final String signature = reader.readBoolean() ? reader.readSizedString() : null;
System.out.println("test: " + name + " " + value + " " + signature);
}
}
}

View File

@ -5,6 +5,7 @@ import net.minestom.server.entity.Player;
import net.minestom.server.entity.fakeplayer.FakePlayer;
import net.minestom.server.listener.manager.PacketConsumer;
import net.minestom.server.network.packet.client.login.LoginStartPacket;
import net.minestom.server.network.packet.server.login.LoginSuccessPacket;
import net.minestom.server.network.packet.server.play.ChatMessagePacket;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.callback.validator.PlayerValidator;
@ -269,4 +270,19 @@ public final class ConnectionManager {
this.players.remove(player);
this.connectionPlayerMap.remove(connection);
}
/**
* Sends a {@link LoginSuccessPacket} and change the connection state to {@link ConnectionState#PLAY}.
*
* @param connection the player connection
* @param uuid the uuid of the player
* @param username the username of the player
*/
public void startPlayState(@NotNull PlayerConnection connection, @NotNull UUID uuid, @NotNull String username) {
LoginSuccessPacket loginSuccessPacket = new LoginSuccessPacket(uuid, username);
connection.sendPacket(loginSuccessPacket);
connection.setConnectionState(ConnectionState.PLAY);
createPlayer(uuid, username, connection);
}
}

View File

@ -61,6 +61,7 @@ public class ClientChannel extends SimpleChannelInboundHandler<InboundPacket> {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
log.info(cause.getMessage());
cause.printStackTrace();
ctx.close();
}
}

View File

@ -1,6 +1,7 @@
package net.minestom.server.network.packet.client.handler;
import net.minestom.server.network.packet.client.login.EncryptionResponsePacket;
import net.minestom.server.network.packet.client.login.LoginPluginResponsePacket;
import net.minestom.server.network.packet.client.login.LoginStartPacket;
public class ClientLoginPacketsHandler extends ClientPacketsHandler {
@ -8,6 +9,7 @@ public class ClientLoginPacketsHandler extends ClientPacketsHandler {
public ClientLoginPacketsHandler() {
register(0, LoginStartPacket::new);
register(1, EncryptionResponsePacket::new);
register(2, LoginPluginResponsePacket::new);
}
}

View File

@ -5,7 +5,7 @@ import net.minestom.server.chat.ChatColor;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.packet.client.ClientPreplayPacket;
import net.minestom.server.network.packet.server.login.LoginDisconnect;
import net.minestom.server.network.packet.server.login.LoginDisconnectPacket;
import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryReader;
@ -47,7 +47,7 @@ public class HandshakePacket implements ClientPreplayPacket {
}
} else {
// Incorrect client version
connection.sendPacket(new LoginDisconnect(INVALID_VERSION_TEXT.toString()));
connection.sendPacket(new LoginDisconnectPacket(INVALID_VERSION_TEXT.toString()));
connection.disconnect();
}
break;

View File

@ -5,9 +5,7 @@ import com.mojang.authlib.exceptions.AuthenticationUnavailableException;
import net.minestom.server.MinecraftServer;
import net.minestom.server.data.type.array.ByteArrayData;
import net.minestom.server.extras.mojangAuth.MojangCrypt;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.packet.client.ClientPreplayPacket;
import net.minestom.server.network.packet.server.login.LoginSuccessPacket;
import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryReader;
@ -32,17 +30,18 @@ public class EncryptionResponsePacket implements ClientPreplayPacket {
if (!(connection instanceof NettyPlayerConnection)) {
return;
}
final NettyPlayerConnection nettyConnection = (NettyPlayerConnection) connection;
new Thread(THREAD_NAME + " #" + UNIQUE_THREAD_ID.incrementAndGet()) {
public void run() {
try {
if (!Arrays.equals(connection.getNonce(), getNonce())) {
MinecraftServer.getLOGGER().error(connection.getLoginUsername() + " tried to login with an invalid nonce!");
final String loginUsername = nettyConnection.getLoginUsername();
if (!Arrays.equals(nettyConnection.getNonce(), getNonce())) {
MinecraftServer.getLOGGER().error(loginUsername + " tried to login with an invalid nonce!");
return;
}
if (!connection.getLoginUsername().isEmpty()) {
final NettyPlayerConnection nettyConnection = (NettyPlayerConnection) connection;
if (!loginUsername.isEmpty()) {
final byte[] digestedData = MojangCrypt.digestData("", MinecraftServer.getKeyPair().getPublic(), getSecretKey());
@ -54,7 +53,7 @@ public class EncryptionResponsePacket implements ClientPreplayPacket {
}
final String string3 = new BigInteger(digestedData).toString(16);
final GameProfile gameProfile = MinecraftServer.getSessionService().hasJoinedServer(new GameProfile(null, connection.getLoginUsername()), string3);
final GameProfile gameProfile = MinecraftServer.getSessionService().hasJoinedServer(new GameProfile(null, loginUsername), string3);
nettyConnection.setEncryptionKey(getSecretKey());
final int threshold = MinecraftServer.getCompressionThreshold();
@ -62,11 +61,8 @@ public class EncryptionResponsePacket implements ClientPreplayPacket {
nettyConnection.enableCompression(threshold);
}
LoginSuccessPacket loginSuccessPacket = new LoginSuccessPacket(gameProfile.getId(), gameProfile.getName());
connection.sendPacket(loginSuccessPacket);
MinecraftServer.getLOGGER().info("UUID of player {} is {}", connection.getLoginUsername(), gameProfile.getId());
connection.setConnectionState(ConnectionState.PLAY);
CONNECTION_MANAGER.createPlayer(gameProfile.getId(), gameProfile.getName(), connection);
MinecraftServer.getLOGGER().info("UUID of player {} is {}", loginUsername, gameProfile.getId());
CONNECTION_MANAGER.startPlayState(connection, gameProfile.getId(), gameProfile.getName());
}
} catch (AuthenticationUnavailableException e) {
e.printStackTrace();

View File

@ -0,0 +1,69 @@
package net.minestom.server.network.packet.client.login;
import net.minestom.server.MinecraftServer;
import net.minestom.server.chat.ChatColor;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.extras.velocity.VelocityProxy;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.packet.client.ClientPreplayPacket;
import net.minestom.server.network.packet.server.login.LoginDisconnectPacket;
import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryReader;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class LoginPluginResponsePacket implements ClientPreplayPacket {
private final static ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager();
public static final ColoredText INVALID_PROXY_RESPONSE = ColoredText.of(ChatColor.RED, "Invalid proxy response!");
public int messageId;
public boolean successful;
public byte[] data;
@Override
public void process(@NotNull PlayerConnection connection) {
// Proxy support
if (connection instanceof NettyPlayerConnection) {
final NettyPlayerConnection nettyPlayerConnection = (NettyPlayerConnection) connection;
final String channel = nettyPlayerConnection.getPluginRequestChannel(messageId);
if (channel != null) {
boolean success = false;
// Velocity
if (VelocityProxy.isEnabled() && channel.equals(VelocityProxy.PLAYER_INFO_CHANNEL)) {
if (data != null) {
BinaryReader reader = new BinaryReader(data);
success = VelocityProxy.checkIntegrity(reader);
}
}
if (success) {
// Proxy usage always mean that the server is in offline mode
final String username = nettyPlayerConnection.getLoginUsername();
final UUID playerUuid = CONNECTION_MANAGER.getPlayerConnectionUuid(connection, username);
CONNECTION_MANAGER.startPlayState(connection, playerUuid, username);
} else {
LoginDisconnectPacket disconnectPacket = new LoginDisconnectPacket(INVALID_PROXY_RESPONSE);
nettyPlayerConnection.sendPacket(disconnectPacket);
}
}
}
}
@Override
public void read(@NotNull BinaryReader reader) {
this.messageId = reader.readVarInt();
this.successful = reader.readBoolean();
if (successful) {
this.data = reader.getRemainingBytes();
}
}
}

View File

@ -4,39 +4,74 @@ import net.minestom.server.MinecraftServer;
import net.minestom.server.chat.ChatColor;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.extras.MojangAuth;
import net.minestom.server.extras.velocity.VelocityProxy;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.packet.client.ClientPreplayPacket;
import net.minestom.server.network.packet.server.login.EncryptionRequestPacket;
import net.minestom.server.network.packet.server.login.LoginDisconnect;
import net.minestom.server.network.packet.server.login.LoginSuccessPacket;
import net.minestom.server.network.packet.server.login.LoginDisconnectPacket;
import net.minestom.server.network.packet.server.login.LoginPluginRequestPacket;
import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryReader;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
public class LoginStartPacket implements ClientPreplayPacket {
private static final String ALREADY_CONNECTED_JSON =
ColoredText.of(ChatColor.RED, "You are already on this server").toString();
private static final ColoredText ALREADY_CONNECTED_JSON = ColoredText.of(ChatColor.RED, "You are already on this server");
public String username;
@Override
public void process(@NotNull PlayerConnection connection) {
if (MojangAuth.isUsingMojangAuth()) {
// Cache the login username
if (connection instanceof NettyPlayerConnection) {
((NettyPlayerConnection) connection).UNSAFE_setLoginUsername(username);
}
// Proxy support (only for netty clients)
if (connection instanceof NettyPlayerConnection) {
final NettyPlayerConnection nettyPlayerConnection = (NettyPlayerConnection) connection;
{
// Velocity support
if (VelocityProxy.isEnabled()) {
final int messageId = ThreadLocalRandom.current().nextInt();
final String channel = VelocityProxy.PLAYER_INFO_CHANNEL;
nettyPlayerConnection.addPluginRequestEntry(messageId, channel);
LoginPluginRequestPacket loginPluginRequestPacket = new LoginPluginRequestPacket();
loginPluginRequestPacket.messageId = messageId;
loginPluginRequestPacket.channel = channel;
loginPluginRequestPacket.data = null;
connection.sendPacket(loginPluginRequestPacket);
return;
}
}
}
if (MojangAuth.isUsingMojangAuth() && connection instanceof NettyPlayerConnection) {
// Mojang auth
if (CONNECTION_MANAGER.getPlayer(username) != null) {
connection.sendPacket(new LoginDisconnect(ALREADY_CONNECTED_JSON));
connection.sendPacket(new LoginDisconnectPacket(ALREADY_CONNECTED_JSON));
connection.disconnect();
return;
}
connection.setConnectionState(ConnectionState.LOGIN);
connection.setLoginUsername(username);
EncryptionRequestPacket encryptionRequestPacket = new EncryptionRequestPacket(connection);
connection.sendPacket(encryptionRequestPacket);
final NettyPlayerConnection nettyPlayerConnection = (NettyPlayerConnection) connection;
nettyPlayerConnection.setConnectionState(ConnectionState.LOGIN);
EncryptionRequestPacket encryptionRequestPacket = new EncryptionRequestPacket(nettyPlayerConnection);
nettyPlayerConnection.sendPacket(encryptionRequestPacket);
} else {
// Offline
final UUID playerUuid = CONNECTION_MANAGER.getPlayerConnectionUuid(connection, username);
final int threshold = MinecraftServer.getCompressionThreshold();
@ -45,11 +80,7 @@ public class LoginStartPacket implements ClientPreplayPacket {
((NettyPlayerConnection) connection).enableCompression(threshold);
}
LoginSuccessPacket successPacket = new LoginSuccessPacket(playerUuid, username);
connection.sendPacket(successPacket);
connection.setConnectionState(ConnectionState.PLAY);
CONNECTION_MANAGER.createPlayer(playerUuid, username, connection);
CONNECTION_MANAGER.startPlayState(connection, playerUuid, username);
}
}

View File

@ -2,6 +2,12 @@ package net.minestom.server.network.packet.server;
public class ServerPacketIdentifier {
public static final int LOGIN_DISCONNECT = 0x00;
public static final int LOGIN_ENCRYPTION_REQUEST = 0x01;
public static final int LOGIN_SUCCESS = 0x02;
public static final int LOGIN_SET_COMPRESSION = 0x03;
public static final int LOGIN_PLUGIN_REQUEST = 0x04;
public static final int SPAWN_ENTITY = 0x00;
public static final int SPAWN_EXPERIENCE_ORB = 0x01;
public static final int SPAWN_LIVING_ENTITY = 0x02;

View File

@ -3,7 +3,8 @@ package net.minestom.server.network.packet.server.login;
import net.minestom.server.MinecraftServer;
import net.minestom.server.data.type.array.ByteArrayData;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -14,7 +15,7 @@ public class EncryptionRequestPacket implements ServerPacket {
public byte[] publicKey;
public byte[] nonce = new byte[4];
public EncryptionRequestPacket(PlayerConnection connection) {
public EncryptionRequestPacket(NettyPlayerConnection connection) {
ThreadLocalRandom.current().nextBytes(nonce);
connection.setNonce(nonce);
}
@ -29,6 +30,6 @@ public class EncryptionRequestPacket implements ServerPacket {
@Override
public int getId() {
return 0x01;
return ServerPacketIdentifier.LOGIN_ENCRYPTION_REQUEST;
}
}

View File

@ -1,25 +0,0 @@
package net.minestom.server.network.packet.server.login;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class LoginDisconnect implements ServerPacket {
private String kickMessage;
public LoginDisconnect(String kickMessage) {
this.kickMessage = kickMessage;
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeSizedString(kickMessage);
}
@Override
public int getId() {
return 0x00;
}
}

View File

@ -0,0 +1,31 @@
package net.minestom.server.network.packet.server.login;
import net.minestom.server.chat.JsonMessage;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class LoginDisconnectPacket implements ServerPacket {
private String kickMessage; // JSON text
public LoginDisconnectPacket(@NotNull String kickMessage) {
this.kickMessage = kickMessage;
}
public LoginDisconnectPacket(@NotNull JsonMessage jsonKickMessage) {
this(jsonKickMessage.toString());
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeSizedString(kickMessage);
}
@Override
public int getId() {
return ServerPacketIdentifier.LOGIN_DISCONNECT;
}
}

View File

@ -0,0 +1,27 @@
package net.minestom.server.network.packet.server.login;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class LoginPluginRequestPacket implements ServerPacket {
public int messageId;
public String channel;
public byte[] data;
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(messageId);
writer.writeSizedString(channel);
if (data != null && data.length > 0) {
writer.writeBytes(data);
}
}
@Override
public int getId() {
return ServerPacketIdentifier.LOGIN_PLUGIN_REQUEST;
}
}

View File

@ -1,6 +1,7 @@
package net.minestom.server.network.packet.server.login;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -24,6 +25,6 @@ public class LoginSuccessPacket implements ServerPacket {
@Override
public int getId() {
return 0x02;
return ServerPacketIdentifier.LOGIN_SUCCESS;
}
}

View File

@ -1,6 +1,7 @@
package net.minestom.server.network.packet.server.login;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -19,6 +20,6 @@ public class SetCompressionPacket implements ServerPacket {
@Override
public int getId() {
return 0x03;
return ServerPacketIdentifier.LOGIN_SET_COMPRESSION;
}
}

View File

@ -1,4 +1,4 @@
package net.minestom.server.network.packet.server.login;
package net.minestom.server.network.packet.server.play;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.GameMode;

View File

@ -29,6 +29,7 @@ public class PluginMessagePacket implements ServerPacket {
*
* @return the current brand name packet
*/
@NotNull
public static PluginMessagePacket getBrandPacket() {
PluginMessagePacket brandMessage = new PluginMessagePacket();
brandMessage.channel = "minecraft:brand";

View File

@ -4,9 +4,11 @@ import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.socket.SocketChannel;
import lombok.Getter;
import lombok.Setter;
import net.minestom.server.extras.mojangAuth.Decrypter;
import net.minestom.server.extras.mojangAuth.Encrypter;
import net.minestom.server.extras.mojangAuth.MojangCrypt;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.netty.codec.PacketCompressor;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.login.SetCompressionPacket;
@ -16,6 +18,8 @@ import org.jetbrains.annotations.Nullable;
import javax.crypto.SecretKey;
import java.net.SocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Represents a networking connection with Netty.
@ -30,9 +34,19 @@ public class NettyPlayerConnection extends PlayerConnection {
@Getter
private boolean compressed = false;
//Could be null. Only used for Mojang Auth
@Getter
@Setter
private byte[] nonce = new byte[4];
private String loginUsername;
private String serverAddress;
private int serverPort;
// Used for the login plugin request packet, to retrive the channel from a message id,
// cleared once the player enters the play state
private Map<Integer, String> pluginRequestMap = new ConcurrentHashMap<>();
public NettyPlayerConnection(@NotNull SocketChannel channel) {
super();
this.channel = channel;
@ -114,6 +128,27 @@ public class NettyPlayerConnection extends PlayerConnection {
return channel;
}
/**
* Retrieves the username received from the client during connection.
* <p>
* This value has not been checked and could be anything.
*
* @return the username given by the client, unchecked
*/
@Nullable
public String getLoginUsername() {
return loginUsername;
}
/**
* Sets the internal login username field
*
* @param loginUsername the new login username field
*/
public void UNSAFE_setLoginUsername(@NotNull String loginUsername) {
this.loginUsername = loginUsername;
}
/**
* Gets the server address that the client used to connect.
* <p>
@ -137,6 +172,45 @@ public class NettyPlayerConnection extends PlayerConnection {
return serverPort;
}
/**
* Adds an entry to the plugin request map.
* <p>
* Only working if {@link #getConnectionState()} is {@link net.minestom.server.network.ConnectionState#LOGIN}.
*
* @param messageId the message id
* @param channel the packet channel
* @throws IllegalStateException if a messageId with the value {@code messageId} already exists for this connection
*/
public void addPluginRequestEntry(int messageId, @NotNull String channel) {
if (!getConnectionState().equals(ConnectionState.LOGIN)) {
return;
}
Check.stateCondition(pluginRequestMap.containsKey(messageId), "You cannot have two messageId with the same value");
this.pluginRequestMap.put(messageId, channel);
}
/**
* Gets a request channel from a message id, previously cached using {@link #addPluginRequestEntry(int, String)}.
* <p>
* Be aware that the internal map is cleared once the player enters the play state.
*
* @param messageId the message id
* @return the channel linked to the message id, null if not found
*/
@Nullable
public String getPluginRequestChannel(int messageId) {
return pluginRequestMap.get(messageId);
}
@Override
public void setConnectionState(@NotNull ConnectionState connectionState) {
super.setConnectionState(connectionState);
// Clear the plugin request map (since it is not used anymore)
if (connectionState.equals(ConnectionState.PLAY)) {
this.pluginRequestMap.clear();
}
}
/**
* Used in {@link net.minestom.server.network.packet.client.handshake.HandshakePacket} to change the internal fields.
*

View File

@ -2,14 +2,13 @@ package net.minestom.server.network.player;
import io.netty.buffer.ByteBuf;
import lombok.Getter;
import lombok.Setter;
import net.minestom.server.MinecraftServer;
import net.minestom.server.chat.ChatColor;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.entity.Player;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.login.LoginDisconnect;
import net.minestom.server.network.packet.server.login.LoginDisconnectPacket;
import net.minestom.server.network.packet.server.play.DisconnectPacket;
import org.jetbrains.annotations.NotNull;
@ -23,14 +22,6 @@ import java.util.concurrent.atomic.AtomicInteger;
public abstract class PlayerConnection {
private Player player;
//Could be null. Only used for Mojang Auth
@Getter
@Setter
private String loginUsername;
//Could be null. Only used for Mojang Auth
@Getter
@Setter
private byte[] nonce = new byte[4];
private ConnectionState connectionState;
private boolean online;
@ -64,7 +55,7 @@ public abstract class PlayerConnection {
if (count > MinecraftServer.getRateLimit()) {
// Sent too many packets
if (connectionState == ConnectionState.LOGIN) {
sendPacket(new LoginDisconnect("Too Many Packets"));
sendPacket(new LoginDisconnectPacket("Too Many Packets"));
} else {
DisconnectPacket disconnectPacket = new DisconnectPacket();
disconnectPacket.message = rateLimitKickMessage;

View File

@ -186,6 +186,8 @@ public class BinaryWriter extends OutputStream {
/**
* Writes a byte array.
* <p>
* WARNING: it doesn't write the length of {@code bytes}.
*
* @param bytes the byte array to write
*/

View File

@ -3,6 +3,7 @@ package demo;
import demo.blocks.BurningTorchBlock;
import demo.blocks.StoneBlock;
import demo.blocks.UpdatableBlockDemo;
import demo.commands.GamemodeCommand;
import demo.commands.TestCommand;
import net.minestom.server.MinecraftServer;
import net.minestom.server.command.CommandManager;
@ -28,6 +29,7 @@ public class Main {
CommandManager commandManager = MinecraftServer.getCommandManager();
commandManager.register(new TestCommand());
commandManager.register(new GamemodeCommand());
/*commandManager.register(new EntitySelectorCommand());
commandManager.register(new HealthCommand());
commandManager.register(new SimpleCommand());
@ -48,6 +50,8 @@ public class Main {
PlayerInit.init();
//VelocityProxy.enable("rBeJJ79W4MVU");
//MojangAuth.init();
minecraftServer.start("0.0.0.0", 25565, PlayerInit.getResponseDataConsumer());

View File

@ -5,6 +5,8 @@ import demo.generator.NoiseTestGenerator;
import net.minestom.server.MinecraftServer;
import net.minestom.server.benchmark.BenchmarkManager;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.data.Data;
import net.minestom.server.data.NbtDataImpl;
import net.minestom.server.entity.*;
import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.entity.type.monster.EntityZombie;
@ -172,7 +174,11 @@ public class PlayerInit {
}
ItemStack itemStack = new ItemStack(Material.DIAMOND_PICKAXE, (byte) 64);
Data data = new NbtDataImpl();
data.set("test", 51);
itemStack.setData(data);
player.getInventory().addItemStack(itemStack);
System.out.println("test " + data.get("test"));
//player.getInventory().addItemStack(new ItemStack(Material.STONE, (byte)64));
});