175 lines
6.5 KiB
Java
175 lines
6.5 KiB
Java
package net.minecraft.server.chase;
|
|
|
|
import com.google.common.base.Charsets;
|
|
import com.mojang.logging.LogUtils;
|
|
import java.io.BufferedReader;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.io.StringReader;
|
|
import java.net.Socket;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.NoSuchElementException;
|
|
import java.util.Optional;
|
|
import java.util.Scanner;
|
|
import javax.annotation.Nullable;
|
|
import net.minecraft.commands.CommandSourceStack;
|
|
import net.minecraft.commands.Commands;
|
|
import net.minecraft.network.chat.CommonComponents;
|
|
import net.minecraft.resources.ResourceKey;
|
|
import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.server.commands.ChaseCommand;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.phys.Vec2;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.apache.commons.io.IOUtils;
|
|
import org.slf4j.Logger;
|
|
|
|
public class ChaseClient {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private static final int RECONNECT_INTERVAL_SECONDS = 5;
|
|
private final String serverHost;
|
|
private final int serverPort;
|
|
private final MinecraftServer server;
|
|
private volatile boolean wantsToRun;
|
|
@Nullable
|
|
private Socket socket;
|
|
@Nullable
|
|
private Thread thread;
|
|
|
|
public ChaseClient(String p_195990_, int p_195991_, MinecraftServer p_195992_) {
|
|
this.serverHost = p_195990_;
|
|
this.serverPort = p_195991_;
|
|
this.server = p_195992_;
|
|
}
|
|
|
|
public void start() {
|
|
if (this.thread != null && this.thread.isAlive()) {
|
|
LOGGER.warn("Remote control client was asked to start, but it is already running. Will ignore.");
|
|
}
|
|
|
|
this.wantsToRun = true;
|
|
this.thread = new Thread(this::run, "chase-client");
|
|
this.thread.setDaemon(true);
|
|
this.thread.start();
|
|
}
|
|
|
|
public void stop() {
|
|
this.wantsToRun = false;
|
|
IOUtils.closeQuietly(this.socket);
|
|
this.socket = null;
|
|
this.thread = null;
|
|
}
|
|
|
|
public void run() {
|
|
String s = this.serverHost + ":" + this.serverPort;
|
|
|
|
while (this.wantsToRun) {
|
|
try {
|
|
LOGGER.info("Connecting to remote control server {}", s);
|
|
this.socket = new Socket(this.serverHost, this.serverPort);
|
|
LOGGER.info("Connected to remote control server! Will continuously execute the command broadcasted by that server.");
|
|
|
|
try (BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(this.socket.getInputStream(), Charsets.US_ASCII))) {
|
|
while (this.wantsToRun) {
|
|
String s1 = bufferedreader.readLine();
|
|
if (s1 == null) {
|
|
LOGGER.warn("Lost connection to remote control server {}. Will retry in {}s.", s, 5);
|
|
break;
|
|
}
|
|
|
|
this.handleMessage(s1);
|
|
}
|
|
} catch (IOException ioexception) {
|
|
LOGGER.warn("Lost connection to remote control server {}. Will retry in {}s.", s, 5);
|
|
}
|
|
} catch (IOException ioexception1) {
|
|
LOGGER.warn("Failed to connect to remote control server {}. Will retry in {}s.", s, 5);
|
|
}
|
|
|
|
if (this.wantsToRun) {
|
|
try {
|
|
Thread.sleep(5000L);
|
|
} catch (InterruptedException interruptedexception) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void handleMessage(String p_195995_) {
|
|
try (Scanner scanner = new Scanner(new StringReader(p_195995_))) {
|
|
scanner.useLocale(Locale.ROOT);
|
|
String s = scanner.next();
|
|
if ("t".equals(s)) {
|
|
this.handleTeleport(scanner);
|
|
} else {
|
|
LOGGER.warn("Unknown message type '{}'", s);
|
|
}
|
|
} catch (NoSuchElementException nosuchelementexception) {
|
|
LOGGER.warn("Could not parse message '{}', ignoring", p_195995_);
|
|
}
|
|
}
|
|
|
|
private void handleTeleport(Scanner p_195997_) {
|
|
this.parseTarget(p_195997_)
|
|
.ifPresent(
|
|
p_195999_ -> this.executeCommand(
|
|
String.format(
|
|
Locale.ROOT,
|
|
"execute in %s run tp @s %.3f %.3f %.3f %.3f %.3f",
|
|
p_195999_.level.location(),
|
|
p_195999_.pos.x,
|
|
p_195999_.pos.y,
|
|
p_195999_.pos.z,
|
|
p_195999_.rot.y,
|
|
p_195999_.rot.x
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
private Optional<ChaseClient.TeleportTarget> parseTarget(Scanner p_196004_) {
|
|
ResourceKey<Level> resourcekey = ChaseCommand.DIMENSION_NAMES.get(p_196004_.next());
|
|
if (resourcekey == null) {
|
|
return Optional.empty();
|
|
} else {
|
|
float f = p_196004_.nextFloat();
|
|
float f1 = p_196004_.nextFloat();
|
|
float f2 = p_196004_.nextFloat();
|
|
float f3 = p_196004_.nextFloat();
|
|
float f4 = p_196004_.nextFloat();
|
|
return Optional.of(new ChaseClient.TeleportTarget(resourcekey, new Vec3(f, f1, f2), new Vec2(f4, f3)));
|
|
}
|
|
}
|
|
|
|
private void executeCommand(String p_196002_) {
|
|
this.server
|
|
.execute(
|
|
() -> {
|
|
List<ServerPlayer> list = this.server.getPlayerList().getPlayers();
|
|
if (!list.isEmpty()) {
|
|
ServerPlayer serverplayer = list.get(0);
|
|
ServerLevel serverlevel = this.server.overworld();
|
|
CommandSourceStack commandsourcestack = new CommandSourceStack(
|
|
serverplayer.commandSource(),
|
|
Vec3.atLowerCornerOf(serverlevel.getSharedSpawnPos()),
|
|
Vec2.ZERO,
|
|
serverlevel,
|
|
4,
|
|
"",
|
|
CommonComponents.EMPTY,
|
|
this.server,
|
|
serverplayer
|
|
);
|
|
Commands commands = this.server.getCommands();
|
|
commands.performPrefixedCommand(commandsourcestack, p_196002_);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
record TeleportTarget(ResourceKey<Level> level, Vec3 pos, Vec2 rot) {
|
|
}
|
|
} |