mirror of
https://github.com/Minestom/Minestom.git
synced 2025-02-06 07:21:32 +01:00
Added optional Mojang auth and UUIDs support (MojangAuth.init()), added support for skin layers, and made everywhere have max lighting.
This commit is contained in:
parent
ac758e4acb
commit
42276efc49
@ -11,6 +11,7 @@ sourceCompatibility = 1.11
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url 'https://jitpack.io' }
|
||||
maven { url 'https://libraries.minecraft.net' }
|
||||
}
|
||||
|
||||
|
||||
@ -47,5 +48,9 @@ dependencies {
|
||||
api 'net.kyori:text-serializer-legacy:3.0.3'
|
||||
api 'net.kyori:text-serializer-gson:3.0.3'
|
||||
api 'net.kyori:text-serializer-plain:3.0.3'
|
||||
api 'com.mojang:authlib:1.5.21'
|
||||
api 'net.sf.jopt-simple:jopt-simple:5.0.4'
|
||||
api 'org.projectlombok:lombok:1.18.12'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.12'
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,16 @@
|
||||
package net.minestom.server;
|
||||
|
||||
import com.mojang.authlib.AuthenticationService;
|
||||
import com.mojang.authlib.minecraft.MinecraftSessionService;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.minestom.server.benchmark.BenchmarkManager;
|
||||
import net.minestom.server.command.CommandManager;
|
||||
import net.minestom.server.data.DataManager;
|
||||
import net.minestom.server.entity.EntityManager;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.extras.mojangAuth.MojangCrypt;
|
||||
import net.minestom.server.gamedata.loottables.LootTableManager;
|
||||
import net.minestom.server.instance.InstanceManager;
|
||||
import net.minestom.server.instance.block.BlockManager;
|
||||
@ -26,8 +32,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Proxy;
|
||||
import java.security.KeyPair;
|
||||
|
||||
public class MinecraftServer {
|
||||
@Getter
|
||||
private final static Logger LOGGER = LoggerFactory.getLogger(MinecraftServer.class);
|
||||
|
||||
public static final int PROTOCOL_VERSION = 578;
|
||||
@ -66,6 +75,11 @@ public class MinecraftServer {
|
||||
public static final int TICK_MS = MS_TO_SEC / 20;
|
||||
public static final int TICK_PER_SECOND = MS_TO_SEC / TICK_MS;
|
||||
|
||||
//Extras
|
||||
@Getter
|
||||
@Setter
|
||||
private static boolean fixLighting = true;
|
||||
|
||||
// Networking
|
||||
private static PacketProcessor packetProcessor;
|
||||
private static PacketListenerManager packetListenerManager;
|
||||
@ -92,6 +106,14 @@ public class MinecraftServer {
|
||||
private static Difficulty difficulty = Difficulty.NORMAL;
|
||||
private static LootTableManager lootTableManager;
|
||||
|
||||
//Mojang Auth
|
||||
@Getter
|
||||
private static KeyPair keyPair = MojangCrypt.generateKeyPair();
|
||||
@Getter
|
||||
private static AuthenticationService authService = new YggdrasilAuthenticationService(Proxy.NO_PROXY, "");
|
||||
@Getter
|
||||
private static MinecraftSessionService sessionService = authService.createMinecraftSessionService();
|
||||
|
||||
public static MinecraftServer init() {
|
||||
connectionManager = new ConnectionManager();
|
||||
packetProcessor = new PacketProcessor();
|
||||
|
@ -21,4 +21,17 @@ public class ByteArrayData extends DataType<byte[]> {
|
||||
}
|
||||
return array;
|
||||
}
|
||||
public static void encodeByteArray(PacketWriter packetWriter, byte[] value) {
|
||||
packetWriter.writeVarInt(value.length);
|
||||
for (byte val : value) {
|
||||
packetWriter.writeByte(val);
|
||||
}
|
||||
}
|
||||
public static byte[] decodeByteArray(PacketReader packetReader) {
|
||||
byte[] array = new byte[packetReader.readVarInt()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = packetReader.readByte();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
19
src/main/java/net/minestom/server/extras/MojangAuth.java
Normal file
19
src/main/java/net/minestom/server/extras/MojangAuth.java
Normal file
@ -0,0 +1,19 @@
|
||||
package net.minestom.server.extras;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
|
||||
public class MojangAuth {
|
||||
|
||||
@Getter
|
||||
private static boolean usingMojangAuth = false;
|
||||
|
||||
public static void init() {
|
||||
if (MinecraftServer.getNettyServer().getAddress() == null) {
|
||||
System.out.println("Using Mojang Auth");
|
||||
usingMojangAuth = true;
|
||||
} else {
|
||||
throw new IllegalStateException("The server has already been started");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package net.minestom.server.extras.mojangAuth;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.ShortBufferException;
|
||||
|
||||
public class CipherBase {
|
||||
private final Cipher cipher;
|
||||
private byte[] inTempArray = new byte[0];
|
||||
private byte[] outTempArray = new byte[0];
|
||||
|
||||
protected CipherBase(Cipher cipher) {
|
||||
this.cipher = cipher;
|
||||
}
|
||||
|
||||
private byte[] bufToByte(ByteBuf buffer) {
|
||||
int remainingBytes = buffer.readableBytes();
|
||||
|
||||
// Need to resize temp array
|
||||
if (inTempArray.length < remainingBytes) {
|
||||
inTempArray = new byte[remainingBytes];
|
||||
}
|
||||
|
||||
buffer.readBytes(inTempArray, 0, remainingBytes);
|
||||
return inTempArray;
|
||||
}
|
||||
|
||||
protected ByteBuf decrypt(ChannelHandlerContext channelHandlerContext, ByteBuf byteBufIn) throws ShortBufferException {
|
||||
int remainingBytes = byteBufIn.readableBytes();
|
||||
byte[] bytes = bufToByte(byteBufIn);
|
||||
|
||||
ByteBuf outputBuffer = channelHandlerContext.alloc().heapBuffer(cipher.getOutputSize(remainingBytes));
|
||||
outputBuffer.writerIndex(cipher.update(bytes, 0, remainingBytes, outputBuffer.array(), outputBuffer.arrayOffset()));
|
||||
|
||||
return outputBuffer;
|
||||
}
|
||||
|
||||
protected void encrypt(ByteBuf byteBufIn, ByteBuf byteBufOut) throws ShortBufferException {
|
||||
int remainingBytes = byteBufIn.readableBytes();
|
||||
byte[] bytes = bufToByte(byteBufIn);
|
||||
int newSize = cipher.getOutputSize(remainingBytes);
|
||||
|
||||
// Need to resize temp array
|
||||
if (outTempArray.length < newSize) {
|
||||
outTempArray = new byte[newSize];
|
||||
}
|
||||
|
||||
byteBufOut.writeBytes(outTempArray, 0, cipher.update(bytes, 0, remainingBytes, outTempArray));
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package net.minestom.server.extras.mojangAuth;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.util.List;
|
||||
|
||||
public class Decrypter extends MessageToMessageDecoder<ByteBuf> {
|
||||
private final CipherBase cipher;
|
||||
|
||||
public Decrypter(Cipher cipher) {
|
||||
this.cipher = new CipherBase(cipher);
|
||||
}
|
||||
|
||||
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
|
||||
list.add(this.cipher.decrypt(channelHandlerContext, byteBuf));
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package net.minestom.server.extras.mojangAuth;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
public class Encrypter extends MessageToByteEncoder<ByteBuf> {
|
||||
private final CipherBase cipher;
|
||||
|
||||
public Encrypter(Cipher cipher) {
|
||||
this.cipher = new CipherBase(cipher);
|
||||
}
|
||||
|
||||
protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBufIn, ByteBuf byteBufOut) throws Exception {
|
||||
this.cipher.encrypt(byteBufIn, byteBufOut);
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package net.minestom.server.extras.mojangAuth;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.*;
|
||||
|
||||
public class MojangCrypt {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
public static KeyPair generateKeyPair() {
|
||||
try {
|
||||
KeyPairGenerator keyPairGenerator1 = KeyPairGenerator.getInstance("RSA");
|
||||
keyPairGenerator1.initialize(1024);
|
||||
return keyPairGenerator1.generateKeyPair();
|
||||
} catch (NoSuchAlgorithmException var1) {
|
||||
var1.printStackTrace();
|
||||
LOGGER.error("Key pair generation failed!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] digestData(String string, PublicKey publicKey, SecretKey secretKey) {
|
||||
try {
|
||||
return digestData("SHA-1", string.getBytes("ISO_8859_1"), secretKey.getEncoded(), publicKey.getEncoded());
|
||||
} catch (UnsupportedEncodingException var4) {
|
||||
var4.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] digestData(String string, byte[]... arr) {
|
||||
try {
|
||||
MessageDigest messageDigest3 = MessageDigest.getInstance(string);
|
||||
|
||||
for(byte[] arr7 : arr) {
|
||||
messageDigest3.update(arr7);
|
||||
}
|
||||
|
||||
return messageDigest3.digest();
|
||||
} catch (NoSuchAlgorithmException var7) {
|
||||
var7.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static SecretKey decryptByteToSecretKey(PrivateKey privateKey, byte[] arr) {
|
||||
return new SecretKeySpec(decryptUsingKey(privateKey, arr), "AES");
|
||||
}
|
||||
|
||||
public static byte[] decryptUsingKey(Key key, byte[] arr) {
|
||||
return cipherData(2, key, arr);
|
||||
}
|
||||
|
||||
private static byte[] cipherData(int integer, Key key, byte[] arr) {
|
||||
try {
|
||||
return setupCipher(integer, key.getAlgorithm(), key).doFinal(arr);
|
||||
} catch (IllegalBlockSizeException var4) {
|
||||
var4.printStackTrace();
|
||||
} catch (BadPaddingException var5) {
|
||||
var5.printStackTrace();
|
||||
}
|
||||
|
||||
LOGGER.error("Cipher data failed!");
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Cipher setupCipher(int integer, String string, Key key) {
|
||||
try {
|
||||
Cipher cipher4 = Cipher.getInstance(string);
|
||||
cipher4.init(integer, key);
|
||||
return cipher4;
|
||||
} catch (InvalidKeyException var4) {
|
||||
var4.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException var5) {
|
||||
var5.printStackTrace();
|
||||
} catch (NoSuchPaddingException var6) {
|
||||
var6.printStackTrace();
|
||||
}
|
||||
|
||||
LOGGER.error("Cipher creation failed!");
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Cipher getCipher(int integer, Key key) {
|
||||
try {
|
||||
Cipher cipher3 = Cipher.getInstance("AES/CFB8/NoPadding");
|
||||
cipher3.init(integer, key, new IvParameterSpec(key.getEncoded()));
|
||||
return cipher3;
|
||||
} catch (GeneralSecurityException var3) {
|
||||
throw new RuntimeException(var3);
|
||||
}
|
||||
}
|
||||
}
|
@ -12,9 +12,7 @@ import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.CustomBlock;
|
||||
import net.minestom.server.instance.block.rule.BlockPlacementRule;
|
||||
import net.minestom.server.network.PacketWriterUtils;
|
||||
import net.minestom.server.network.packet.server.play.BlockChangePacket;
|
||||
import net.minestom.server.network.packet.server.play.ParticlePacket;
|
||||
import net.minestom.server.network.packet.server.play.UnloadChunkPacket;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.particle.Particle;
|
||||
import net.minestom.server.particle.ParticleCreator;
|
||||
import net.minestom.server.storage.StorageFolder;
|
||||
@ -448,6 +446,29 @@ public class InstanceContainer extends Instance {
|
||||
} else {
|
||||
sendChunkUpdate(player, chunk);
|
||||
}
|
||||
|
||||
if (MinecraftServer.isFixLighting()) {
|
||||
UpdateLightPacket updateLightPacket = new UpdateLightPacket();
|
||||
updateLightPacket.chunkX = chunk.getChunkX();
|
||||
updateLightPacket.chunkZ = chunk.getChunkZ();
|
||||
updateLightPacket.skyLightMask = 0x3FFF0;
|
||||
updateLightPacket.blockLightMask = 0x3F;
|
||||
updateLightPacket.emptySkyLightMask = 0x0F;
|
||||
updateLightPacket.emptyBlockLightMask = 0x3FFC0;
|
||||
byte[] bytes = new byte[2048];
|
||||
Arrays.fill(bytes, (byte) 0xFF);
|
||||
List<byte[]> temp = new ArrayList<>();
|
||||
List<byte[]> temp2 = new ArrayList<>();
|
||||
for (int i = 0; i < 14; ++i) {
|
||||
temp.add(bytes);
|
||||
}
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
temp2.add(bytes);
|
||||
}
|
||||
updateLightPacket.skyLight = temp;
|
||||
updateLightPacket.blockLight = temp2;
|
||||
PacketWriterUtils.writeAndSend(player, updateLightPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -39,8 +39,8 @@ public class NettyServer {
|
||||
|
||||
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||
protected void initChannel(SocketChannel socketChannel) {
|
||||
socketChannel.pipeline().addLast(new NettyDecoder());
|
||||
socketChannel.pipeline().addLast(new ClientChannel(packetProcessor));
|
||||
socketChannel.pipeline().addLast("decoder", new NettyDecoder());
|
||||
socketChannel.pipeline().addLast("encoder", new ClientChannel(packetProcessor));
|
||||
}
|
||||
});
|
||||
ChannelFuture channelFuture = serverBootstrap.bind().sync();
|
||||
|
@ -1,11 +1,13 @@
|
||||
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.LoginStartPacket;
|
||||
|
||||
public class ClientLoginPacketsHandler extends ClientPacketsHandler {
|
||||
|
||||
public ClientLoginPacketsHandler() {
|
||||
register(0, LoginStartPacket::new);
|
||||
register(1, EncryptionResponsePacket::new);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,68 @@
|
||||
package net.minestom.server.network.packet.client.login;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
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.ConnectionManager;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
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 javax.crypto.SecretKey;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class EncryptionResponsePacket implements ClientPreplayPacket {
|
||||
|
||||
private final static String THREAD_NAME = "Mojang Auth Thread";
|
||||
private static AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0);
|
||||
private byte[] sharedSecret;
|
||||
private byte[] verifyToken;
|
||||
|
||||
@Override
|
||||
public void process(PlayerConnection connection, ConnectionManager connectionManager) {
|
||||
new Thread(THREAD_NAME + " #" + UNIQUE_THREAD_ID.incrementAndGet()) {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
if (!Arrays.equals(connection.getNonce(), getNonce())) {
|
||||
System.out.println(connection.getLoginUsername() + " tried to login with an invalid nonce!");
|
||||
return;
|
||||
}
|
||||
if (!connection.getLoginUsername().isEmpty()) {
|
||||
String string3 = new BigInteger(MojangCrypt.digestData("", MinecraftServer.getKeyPair().getPublic(), getSecretKey())).toString(16);
|
||||
GameProfile gameProfile = MinecraftServer.getSessionService().hasJoinedServer(new GameProfile(null, connection.getLoginUsername()), string3);
|
||||
((NettyPlayerConnection) connection).setEncryptionKey(getSecretKey());
|
||||
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);
|
||||
connectionManager.createPlayer(gameProfile.getId(), gameProfile.getName(), connection);
|
||||
}
|
||||
} catch (AuthenticationUnavailableException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
sharedSecret = ByteArrayData.decodeByteArray(reader);
|
||||
verifyToken = ByteArrayData.decodeByteArray(reader);
|
||||
}
|
||||
|
||||
public SecretKey getSecretKey() {
|
||||
return MojangCrypt.decryptByteToSecretKey(MinecraftServer.getKeyPair().getPrivate(), sharedSecret);
|
||||
}
|
||||
|
||||
public byte[] getNonce() {
|
||||
return MinecraftServer.getKeyPair().getPrivate() == null ? this.verifyToken : MojangCrypt.decryptUsingKey(MinecraftServer.getKeyPair().getPrivate(), this.verifyToken);
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
package net.minestom.server.network.packet.client.login;
|
||||
|
||||
import net.minestom.server.extras.MojangAuth;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
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.LoginSuccessPacket;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
|
||||
@ -15,15 +17,21 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
||||
|
||||
@Override
|
||||
public void process(PlayerConnection connection, ConnectionManager connectionManager) {
|
||||
// TODO send encryption request OR directly login success
|
||||
if (MojangAuth.isUsingMojangAuth()) {
|
||||
connection.setConnectionState(ConnectionState.LOGIN);
|
||||
|
||||
UUID playerUuid = connectionManager.getPlayerConnectionUuid(connection);
|
||||
connection.setLoginUsername(username);
|
||||
EncryptionRequestPacket encryptionRequestPacket = new EncryptionRequestPacket(connection);
|
||||
connection.sendPacket(encryptionRequestPacket);
|
||||
} else {
|
||||
UUID playerUuid = connectionManager.getPlayerConnectionUuid(connection);
|
||||
|
||||
LoginSuccessPacket successPacket = new LoginSuccessPacket(playerUuid, username);
|
||||
connection.sendPacket(successPacket);
|
||||
LoginSuccessPacket successPacket = new LoginSuccessPacket(playerUuid, username);
|
||||
connection.sendPacket(successPacket);
|
||||
|
||||
connection.setConnectionState(ConnectionState.PLAY);
|
||||
connectionManager.createPlayer(playerUuid, username, connection);
|
||||
connection.setConnectionState(ConnectionState.PLAY);
|
||||
connectionManager.createPlayer(playerUuid, username, connection);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,32 @@
|
||||
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.PacketWriter;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class EncryptionRequestPacket implements ServerPacket {
|
||||
|
||||
private byte[] nonce = new byte[4];
|
||||
|
||||
public EncryptionRequestPacket(PlayerConnection connection) {
|
||||
ThreadLocalRandom.current().nextBytes(nonce);
|
||||
connection.setNonce(nonce);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketWriter writer) {
|
||||
writer.writeSizedString("");
|
||||
byte[] publicKey = MinecraftServer.getKeyPair().getPublic().getEncoded();
|
||||
ByteArrayData.encodeByteArray(writer, publicKey);
|
||||
ByteArrayData.encodeByteArray(writer, nonce);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return 0x01;
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ public class LoginSuccessPacket implements ServerPacket {
|
||||
|
||||
@Override
|
||||
public void write(PacketWriter writer) {
|
||||
writer.writeSizedString(uuid.toString()); // TODO mojang auth
|
||||
writer.writeSizedString(uuid.toString());
|
||||
writer.writeSizedString(username);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,8 @@ import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UpdateLightPacket implements ServerPacket {
|
||||
|
||||
public int chunkX;
|
||||
@ -15,8 +17,8 @@ public class UpdateLightPacket implements ServerPacket {
|
||||
public int emptySkyLightMask;
|
||||
public int emptyBlockLightMask;
|
||||
|
||||
public byte[] skyLight;
|
||||
public byte[] blockLight;
|
||||
public List<byte[]> skyLight;
|
||||
public List<byte[]> blockLight;
|
||||
|
||||
@Override
|
||||
public void write(PacketWriter writer) {
|
||||
@ -29,10 +31,17 @@ public class UpdateLightPacket implements ServerPacket {
|
||||
writer.writeVarInt(emptySkyLightMask);
|
||||
writer.writeVarInt(emptyBlockLightMask);
|
||||
|
||||
writer.writeVarInt(2048); // Always 2048 length
|
||||
writer.writeBytes(skyLight);
|
||||
writer.writeVarInt(2048); // Always 2048 length
|
||||
writer.writeBytes(blockLight);
|
||||
//writer.writeVarInt(skyLight.size());
|
||||
for (byte[] bytes : skyLight) {
|
||||
writer.writeVarInt(2048); // Always 2048 length
|
||||
writer.writeBytes(bytes);
|
||||
}
|
||||
|
||||
//writer.writeVarInt(blockLight.size());
|
||||
for (byte[] bytes : blockLight) {
|
||||
writer.writeVarInt(2048); // Always 2048 length
|
||||
writer.writeBytes(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,9 +2,14 @@ package net.minestom.server.network.player;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import lombok.Getter;
|
||||
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.packet.server.ServerPacket;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
@ -13,49 +18,72 @@ import java.net.SocketAddress;
|
||||
*/
|
||||
public class NettyPlayerConnection extends PlayerConnection {
|
||||
|
||||
private ChannelHandlerContext channel;
|
||||
private ChannelHandlerContext channel;
|
||||
@Getter
|
||||
private boolean encrypted = false;
|
||||
|
||||
public NettyPlayerConnection(ChannelHandlerContext channel) {
|
||||
super();
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(ByteBuf buffer) {
|
||||
buffer.retain();
|
||||
getChannel().writeAndFlush(buffer);
|
||||
}
|
||||
public NettyPlayerConnection(ChannelHandlerContext channel) {
|
||||
super();
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writePacket(ByteBuf buffer) {
|
||||
buffer.retain();
|
||||
getChannel().write(buffer);
|
||||
}
|
||||
public void setEncryptionKey(SecretKey secretKey) {
|
||||
this.encrypted = true;
|
||||
getChannel().pipeline().addBefore("decoder", "decrypt", new Decrypter(MojangCrypt.getCipher(2, secretKey)));
|
||||
getChannel().pipeline().addBefore("encoder", "encrypt", new Encrypter(MojangCrypt.getCipher(1, secretKey)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(ServerPacket serverPacket) {
|
||||
ByteBuf buffer = PacketUtils.writePacket(serverPacket);
|
||||
sendPacket(buffer);
|
||||
buffer.release();
|
||||
}
|
||||
@Override
|
||||
public void sendPacket(ByteBuf buffer) {
|
||||
if (encrypted) {
|
||||
buffer = buffer.copy();
|
||||
buffer.retain();
|
||||
getChannel().writeAndFlush(buffer);
|
||||
buffer.release();
|
||||
} else {
|
||||
buffer.retain();
|
||||
getChannel().writeAndFlush(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
getChannel().flush();
|
||||
}
|
||||
@Override
|
||||
public void writePacket(ByteBuf buffer) {
|
||||
if (encrypted) {
|
||||
buffer = buffer.copy();
|
||||
buffer.retain();
|
||||
getChannel().write(buffer);
|
||||
buffer.release();
|
||||
} else {
|
||||
buffer.retain();
|
||||
getChannel().write(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketAddress getRemoteAddress() {
|
||||
return getChannel().channel().remoteAddress();
|
||||
}
|
||||
@Override
|
||||
public void sendPacket(ServerPacket serverPacket) {
|
||||
ByteBuf buffer = PacketUtils.writePacket(serverPacket);
|
||||
sendPacket(buffer);
|
||||
buffer.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
getChannel().close();
|
||||
}
|
||||
@Override
|
||||
public void flush() {
|
||||
getChannel().flush();
|
||||
}
|
||||
|
||||
public ChannelHandlerContext getChannel() {
|
||||
return channel;
|
||||
}
|
||||
@Override
|
||||
public SocketAddress getRemoteAddress() {
|
||||
return getChannel().channel().remoteAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
getChannel().close();
|
||||
}
|
||||
|
||||
public ChannelHandlerContext getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package net.minestom.server.network.player;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
@ -14,6 +16,10 @@ import java.net.SocketAddress;
|
||||
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user