ChaseClient.java

net.minecraft.server.chase.ChaseClient

信息

  • 全限定名:net.minecraft.server.chase.ChaseClient
  • 类型:public class
  • 包:net.minecraft.server.chase
  • 源码路径:src/main/java/net/minecraft/server/chase/ChaseClient.java
  • 起始行号:L31
  • 职责:

    TODO

字段/常量

  • LOGGER

    • 类型: Logger
    • 修饰符: private static final
    • 源码定位: L32
    • 说明:

      TODO

  • RECONNECT_INTERVAL_SECONDS

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L33
    • 说明:

      TODO

  • serverHost

    • 类型: String
    • 修饰符: private final
    • 源码定位: L34
    • 说明:

      TODO

  • serverPort

    • 类型: int
    • 修饰符: private final
    • 源码定位: L35
    • 说明:

      TODO

  • server

    • 类型: MinecraftServer
    • 修饰符: private final
    • 源码定位: L36
    • 说明:

      TODO

  • wantsToRun

    • 类型: boolean
    • 修饰符: private volatile
    • 源码定位: L37
    • 说明:

      TODO

  • socket

    • 类型: Socket
    • 修饰符: private
    • 源码定位: L38
    • 说明:

      TODO

  • thread

    • 类型: Thread
    • 修饰符: private
    • 源码定位: L39
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.server.chase.ChaseClient.TeleportTarget
    • 类型: record
    • 修饰符: package-private
    • 源码定位: L172
    • 说明:

      TODO

构造器

public ChaseClient(String serverHost, int serverPort, MinecraftServer server) @ L41

  • 构造器名:ChaseClient
  • 源码定位:L41
  • 修饰符:public

参数:

  • serverHost: String
  • serverPort: int
  • server: MinecraftServer

说明:

TODO

方法

下面的方法块按源码顺序生成。

public void start() @ L47

  • 方法名:start
  • 源码定位:L47
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public void stop() @ L58

  • 方法名:stop
  • 源码定位:L58
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public void run() @ L65

  • 方法名:run
  • 源码定位:L65
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

private void handleMessage(String message) @ L100

  • 方法名:handleMessage
  • 源码定位:L100
  • 返回类型:void
  • 修饰符:private

参数:

  • message: String

说明:

TODO

private void handleTeleport(Scanner scanner) @ L114

  • 方法名:handleTeleport
  • 源码定位:L114
  • 返回类型:void
  • 修饰符:private

参数:

  • scanner: Scanner

说明:

TODO

private Optional<ChaseClient.TeleportTarget> parseTarget(Scanner scanner) @ L132

  • 方法名:parseTarget
  • 源码定位:L132
  • 返回类型:Optional<ChaseClient.TeleportTarget>
  • 修饰符:private

参数:

  • scanner: Scanner

说明:

TODO

private void executeCommand(String command) @ L146

  • 方法名:executeCommand
  • 源码定位:L146
  • 返回类型:void
  • 修饰符:private

参数:

  • command: String

说明:

TODO

代码

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;
    private @Nullable Socket socket;
    private @Nullable Thread thread;
 
    public ChaseClient(String serverHost, int serverPort, MinecraftServer server) {
        this.serverHost = serverHost;
        this.serverPort = serverPort;
        this.server = server;
    }
 
    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 serverAddress = this.serverHost + ":" + this.serverPort;
 
        while (this.wantsToRun) {
            try {
                LOGGER.info("Connecting to remote control server {}", serverAddress);
                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 input = new BufferedReader(new InputStreamReader(this.socket.getInputStream(), StandardCharsets.US_ASCII))) {
                    while (this.wantsToRun) {
                        String message = input.readLine();
                        if (message == null) {
                            LOGGER.warn("Lost connection to remote control server {}. Will retry in {}s.", serverAddress, 5);
                            break;
                        }
 
                        this.handleMessage(message);
                    }
                } catch (IOException var8) {
                    LOGGER.warn("Lost connection to remote control server {}. Will retry in {}s.", serverAddress, 5);
                }
            } catch (IOException var9) {
                LOGGER.warn("Failed to connect to remote control server {}. Will retry in {}s.", serverAddress, 5);
            }
 
            if (this.wantsToRun) {
                try {
                    Thread.sleep(5000L);
                } catch (InterruptedException var5) {
                }
            }
        }
    }
 
    private void handleMessage(String message) {
        try (Scanner scanner = new Scanner(new StringReader(message))) {
            scanner.useLocale(Locale.ROOT);
            String head = scanner.next();
            if ("t".equals(head)) {
                this.handleTeleport(scanner);
            } else {
                LOGGER.warn("Unknown message type '{}'", head);
            }
        } catch (NoSuchElementException var7) {
            LOGGER.warn("Could not parse message '{}', ignoring", message);
        }
    }
 
    private void handleTeleport(Scanner scanner) {
        this.parseTarget(scanner)
            .ifPresent(
                target -> this.executeCommand(
                    String.format(
                        Locale.ROOT,
                        "execute in %s run tp @s %.3f %.3f %.3f %.3f %.3f",
                        target.level.identifier(),
                        target.pos.x,
                        target.pos.y,
                        target.pos.z,
                        target.rot.y,
                        target.rot.x
                    )
                )
            );
    }
 
    private Optional<ChaseClient.TeleportTarget> parseTarget(Scanner scanner) {
        ResourceKey<Level> levelType = ChaseCommand.DIMENSION_NAMES.get(scanner.next());
        if (levelType == null) {
            return Optional.empty();
        } else {
            float x = scanner.nextFloat();
            float y = scanner.nextFloat();
            float z = scanner.nextFloat();
            float yRot = scanner.nextFloat();
            float xRot = scanner.nextFloat();
            return Optional.of(new ChaseClient.TeleportTarget(levelType, new Vec3(x, y, z), new Vec2(xRot, yRot)));
        }
    }
 
    private void executeCommand(String command) {
        this.server
            .execute(
                () -> {
                    List<ServerPlayer> players = this.server.getPlayerList().getPlayers();
                    if (!players.isEmpty()) {
                        ServerPlayer player = players.get(0);
                        ServerLevel level = this.server.overworld();
                        CommandSourceStack commandSourceStack = new CommandSourceStack(
                            player.commandSource(),
                            Vec3.atLowerCornerOf(level.getRespawnData().pos()),
                            Vec2.ZERO,
                            level,
                            LevelBasedPermissionSet.OWNER,
                            "",
                            CommonComponents.EMPTY,
                            this.server,
                            player
                        );
                        Commands commands = this.server.getCommands();
                        commands.performPrefixedCommand(commandSourceStack, command);
                    }
                }
            );
    }
 
    record TeleportTarget(ResourceKey<Level> level, Vec3 pos, Vec2 rot) {
    }
}

引用的其他类

  • CommandSourceStack

    • 引用位置: 构造调用
    • 关联成员: CommandSourceStack()
  • MinecraftServer

    • 引用位置: 参数/字段
  • Vec2

    • 引用位置: 构造调用
    • 关联成员: Vec2()
  • Vec3

    • 引用位置: 方法调用/构造调用
    • 关联成员: Vec3(), Vec3.atLowerCornerOf()