src/main/java/wtf/sten/vault/Remote.java
package wtf.sten.vault;
import com.google.gson.JsonObject;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.client.gui.screens.ConnectScreen;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.multiplayer.resolver.ServerAddress;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.entity.player.Input;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
public final class Remote {
private static String heldDir = "";
private static long heldUntil;
private Remote() {
}
public static void tick(Minecraft mc) {
if (!heldDir.isEmpty() && System.currentTimeMillis() >= heldUntil) {
heldDir = "";
}
}
public static Input heldInput() {
if (heldDir.isEmpty() || System.currentTimeMillis() >= heldUntil) return null;
String dir = heldDir;
return new Input(
"forward".equals(dir),
"back".equals(dir),
"left".equals(dir),
"right".equals(dir),
"jump".equals(dir),
"sneak".equals(dir),
"sprint".equals(dir)
);
}
public static void apply(JsonObject cmd) {
if (cmd == null || !VaultConfig.get().remoteControl) return;
try {
Minecraft mc = Minecraft.getInstance();
String kind = str(cmd, "kind");
switch (kind) {
case "chat" -> chat(mc, str(cmd, "text"));
case "move" -> move(mc, str(cmd, "dir"), num(cmd, "ms", 400));
case "look" -> look(mc, (float) num(cmd, "yaw", 0), (float) num(cmd, "pitch", 0));
case "screenshot" -> Shot.capture(mc, "manual");
case "switch" -> switchNow(str(cmd, "uid"));
case "join" -> join(mc, str(cmd, "host"), str(cmd, "proxy"));
case "proxy" -> setProxy(str(cmd, "proxy"));
case "disconnect" -> disconnect(mc);
case "stop" -> stop();
default -> {
}
}
} catch (Exception ex) {
StenNet.status = ex.getMessage() == null ? "Remote command failed" : ex.getMessage();
}
}
private static void chat(Minecraft mc, String text) {
if (text == null || text.isBlank()) return;
ClientPacketListener conn = mc.getConnection();
if (conn == null && mc.player != null) conn = mc.player.connection;
if (conn == null) {
StenNet.status = "Join a server first";
return;
}
String trimmed = text.trim();
if (trimmed.length() > 256) trimmed = trimmed.substring(0, 256);
if (trimmed.startsWith("/")) conn.sendCommand(trimmed.substring(1));
else conn.sendChat(trimmed);
}
private static void move(Minecraft mc, String dir, long ms) {
if (mc.player == null) {
StenNet.status = "Not in a world";
return;
}
String next = dir == null ? "" : dir.toLowerCase(Locale.ROOT);
if (next.isEmpty() || "stop".equals(next)) {
stop();
return;
}
heldDir = next;
heldUntil = System.currentTimeMillis() + Math.min(4000, Math.max(50, ms));
}
private static void look(Minecraft mc, float yaw, float pitch) {
LocalPlayer player = mc.player;
if (player == null) return;
player.setYRot(player.getYRot() + yaw);
player.setXRot(Math.max(-90, Math.min(90, player.getXRot() + pitch)));
}
static String normalizeHost(String raw) {
if (raw == null) return "";
String host = raw.trim();
int proto = host.indexOf("://");
if (proto >= 0) host = host.substring(proto + 3);
int cut = -1;
for (int i = 0; i < host.length(); i++) {
char c = host.charAt(i);
if (c == '/' || c == '?' || c == '#') {
cut = i;
break;
}
}
if (cut >= 0) host = host.substring(0, cut);
int at = host.lastIndexOf('@');
if (at >= 0) host = host.substring(at + 1);
if (host.endsWith(".")) host = host.substring(0, host.length() - 1);
return host.trim();
}
private static void join(Minecraft mc, String host, String proxy) {
String target = normalizeHost(host);
if (target.isEmpty() || !ServerAddress.isValidAddress(target)) {
StenNet.status = "Invalid server address";
return;
}
if (proxy != null && !proxy.isBlank()) setProxy(proxy);
ServerAddress address = ServerAddress.parseString(target);
ServerData data = new ServerData("sten.wtf", target, ServerData.Type.OTHER);
mc.execute(() -> {
try {
boolean inWorld = mc.level != null;
if (inWorld) mc.disconnect(new TitleScreen(), false);
Runnable connect = () -> {
try {
Screen parent = mc.gui.screen();
if (parent == null) parent = new TitleScreen();
ConnectScreen.startConnecting(parent, mc, address, data, false, null);
} catch (Exception ex) {
StenNet.status = ex.getMessage() == null ? "Join failed" : ex.getMessage();
}
};
if (inWorld) mc.execute(connect);
else connect.run();
} catch (Exception ex) {
StenNet.status = ex.getMessage() == null ? "Join failed" : ex.getMessage();
}
});
}
private static void setProxy(String raw) {
VaultConfig cfg = VaultConfig.get();
String next = raw == null ? "" : raw.trim();
if (!next.isEmpty() && Proxy.parse(next) == null) {
StenNet.status = "Invalid SOCKS5 proxy";
return;
}
cfg.proxy = next;
cfg.save();
StenNet.status = next.isEmpty() ? "Direct connection" : "Proxy " + next;
}
private static void disconnect(Minecraft mc) {
if (mc.level == null) return;
mc.execute(() -> mc.disconnect(new TitleScreen(), false));
}
private static void switchNow(String uid) {
if (uid == null || uid.isBlank()) return;
StenNet.status = "Remote switch…";
CompletableFuture.runAsync(() -> {
try {
JsonObject minted = StenNet.switchAccount(uid);
Minecraft.getInstance().execute(() -> {
try {
SessionSwap.apply(minted);
} catch (Exception ex) {
StenNet.status = ex.getMessage();
}
});
} catch (Exception ex) {
StenNet.status = ex.getMessage() == null ? "Switch failed" : ex.getMessage();
}
});
}
private static void stop() {
heldDir = "";
}
private static String str(JsonObject obj, String key) {
if (obj == null || !obj.has(key) || obj.get(key).isJsonNull()) return "";
try {
return obj.get(key).getAsString();
} catch (Exception ignored) {
return "";
}
}
private static long num(JsonObject obj, String key, long fallback) {
if (obj == null || !obj.has(key) || obj.get(key).isJsonNull()) return fallback;
try {
return obj.get(key).getAsLong();
} catch (Exception ignored) {
return fallback;
}
}
}