basic (very wip) mojang api, protocol encryption, login

This commit is contained in:
bixilon 2020-06-03 00:56:07 +02:00
parent 34270f564f
commit c044abbdc3
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
17 changed files with 552 additions and 36 deletions

View File

@ -0,0 +1,6 @@
package de.bixilon.minosoft;
public class Config {
public static String username = ""; // mojang email
public static String password = "";
}

View File

@ -7,6 +7,6 @@ public class Minosoft {
public static void main(String[] args) { public static void main(String[] args) {
Log.info("Starting..."); Log.info("Starting...");
Connection c = new Connection("127.0.0.1", 25565); Connection c = new Connection("127.0.0.1", 25565);
c.ping(); c.connect();
} }
} }

View File

@ -3,7 +3,7 @@ package de.bixilon.minosoft.logging;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
public class Log { public class Log {
static LogLevel level = LogLevel.VERBOSE; static LogLevel level = LogLevel.PROTOCOL;
static SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); static SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
public static void log(LogLevel l, String message) { public static void log(LogLevel l, String message) {

View File

@ -0,0 +1,73 @@
package de.bixilon.minosoft.objects;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.util.HTTP;
import de.bixilon.minosoft.util.Util;
import org.json.JSONObject;
import java.net.http.HttpResponse;
import java.util.UUID;
public class Account {
String username;
String password;
String playerName;
String token;
UUID uuid;
public Account(String username, String password) {
this.username = username;
this.password = password;
}
public void login() {
JSONObject payload = new JSONObject();
payload.put("agent", new JSONObject().put("name", "Minecraft").put("version", 1));
payload.put("username", username);
payload.put("password", password);
// ToDo not in main thread
HttpResponse<String> response = HTTP.postJson("https://authserver.mojang.com/authenticate", payload);
if (response == null || response.statusCode() != 200) {
assert response != null;
Log.info(String.format("[Mojang API] Login failed with username=%s (%s)", username, response.statusCode()));
return;
}
Log.info(String.format("[Mojang API] Login successful with username=%s", username));
// login good
JSONObject raw = new JSONObject(response.body());
token = raw.getString("accessToken");
uuid = Util.formatUUID(raw.getJSONObject("selectedProfile").getString("id"));
playerName = raw.getJSONObject("selectedProfile").getString("name");
}
public void join(String serverId) {
JSONObject payload = new JSONObject();
payload.put("accessToken", token);
payload.put("selectedProfile", getUUID().toString().replace("-", ""));
payload.put("serverId", serverId);
// ToDo not in main thread
HttpResponse<String> response = HTTP.postJson("https://sessionserver.mojang.com/session/minecraft/join", payload);
if (response == null || response.statusCode() != 204) {
assert response != null;
Log.info("[Mojang API] Login to join server!");
return;
}
Log.info("[Mojang API] Joined server successfully");
}
public UUID getUUID() {
return this.uuid;
}
public String getPlayerName() {
return this.playerName;
}
}

View File

@ -0,0 +1,24 @@
package de.bixilon.minosoft.objects;
import java.util.UUID;
public class Player {
Account acc;
public Player(Account acc) {
this.acc = acc;
acc.login();
}
public String getPlayerName() {
return acc.getPlayerName();
}
public UUID getPlayerUUID() {
return acc.getUUID();
}
public Account getAccount() {
return this.acc;
}
}

View File

@ -1,8 +1,13 @@
package de.bixilon.minosoft.protocol.network; package de.bixilon.minosoft.protocol.network;
import de.bixilon.minosoft.Config;
import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.objects.Account;
import de.bixilon.minosoft.objects.Player;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket; import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.packets.ServerboundPacket;
import de.bixilon.minosoft.protocol.packets.serverbound.handshaking.PacketHandshake; import de.bixilon.minosoft.protocol.packets.serverbound.handshaking.PacketHandshake;
import de.bixilon.minosoft.protocol.packets.serverbound.login.PacketLoginStart;
import de.bixilon.minosoft.protocol.packets.serverbound.status.PacketStatusPing; import de.bixilon.minosoft.protocol.packets.serverbound.status.PacketStatusPing;
import de.bixilon.minosoft.protocol.packets.serverbound.status.PacketStatusRequest; import de.bixilon.minosoft.protocol.packets.serverbound.status.PacketStatusRequest;
import de.bixilon.minosoft.protocol.protocol.ConnectionState; import de.bixilon.minosoft.protocol.protocol.ConnectionState;
@ -18,6 +23,7 @@ public class Connection {
private final Network network; private final Network network;
private final PacketHandler handler; private final PacketHandler handler;
private final ArrayList<ClientboundPacket> handlingQueue; private final ArrayList<ClientboundPacket> handlingQueue;
private Player player = new Player(new Account(Config.username, Config.password));
private ConnectionState state = ConnectionState.DISCONNECTED; private ConnectionState state = ConnectionState.DISCONNECTED;
private boolean onlyPing; private boolean onlyPing;
@ -88,6 +94,9 @@ public class Connection {
network.sendPacket(new PacketStatusRequest()); network.sendPacket(new PacketStatusRequest());
network.sendPacket(new PacketStatusPing(0)); network.sendPacket(new PacketStatusPing(0));
break; break;
case LOGIN:
network.sendPacket(new PacketLoginStart(player));
break;
} }
} }
@ -111,4 +120,12 @@ public class Connection {
public void disconnect() { public void disconnect() {
setConnectionState(ConnectionState.DISCONNECTING); setConnectionState(ConnectionState.DISCONNECTING);
} }
public Player getPlayer() {
return player;
}
public void sendPacket(ServerboundPacket p) {
network.sendPacket(p);
}
} }

View File

@ -3,11 +3,14 @@ package de.bixilon.minosoft.protocol.network;
import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket; import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.packets.ServerboundPacket; import de.bixilon.minosoft.protocol.packets.ServerboundPacket;
import de.bixilon.minosoft.protocol.protocol.ConnectionState; import de.bixilon.minosoft.protocol.packets.serverbound.login.PacketEncryptionResponse;
import de.bixilon.minosoft.protocol.protocol.InPacketBuffer; import de.bixilon.minosoft.protocol.protocol.*;
import de.bixilon.minosoft.protocol.protocol.Protocol;
import de.bixilon.minosoft.util.Util; import de.bixilon.minosoft.util.Util;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
@ -22,6 +25,9 @@ public class Network {
private final List<byte[]> binQueue; private final List<byte[]> binQueue;
private final List<byte[]> binQueueIn; private final List<byte[]> binQueueIn;
private Socket socket; private Socket socket;
private boolean encryptionEnabled = false;
private Cipher cipherEncrypt;
private Cipher cipherDecrypt;
public Network(Connection c) { public Network(Connection c) {
this.connection = c; this.connection = c;
@ -62,29 +68,37 @@ public class Network {
binQueue.remove(0); binQueue.remove(0);
} }
// everything sent for now, waiting for data if (dIn.available() == 0) {
// nothing to receive
while (dIn.available() > 0) { Util.sleep(1);
int numRead = 0; continue;
int len = 0; }
byte read; // everything sent for now, waiting for data
do { List<Byte> raw = new ArrayList<>();
read = dIn.readByte(); byte[] buffer = new byte[1];
int value = (read & 0b01111111); while (true) {
len |= (value << (7 * numRead)); if (raw.size() > ProtocolDefinition.PROTOCOL_PACKET_MAX_SIZE) {
raw = null;
numRead++; break;
if (numRead > 5) { }
throw new RuntimeException("VarInt is too big"); if (dIn.available() == 0) {
// packet end
break;
}
dIn.readFully(buffer, 0, 1);
raw.add(buffer[0]);
}
if (raw == null || raw.size() == 0) {
// data was tto long, ...
continue;
}
// convert to array
byte[] in = new byte[raw.size()];
for (int i = 0; i < raw.size(); i++) {
in[i] = raw.get(i);
} }
} while ((read & 0b10000000) != 0);
byte[] in = dIn.readNBytes(len);
// add to queue // add to queue
binQueueIn.add(in); binQueueIn.add(in);
}
Util.sleep(1); Util.sleep(1);
} }
@ -107,17 +121,52 @@ public class Network {
while (queue.size() > 0) { while (queue.size() > 0) {
ServerboundPacket p = queue.get(0); ServerboundPacket p = queue.get(0);
binQueue.add(p.write(connection.getVersion()).getOutBytes()); byte[] raw = p.write(connection.getVersion()).getOutBytes();
if (encryptionEnabled) {
// encrypt
byte[] encrypted;
try {
encrypted = cipherEncrypt.doFinal(raw);
} catch (IllegalBlockSizeException | BadPaddingException e) {
Log.fatal("Failed to encrypt!");
e.printStackTrace();
binQueue.remove(0);
continue;
}
binQueue.add(encrypted);
} else {
binQueue.add(raw);
}
queue.remove(0); queue.remove(0);
if (p instanceof PacketEncryptionResponse) {
// enable encryption
enableEncryption(((PacketEncryptionResponse) p).getSecretKey());
}
} }
while (binQueueIn.size() > 0) { while (binQueueIn.size() > 0) {
// read data // read data
InPacketBuffer inPacketBuffer = new InPacketBuffer(binQueueIn.get(0)); byte[] raw = binQueueIn.get(0);
InPacketBuffer inPacketBuffer;
if (encryptionEnabled) {
// decrypt
byte[] decrypted;
try {
decrypted = cipherDecrypt.doFinal(raw);
} catch (IllegalBlockSizeException | BadPaddingException e) {
Log.fatal("Failed to decrypt!");
e.printStackTrace();
binQueueIn.remove(0);
continue;
}
inPacketBuffer = new InPacketBuffer(decrypted);
} else {
inPacketBuffer = new InPacketBuffer(raw);
}
Class<? extends ClientboundPacket> clazz = Protocol.getPacketByPacket(connection.getVersion().getProtocol().getPacketByCommand(connection.getConnectionState(), inPacketBuffer.getCommand())); Class<? extends ClientboundPacket> clazz = Protocol.getPacketByPacket(connection.getVersion().getProtocol().getPacketByCommand(connection.getConnectionState(), inPacketBuffer.getCommand()));
if (clazz == null) { if (clazz == null) {
Log.warn("[IN] Unknown: " + inPacketBuffer.getCommand()); Log.warn("[IN] Unknown packet with command " + inPacketBuffer.getCommand());
binQueueIn.remove(0); binQueueIn.remove(0);
continue; continue;
} }
@ -143,6 +192,13 @@ public class Network {
public void sendPacket(ServerboundPacket p) { public void sendPacket(ServerboundPacket p) {
queue.add(p); queue.add(p);
}
public void enableEncryption(SecretKey secretKey) {
Log.debug("Enabling encryption...");
cipherEncrypt = CryptManager.createNetCipherInstance(Cipher.ENCRYPT_MODE, secretKey);
cipherDecrypt = CryptManager.createNetCipherInstance(Cipher.DECRYPT_MODE, secretKey);
encryptionEnabled = true;
Log.debug("Encryption enabled!");
} }
} }

View File

@ -0,0 +1,48 @@
package de.bixilon.minosoft.protocol.packets.clientbound.login;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.protocol.InPacketBuffer;
import de.bixilon.minosoft.protocol.protocol.PacketHandler;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
public class PacketEncryptionKeyRequest implements ClientboundPacket {
String serverId; //normally empty
byte[] publicKey;
byte[] verifyToken;
@Override
public void read(InPacketBuffer buffer, ProtocolVersion v) {
switch (v) {
case VERSION_1_7_10:
serverId = buffer.readString();
publicKey = buffer.readBytes(buffer.readShort()); // read length, then the bytes
verifyToken = buffer.readBytes(buffer.readShort()); // read length, then the bytes
break;
} // ToDo
log();
}
@Override
public void log() {
Log.protocol("Receiving encryption request packet");
}
@Override
public void handle(PacketHandler h) {
h.handle(this);
}
public byte[] getPublicKey() {
return publicKey;
}
public byte[] getVerifyToken() {
return verifyToken;
}
public String getServerId() {
return serverId;
}
}

View File

@ -0,0 +1,40 @@
package de.bixilon.minosoft.protocol.packets.clientbound.login;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.protocol.InPacketBuffer;
import de.bixilon.minosoft.protocol.protocol.PacketHandler;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
import java.util.UUID;
public class PacketLoginSuccess implements ClientboundPacket {
UUID uuid;
String username;
@Override
public void read(InPacketBuffer buffer, ProtocolVersion v) {
uuid = UUID.fromString(buffer.readString());
username = buffer.readString();
log();
}
@Override
public void log() {
Log.protocol("Receiving login success packet");
}
@Override
public void handle(PacketHandler h) {
h.handle(this);
}
public UUID getUUID() {
return uuid;
}
public String getUsername() {
return username;
}
}

View File

@ -0,0 +1,50 @@
package de.bixilon.minosoft.protocol.packets.serverbound.login;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ServerboundPacket;
import de.bixilon.minosoft.protocol.protocol.CryptManager;
import de.bixilon.minosoft.protocol.protocol.OutPacketBuffer;
import de.bixilon.minosoft.protocol.protocol.Packets;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
import javax.crypto.SecretKey;
import java.security.PublicKey;
public class PacketEncryptionResponse implements ServerboundPacket {
byte[] secret;
byte[] token;
SecretKey secretKey;
public PacketEncryptionResponse(SecretKey secret, byte[] token, PublicKey key) {
this.secretKey = secret;
this.secret = CryptManager.encryptData(key, secret.getEncoded());
this.token = CryptManager.encryptData(key, token);
}
public SecretKey getSecretKey() {
return secretKey;
}
@Override
public OutPacketBuffer write(ProtocolVersion v) {
log();
OutPacketBuffer buffer = new OutPacketBuffer(v.getPacketCommand(Packets.Serverbound.LOGIN_ENCRYPTION_RESPONSE));
switch (v) {
case VERSION_1_7_10:
buffer.writeShort((short) secret.length);
buffer.writeBytes(secret);
buffer.writeShort((short) token.length);
buffer.writeBytes(token);
}
//buffer.writeString(username);
return buffer;
}
@Override
public void log() {
Log.protocol("Sending encryption response");
}
}

View File

@ -0,0 +1,35 @@
package de.bixilon.minosoft.protocol.packets.serverbound.login;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.objects.Player;
import de.bixilon.minosoft.protocol.packets.ServerboundPacket;
import de.bixilon.minosoft.protocol.protocol.OutPacketBuffer;
import de.bixilon.minosoft.protocol.protocol.Packets;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
public class PacketLoginStart implements ServerboundPacket {
private final String username;
public PacketLoginStart(Player p) {
username = p.getPlayerName();
}
public PacketLoginStart(String username) {
this.username = username;
}
@Override
public OutPacketBuffer write(ProtocolVersion v) {
log();
// no version checking, is the same in all versions (1.7.x - 1.15.2)
OutPacketBuffer buffer = new OutPacketBuffer(v.getPacketCommand(Packets.Serverbound.LOGIN_LOGIN_START));
buffer.writeString(username);
return buffer;
}
@Override
public void log() {
Log.protocol(String.format("Sending login start (%s)", username));
}
}

View File

@ -0,0 +1,109 @@
package de.bixilon.minosoft.protocol.protocol;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
public class CryptManager {
// little thanks to https://skmedix.github.io/ForgeJavaDocs/javadoc/forge/1.7.10-10.13.4.1614/net/minecraft/util/CryptManager.html
public static SecretKey createNewSharedKey() {
try {
KeyGenerator key = KeyGenerator.getInstance("AES");
key.init(128);
return key.generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public static KeyPair createNewKeyPair() {
try {
KeyPairGenerator keyPair = KeyPairGenerator.getInstance("RSA");
keyPair.initialize(1024);
return keyPair.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public static byte[] getServerHash(String serverId, PublicKey publicKey, SecretKey secretKey) {
try {
return digestOperation(serverId.getBytes("ISO_8859_1"), secretKey.getEncoded(), publicKey.getEncoded());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
private static byte[] digestOperation(byte[]... bytes) {
try {
MessageDigest disgest = MessageDigest.getInstance("SHA-1");
for (byte[] b : bytes) {
disgest.update(b);
}
return disgest.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public static PublicKey decodePublicKey(byte[] key) {
try {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
}
return null;
}
public static SecretKey decryptSharedKey(PrivateKey key, byte[] data) {
return new SecretKeySpec(decryptData(key, data), "AES");
}
public static byte[] encryptData(Key key, byte[] data) {
return cipherOperation(1, key, data);
}
public static byte[] decryptData(Key key, byte[] data) {
return cipherOperation(2, key, data);
}
private static byte[] cipherOperation(int p_75885_0_, Key key, byte[] data) {
try {
return createTheCipherInstance(p_75885_0_, key.getAlgorithm(), key).doFinal(data);
} catch (IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
return null;
}
private static Cipher createTheCipherInstance(int p_75886_0_, String transformation, Key key) {
try {
Cipher cipher = Cipher.getInstance(transformation);
cipher.init(p_75886_0_, key);
return cipher;
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
}
return null;
}
public static Cipher createNetCipherInstance(int opMode, Key key) {
try {
Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding");
cipher.init(opMode, key, new IvParameterSpec(key.getEncoded()));
return cipher;
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,15 +1,13 @@
package de.bixilon.minosoft.protocol.protocol; package de.bixilon.minosoft.protocol.protocol;
import java.util.ArrayList;
import java.util.List;
public class InPacketBuffer extends InByteBuffer { public class InPacketBuffer extends InByteBuffer {
private final int command; private final int command;
private final int length; // not interested in yet
public InPacketBuffer(byte[] bytes) { public InPacketBuffer(byte[] bytes) {
super(bytes); super(bytes);
// ToDo: compression // ToDo: compression
length = readVarInt();
command = readVarInt(); command = readVarInt();
} }

View File

@ -2,8 +2,15 @@ package de.bixilon.minosoft.protocol.protocol;
import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.network.Connection; import de.bixilon.minosoft.protocol.network.Connection;
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketEncryptionKeyRequest;
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketLoginSuccess;
import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusPong; import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusPong;
import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusResponse; import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusResponse;
import de.bixilon.minosoft.protocol.packets.serverbound.login.PacketEncryptionResponse;
import javax.crypto.SecretKey;
import java.math.BigInteger;
import java.security.PublicKey;
public class PacketHandler { public class PacketHandler {
Connection connection; Connection connection;
@ -14,7 +21,6 @@ public class PacketHandler {
public void handle(PacketStatusResponse pkg) { public void handle(PacketStatusResponse pkg) {
Log.info(String.format("Status response received: %s/%s online. MotD: '%s'", pkg.getResponse().getPlayerOnline(), pkg.getResponse().getMaxPlayers(), pkg.getResponse().getMotd())); Log.info(String.format("Status response received: %s/%s online. MotD: '%s'", pkg.getResponse().getPlayerOnline(), pkg.getResponse().getMaxPlayers(), pkg.getResponse().getMotd()));
} }
public void handle(PacketStatusPong pkg) { public void handle(PacketStatusPong pkg) {
@ -22,7 +28,20 @@ public class PacketHandler {
if (connection.isOnlyPing()) { if (connection.isOnlyPing()) {
// pong arrived, closing connection // pong arrived, closing connection
connection.disconnect(); connection.disconnect();
}
}
public void handle(PacketEncryptionKeyRequest pkg) {
SecretKey secretKey = CryptManager.createNewSharedKey();
PublicKey publicKey = CryptManager.decodePublicKey(pkg.getPublicKey());
String serverHash = new BigInteger(CryptManager.getServerHash(pkg.getServerId(), publicKey, secretKey)).toString(16);
connection.getPlayer().getAccount().join(serverHash);
connection.sendPacket(new PacketEncryptionResponse(secretKey, pkg.getVerifyToken(), publicKey));
} }
public void handle(PacketLoginSuccess pkg) {
// now we are playing
connection.setConnectionState(ConnectionState.PLAY);
} }
} }

View File

@ -1,6 +1,8 @@
package de.bixilon.minosoft.protocol.protocol; package de.bixilon.minosoft.protocol.protocol;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket; import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketEncryptionKeyRequest;
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketLoginSuccess;
import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusPong; import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusPong;
import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusResponse; import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusResponse;
@ -26,5 +28,7 @@ public interface Protocol {
private static void initPacketClassMapping() { private static void initPacketClassMapping() {
packetClassMapping.put(Packets.Clientbound.STATUS_RESPONSE, PacketStatusResponse.class); packetClassMapping.put(Packets.Clientbound.STATUS_RESPONSE, PacketStatusResponse.class);
packetClassMapping.put(Packets.Clientbound.STATUS_PONG, PacketStatusPong.class); packetClassMapping.put(Packets.Clientbound.STATUS_PONG, PacketStatusPong.class);
packetClassMapping.put(Packets.Clientbound.LOGIN_ENCRYPTION_REQUEST, PacketEncryptionKeyRequest.class);
packetClassMapping.put(Packets.Clientbound.LOGIN_LOGIN_SUCCESS, PacketLoginSuccess.class);
} }
} }

View File

@ -0,0 +1,28 @@
package de.bixilon.minosoft.util;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class HTTP {
public static HttpResponse<String> postJson(String url, JSONObject json) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.POST(HttpRequest.BodyPublishers.ofString(json.toString()))
.header("Content-Type", "application/json")
.build();
try {
return client.send(request,
HttpResponse.BodyHandlers.ofString());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -1,12 +1,21 @@
package de.bixilon.minosoft.util; package de.bixilon.minosoft.util;
import java.util.UUID;
import java.util.regex.Pattern;
public class Util { public class Util {
private static final Pattern UUID_FIX = Pattern.compile("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})");
// thanks https://www.spigotmc.org/threads/free-code-easily-convert-between-trimmed-and-full-uuids.165615
public static void sleep(int ms) { public static void sleep(int ms) {
try { try {
Thread.sleep(ms); Thread.sleep(ms);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
}
public static UUID formatUUID(String uuid) {
return UUID.fromString(UUID_FIX.matcher(uuid.replace("-", "")).replaceAll("$1-$2-$3-$4-$5"));
} }
} }