add fabric client

This commit is contained in:
1e99 2024-11-17 14:37:10 +01:00
parent 13315e708c
commit 1aabd0f3cf
4 changed files with 117 additions and 27 deletions

View file

@ -1,18 +1,45 @@
package eu.e99.svc.client.fabric;
import net.fabricmc.api.ClientModInitializer;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLSocketFactory;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
public class FabricSimplerVoiceChat implements ClientModInitializer {
public static final String NAMESPACE = "svc";
public static final Logger LOGGER = LoggerFactory.getLogger(NAMESPACE);
@Override
public void onInitializeClient() {
LOGGER.info("Simpler Voice Chat Running");
System.out.printf("Simpler Voice Chat loading...%n");
SSLSocketFactory socketFactory;
try {
socketFactory = SVCClient.createSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
System.out.printf("Failed to create socket factory:%n");
e.printStackTrace(System.out);
return;
}
MinecraftClient client = MinecraftClient.getInstance();
Session session = client.getSession();
SVCClient voiceChat = new SVCClient(
"localhost",
6969,
session.getAccessToken(),
session.getUsername(),
session.getUuidOrNull(),
socketFactory
);
Thread.ofPlatform().start(voiceChat::start);
}
}

View file

@ -3,11 +3,9 @@ package eu.e99.svc.client.fabric;
import eu.e99.svc.AllTrustManager;
import eu.e99.svc.Connection;
import eu.e99.svc.SimplerVoiceChat;
import eu.e99.svc.auth.MojangAPI;
import eu.e99.svc.io.BinaryMessage;
import eu.e99.svc.packet.AuthRequestPacket;
import eu.e99.svc.packet.AuthResponsePacket;
import eu.e99.svc.packet.AuthSuccessPacket;
import eu.e99.svc.packet.ClientHelloPacket;
import eu.e99.svc.packet.*;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
@ -18,10 +16,11 @@ import java.net.Socket;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.UUID;
public class SVCClient {
public static void main(String[] args) throws NoSuchAlgorithmException, KeyManagementException {
public static SSLSocketFactory createSocketFactory() throws NoSuchAlgorithmException, KeyManagementException {
TrustManager[] trustManagers = new TrustManager[]{
new AllTrustManager(),
};
@ -29,37 +28,58 @@ public class SVCClient {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, new SecureRandom());
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
SVCClient voiceChat = new SVCClient("localhost", 6969, socketFactory);
voiceChat.start();
return sslContext.getSocketFactory();
}
private final String host;
private final int port;
private final String accessToken;
private final String username;
private final UUID uuid;
private final SSLSocketFactory socketFactory;
public SVCClient(String host, int port, SSLSocketFactory socketFactory) {
public SVCClient(String host, int port, String accessToken, String username, UUID uuid, SSLSocketFactory socketFactory) {
this.host = host;
this.port = port;
this.accessToken = accessToken;
this.username = username;
this.uuid = uuid;
this.socketFactory = socketFactory;
}
public void start() {
// Connect and auth
try (Socket socket = this.socketFactory.createSocket()) {
socket.connect(new InetSocketAddress(this.host, this.port));
Connection conn = new Connection(socket);
while (true) {
try (Socket socket = this.socketFactory.createSocket()) {
System.out.printf("Connecting to %s.%n", this.host);
socket.connect(new InetSocketAddress(this.host, this.port));
Connection conn = new Connection(socket);
System.out.printf("Connected.");
this.handleHandshake(conn);
} catch (IOException e) {
System.out.printf("Failed to connect.%n");
e.printStackTrace(System.out);
boolean ok = this.handleHandshake(conn);
if (!ok) {
System.out.printf("Handshake failed.%n");
break;
}
System.out.printf("Successfully authenticated.%n");
} catch (IOException e) {
System.out.printf("Failed to connect.%n");
e.printStackTrace(System.out);
}
System.out.printf("Disconnected. Attempting reconnection in 30 seconds.%n");
try {
Thread.sleep(30_000);
} catch (InterruptedException e) {
System.out.printf("Failed to wait:%n");
e.printStackTrace(System.out);
}
}
}
private void handleHandshake(Connection conn) throws IOException {
private boolean handleHandshake(Connection conn) throws IOException {
ClientHelloPacket clientHello = new ClientHelloPacket();
clientHello.version = SimplerVoiceChat.PROTOCOL_VERSION;
conn.writePacket(clientHello);
@ -69,18 +89,35 @@ public class SVCClient {
switch (packet) {
case AuthRequestPacket authRequest -> {
System.out.printf("Joining fake server to authenticate.%n");
System.out.printf("Joining server to authenticate...%n");
boolean ok;
try {
ok = MojangAPI.joinServer(this.accessToken, this.uuid, authRequest.serverId);
} catch (Exception e) {
System.out.printf("Failed to join server:%n");
e.printStackTrace(System.out);
return false;
}
if (!ok) {
System.out.printf("Failed to join server.%n");
return false;
}
AuthResponsePacket authResponse = new AuthResponsePacket();
authResponse.username = "Test";
authResponse.username = this.username;
conn.writePacket(authResponse);
}
case AuthSuccessPacket authComplete -> {
System.out.printf("Successfully authenticated.%n");
return;
return true;
}
case DisconnectPacket disconnect -> {
System.out.printf("Disconnected with reason \"%s\".%n", disconnect.reason);
return false;
}
default -> {
System.out.printf("Got unexpected packet.%n");
System.out.printf("Got unexpected packet %s.%n", packet.getClass().getName());
}
}
}

View file

@ -24,7 +24,7 @@ public class MojangAPI {
.build();
HttpResponse<String> res = client.send(req, HttpResponse.BodyHandlers.ofString());
if (res.statusCode() == 204) {
if (res.statusCode() != 200) {
return null;
}
@ -39,4 +39,29 @@ public class MojangAPI {
return new PlayerProfile(name, uuid);
}
}
public static boolean joinServer(String accessToken, UUID uuid, String serverId) throws IOException, InterruptedException {
try (HttpClient client = HttpClient.newHttpClient()) {
String loc = "https://sessionserver.mojang.com/session/minecraft/join";
URI uri = URI.create(loc);
JsonObject body = new JsonObject();
body.addProperty("accessToken", accessToken);
body.addProperty("selectedProfile", uuid.toString().replace("-", ""));
body.addProperty("serverId", serverId);
HttpRequest req = HttpRequest.newBuilder()
.uri(uri)
.POST(HttpRequest.BodyPublishers.ofString(body.toString()))
.build();
HttpResponse<Void> res = client.send(req, HttpResponse.BodyHandlers.discarding());
System.out.printf("%d%n", res.statusCode());
if (res.statusCode() != 204) {
return false;
}
return true;
}
}
}

View file

@ -7,6 +7,7 @@ import eu.e99.svc.auth.PlayerProfile;
import eu.e99.svc.io.BinaryMessage;
import eu.e99.svc.packet.*;
import java.io.EOFException;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
@ -38,7 +39,7 @@ public class Server {
this.socket.notify();
}
System.out.printf("Failed to accept client.%n");
System.out.printf("Failed to handle client.%n");
e.printStackTrace(System.out);
}
});