mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 01:16:46 -04:00
auto load mappings after pong arrived (or version was specified), refactor networking a bit (no sleep anymore)
This commit is contained in:
parent
9c4b7cd991
commit
7f46603ef0
@ -18,6 +18,7 @@ import de.bixilon.minosoft.game.datatypes.objectLoader.versions.Versions;
|
||||
import de.bixilon.minosoft.gui.main.GUITools;
|
||||
import de.bixilon.minosoft.gui.main.Server;
|
||||
import de.bixilon.minosoft.gui.main.ServerListCell;
|
||||
import de.bixilon.minosoft.logging.Log;
|
||||
import javafx.application.Application;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
@ -41,6 +42,7 @@ public class Launcher extends Application {
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws IOException {
|
||||
Log.info("Starting launcher...");
|
||||
GUITools.versions.add(Versions.getLowestVersionSupported());
|
||||
for (Map.Entry<Integer, Version> version : Versions.getVersionMap().entrySet()) {
|
||||
GUITools.versions.add(version.getValue());
|
||||
@ -83,5 +85,6 @@ public class Launcher extends Application {
|
||||
primaryStage.show();
|
||||
primaryStage.setOnCloseRequest(windowEvent -> System.exit(0));
|
||||
|
||||
Log.info("Launcher started!");
|
||||
}
|
||||
}
|
@ -65,6 +65,7 @@ public class Minosoft {
|
||||
}
|
||||
Log.info(String.format("Loaded versions mapping in %dms", (System.currentTimeMillis() - mappingStartLoadingTime)));
|
||||
|
||||
Log.debug("Refreshing token...");
|
||||
checkClientToken();
|
||||
|
||||
accountList = config.getMojangAccounts();
|
||||
@ -82,6 +83,7 @@ public class Minosoft {
|
||||
} else {
|
||||
Log.mojang("Could not refresh session, you will not be able to join premium servers!");
|
||||
}
|
||||
Log.debug("Refreshed token!");
|
||||
|
||||
serverList = config.getServers();
|
||||
Launcher.main();
|
||||
|
@ -109,7 +109,6 @@ public class Configuration {
|
||||
String basePath = String.format("servers.%d.", server.getId());
|
||||
putString(basePath + "name", server.getName());
|
||||
putString(basePath + "address", server.getAddress());
|
||||
putString(basePath + "account", server.getAccount());
|
||||
putInt(basePath + "version", server.getDesiredVersion());
|
||||
if (server.getBase64Favicon() != null) {
|
||||
putString(basePath + "favicon", server.getBase64Favicon());
|
||||
@ -208,7 +207,7 @@ public class Configuration {
|
||||
if (entry.containsKey("favicon")) {
|
||||
favicon = (String) entry.get("favicon");
|
||||
}
|
||||
servers.add(new Server(Integer.parseInt(set.getKey()), (String) entry.get("name"), (String) entry.get("address"), (String) entry.get("account"), (int) entry.get("version"), favicon));
|
||||
servers.add(new Server(Integer.parseInt(set.getKey()), (String) entry.get("name"), (String) entry.get("address"), (int) entry.get("version"), favicon));
|
||||
}
|
||||
return servers;
|
||||
}
|
||||
|
@ -126,6 +126,10 @@ public class Versions {
|
||||
} else {
|
||||
version = versionMap.get(protocolId);
|
||||
}
|
||||
if (version.getMapping() != null && version.getMapping().isFullyLoaded()) {
|
||||
// already loaded
|
||||
return;
|
||||
}
|
||||
Log.verbose(String.format("Loading mappings for version %s...", version));
|
||||
long startTime = System.currentTimeMillis();
|
||||
for (Map.Entry<String, Mappings> mappingSet : mappingsHashMap.entrySet()) {
|
||||
|
@ -55,6 +55,7 @@ public class MainWindow implements Initializable {
|
||||
|
||||
TextField serverName = new TextField();
|
||||
serverName.setPromptText("Servername");
|
||||
serverName.setText("A Minosoft server");
|
||||
TextField serverAddress = new TextField();
|
||||
serverAddress.setPromptText("Server address");
|
||||
|
||||
@ -78,7 +79,7 @@ public class MainWindow implements Initializable {
|
||||
|
||||
dialog.setResultConverter(dialogButton -> {
|
||||
if (dialogButton == loginButtonType) {
|
||||
Server server = new Server(Minosoft.serverList.size() + 1, serverName.getText(), DNSUtil.correctHostName(serverAddress.getText()), null, GUITools.versionList.getSelectionModel().getSelectedItem().getProtocolVersion());
|
||||
Server server = new Server(Minosoft.serverList.size() + 1, serverName.getText(), DNSUtil.correctHostName(serverAddress.getText()), GUITools.versionList.getSelectionModel().getSelectedItem().getProtocolVersion());
|
||||
Minosoft.serverList.add(server);
|
||||
server.saveToConfig();
|
||||
ServerListCell.listView.getItems().add(server);
|
||||
|
@ -23,23 +23,20 @@ public class Server {
|
||||
final int id;
|
||||
String name;
|
||||
String address;
|
||||
String account;
|
||||
int desiredVersion;
|
||||
String favicon;
|
||||
|
||||
public Server(int id, String name, String address, String account, int desiredVersion) {
|
||||
public Server(int id, String name, String address, int desiredVersion) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
this.account = account;
|
||||
this.desiredVersion = desiredVersion;
|
||||
}
|
||||
|
||||
public Server(int id, String name, String address, String account, int desiredVersion, String favicon) {
|
||||
public Server(int id, String name, String address, int desiredVersion, String favicon) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
this.account = account;
|
||||
this.desiredVersion = desiredVersion;
|
||||
this.favicon = favicon;
|
||||
}
|
||||
@ -60,14 +57,6 @@ public class Server {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(String account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public int getDesiredVersion() {
|
||||
return desiredVersion;
|
||||
}
|
||||
|
@ -111,6 +111,7 @@ public class ServerListCell extends ListCell<Server> implements Initializable {
|
||||
players.setText("");
|
||||
version.setText("Offline");
|
||||
motd.setText("Could not connect to server!");
|
||||
motd.setTextFill(Color.RED);
|
||||
optionsConnect.setDisable(true);
|
||||
canConnect = false;
|
||||
return;
|
||||
@ -138,7 +139,7 @@ public class ServerListCell extends ListCell<Server> implements Initializable {
|
||||
icon.setImage(ping.getFavicon());
|
||||
}
|
||||
}));
|
||||
connection.resolve(ConnectionReasons.PING); // resolve dns address and ping
|
||||
connection.resolve(ConnectionReasons.PING, server.getDesiredVersion()); // resolve dns address and ping
|
||||
}
|
||||
setOnMouseClicked(click -> {
|
||||
if (click.getClickCount() == 2) {
|
||||
|
@ -71,19 +71,13 @@ public class Connection {
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an server ping to the server (player count, motd, ...)
|
||||
*/
|
||||
public void ping() {
|
||||
Log.info(String.format("Pinging server: %s", address));
|
||||
reason = ConnectionReasons.PING;
|
||||
network.connect(address);
|
||||
}
|
||||
|
||||
public void resolve(ConnectionReasons reason, int protocolId) {
|
||||
this.desiredVersionNumber = protocolId;
|
||||
|
||||
Thread resolveThread = new Thread(() -> {
|
||||
if (desiredVersionNumber != -1) {
|
||||
setVersion(Versions.getVersionById(desiredVersionNumber));
|
||||
}
|
||||
if (addresses == null) {
|
||||
try {
|
||||
addresses = DNSUtil.getServerAddresses(hostname);
|
||||
@ -113,10 +107,7 @@ public class Connection {
|
||||
network.connect(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to connect to the server and login
|
||||
*/
|
||||
public void connect() {
|
||||
private void connect() {
|
||||
Log.info(String.format("Connecting to server: %s", address));
|
||||
if (reason == null || reason == ConnectionReasons.DNS) {
|
||||
// first get version, then login
|
||||
@ -205,7 +196,6 @@ public class Connection {
|
||||
public void setVersion(Version version) {
|
||||
this.version = version;
|
||||
this.customMapping.setVersion(version);
|
||||
if (reason == ConnectionReasons.GET_VERSION) {
|
||||
try {
|
||||
Versions.loadVersionMappings(version.getProtocolVersion());
|
||||
} catch (Exception e) {
|
||||
@ -214,7 +204,6 @@ public class Connection {
|
||||
System.exit(1);
|
||||
}
|
||||
customMapping.setVersion(version);
|
||||
}
|
||||
}
|
||||
|
||||
public PacketHandler getHandler() {
|
||||
|
@ -64,6 +64,8 @@ public class Network {
|
||||
socket = new Socket();
|
||||
socket.setSoTimeout(ProtocolDefinition.SOCKET_CONNECT_TIMEOUT);
|
||||
socket.connect(new InetSocketAddress(address.getHostname(), address.getPort()), ProtocolDefinition.SOCKET_CONNECT_TIMEOUT);
|
||||
// connected, use minecraft timeout
|
||||
socket.setSoTimeout(ProtocolDefinition.SOCKET_TIMEOUT);
|
||||
connected = true;
|
||||
connection.setConnectionState(ConnectionStates.HANDSHAKING);
|
||||
socket.setKeepAlive(true);
|
||||
@ -120,79 +122,82 @@ public class Network {
|
||||
}
|
||||
}
|
||||
|
||||
// everything sent for now, waiting for data
|
||||
if (inputStream.available() > 0) { // available seems not to work in CipherInputStream
|
||||
int numRead = 0;
|
||||
int length = 0;
|
||||
byte read;
|
||||
do {
|
||||
read = cipherInputStream.readNBytes(1)[0];
|
||||
int value = (read & 0b01111111);
|
||||
length |= (value << (7 * numRead));
|
||||
|
||||
numRead++;
|
||||
if (numRead > 5) {
|
||||
throw new RuntimeException("VarInt is too big");
|
||||
}
|
||||
} while ((read & 0b10000000) != 0);
|
||||
|
||||
byte[] data = cipherInputStream.readNBytes(length);
|
||||
|
||||
if (compressionThreshold >= 0) {
|
||||
// compression is enabled
|
||||
// check if there is a need to decompress it and if so, do it!
|
||||
InByteBuffer rawBuffer = new InByteBuffer(data, connection);
|
||||
int packetSize = rawBuffer.readVarInt();
|
||||
byte[] left = rawBuffer.readBytesLeft();
|
||||
if (packetSize == 0) {
|
||||
// no need
|
||||
data = left;
|
||||
} else {
|
||||
// need to decompress data
|
||||
data = Util.decompress(left, connection).readBytesLeft();
|
||||
}
|
||||
// everything sent for now, waiting for data
|
||||
int numRead = 0;
|
||||
int length = 0;
|
||||
int read;
|
||||
do {
|
||||
read = cipherInputStream.read();
|
||||
if (read == -1) {
|
||||
break;
|
||||
}
|
||||
int value = (read & 0b01111111);
|
||||
length |= (value << (7 * numRead));
|
||||
|
||||
InPacketBuffer inPacketBuffer = new InPacketBuffer(data, connection);
|
||||
Packets.Clientbound packet = null;
|
||||
try {
|
||||
packet = connection.getPacketByCommand(connection.getConnectionState(), inPacketBuffer.getCommand());
|
||||
if (packet == null) {
|
||||
Log.fatal(String.format("Version packet enum does not contain a packet with id 0x%x. Your version.json is broken!", inPacketBuffer.getCommand()));
|
||||
System.exit(1);
|
||||
}
|
||||
Class<? extends ClientboundPacket> clazz = packet.getClazz();
|
||||
numRead++;
|
||||
if (numRead > 5) {
|
||||
throw new RuntimeException("VarInt is too big");
|
||||
}
|
||||
} while ((read & 0b10000000) != 0);
|
||||
if (length == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (clazz == null) {
|
||||
Log.warn(String.format("[IN] Received unknown packet (id=0x%x, name=%s, length=%d, dataLength=%d, version=%s, state=%s)", inPacketBuffer.getCommand(), packet, inPacketBuffer.getLength(), inPacketBuffer.getBytesLeft(), connection.getVersion(), connection.getConnectionState()));
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
ClientboundPacket packetInstance = clazz.getConstructor().newInstance();
|
||||
boolean success = packetInstance.read(inPacketBuffer);
|
||||
if (inPacketBuffer.getBytesLeft() > 0 || !success) {
|
||||
// warn not all data used
|
||||
Log.warn(String.format("[IN] Could not parse packet %s (used=%d, available=%d, total=%d, success=%s)", packet, inPacketBuffer.getPosition(), inPacketBuffer.getBytesLeft(), inPacketBuffer.getLength(), success));
|
||||
continue;
|
||||
}
|
||||
byte[] data = cipherInputStream.readNBytes(length);
|
||||
|
||||
//set special settings to avoid miss timing issues
|
||||
if (packetInstance instanceof PacketLoginSuccess) {
|
||||
connection.setConnectionState(ConnectionStates.PLAY);
|
||||
} else if (packetInstance instanceof PacketCompressionInterface) {
|
||||
compressionThreshold = ((PacketCompressionInterface) packetInstance).getThreshold();
|
||||
}
|
||||
connection.handle(packetInstance);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
// safety first, but will not occur
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.protocol(String.format("An error occurred while parsing an packet (%s): %s", packet, e));
|
||||
e.printStackTrace();
|
||||
if (compressionThreshold >= 0) {
|
||||
// compression is enabled
|
||||
// check if there is a need to decompress it and if so, do it!
|
||||
InByteBuffer rawBuffer = new InByteBuffer(data, connection);
|
||||
int packetSize = rawBuffer.readVarInt();
|
||||
byte[] left = rawBuffer.readBytesLeft();
|
||||
if (packetSize == 0) {
|
||||
// no need
|
||||
data = left;
|
||||
} else {
|
||||
// need to decompress data
|
||||
data = Util.decompress(left, connection).readBytesLeft();
|
||||
}
|
||||
}
|
||||
Util.sleep(1);
|
||||
|
||||
InPacketBuffer inPacketBuffer = new InPacketBuffer(data, connection);
|
||||
Packets.Clientbound packet = null;
|
||||
try {
|
||||
packet = connection.getPacketByCommand(connection.getConnectionState(), inPacketBuffer.getCommand());
|
||||
if (packet == null) {
|
||||
Log.fatal(String.format("Version packet enum does not contain a packet with id 0x%x. Your version.json is broken!", inPacketBuffer.getCommand()));
|
||||
System.exit(1);
|
||||
}
|
||||
Class<? extends ClientboundPacket> clazz = packet.getClazz();
|
||||
|
||||
if (clazz == null) {
|
||||
Log.warn(String.format("[IN] Received unknown packet (id=0x%x, name=%s, length=%d, dataLength=%d, version=%s, state=%s)", inPacketBuffer.getCommand(), packet, inPacketBuffer.getLength(), inPacketBuffer.getBytesLeft(), connection.getVersion(), connection.getConnectionState()));
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
ClientboundPacket packetInstance = clazz.getConstructor().newInstance();
|
||||
boolean success = packetInstance.read(inPacketBuffer);
|
||||
if (inPacketBuffer.getBytesLeft() > 0 || !success) {
|
||||
// warn not all data used
|
||||
Log.warn(String.format("[IN] Could not parse packet %s (used=%d, available=%d, total=%d, success=%s)", packet, inPacketBuffer.getPosition(), inPacketBuffer.getBytesLeft(), inPacketBuffer.getLength(), success));
|
||||
continue;
|
||||
}
|
||||
|
||||
//set special settings to avoid miss timing issues
|
||||
if (packetInstance instanceof PacketLoginSuccess) {
|
||||
connection.setConnectionState(ConnectionStates.PLAY);
|
||||
} else if (packetInstance instanceof PacketCompressionInterface) {
|
||||
compressionThreshold = ((PacketCompressionInterface) packetInstance).getThreshold();
|
||||
}
|
||||
connection.handle(packetInstance);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
// safety first, but will not occur
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.protocol(String.format("An error occurred while parsing an packet (%s): %s", packet, e));
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
socket.close();
|
||||
connected = false;
|
||||
|
@ -17,6 +17,7 @@ import de.bixilon.minosoft.logging.Log;
|
||||
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
|
||||
import de.bixilon.minosoft.protocol.protocol.InByteBuffer;
|
||||
import de.bixilon.minosoft.protocol.protocol.PacketHandler;
|
||||
import de.bixilon.minosoft.util.Util;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@ -27,7 +28,7 @@ public class PacketLoginSuccess implements ClientboundPacket {
|
||||
@Override
|
||||
public boolean read(InByteBuffer buffer) {
|
||||
if (buffer.getProtocolId() < 707) {
|
||||
uuid = UUID.fromString(buffer.readString());
|
||||
uuid = Util.uuidFromString(buffer.readString());
|
||||
username = buffer.readString();
|
||||
return true;
|
||||
}
|
||||
|
@ -40,8 +40,13 @@ public final class Util {
|
||||
}
|
||||
}
|
||||
|
||||
public static UUID formatUUID(String uuid) {
|
||||
return UUID.fromString(UUID_FIX.matcher(uuid.replace("-", "")).replaceAll("$1-$2-$3-$4-$5"));
|
||||
public static UUID uuidFromString(String uuid) {
|
||||
if (uuid.length() == 36) {
|
||||
return UUID.fromString(uuid);
|
||||
} else if (uuid.length() == 32) {
|
||||
return UUID.fromString(UUID_FIX.matcher(uuid.replace("-", "")).replaceAll("$1-$2-$3-$4-$5"));
|
||||
}
|
||||
throw new IllegalArgumentException(String.format("%s is not a valid UUID String", uuid));
|
||||
}
|
||||
|
||||
public static InByteBuffer decompress(byte[] bytes, Connection connection) {
|
||||
|
@ -31,7 +31,7 @@ public class MojangAccount {
|
||||
public MojangAccount(JsonObject json) {
|
||||
this.accessToken = json.get("accessToken").getAsString();
|
||||
JsonObject profile = json.get("selectedProfile").getAsJsonObject();
|
||||
this.uuid = Util.formatUUID(profile.get("id").getAsString());
|
||||
this.uuid = Util.uuidFromString(profile.get("id").getAsString());
|
||||
this.playerName = profile.get("name").getAsString();
|
||||
|
||||
JsonObject mojang = json.get("user").getAsJsonObject();
|
||||
|
Loading…
x
Reference in New Issue
Block a user