ChaseServer.java
net.minecraft.server.chase.ChaseServer
信息
- 全限定名:net.minecraft.server.chase.ChaseServer
- 类型:public class
- 包:net.minecraft.server.chase
- 源码路径:src/main/java/net/minecraft/server/chase/ChaseServer.java
- 起始行号:L23
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L24 - 说明:
TODO
- 类型:
-
serverBindAddress- 类型:
String - 修饰符:
private final - 源码定位:
L25 - 说明:
TODO
- 类型:
-
serverPort- 类型:
int - 修饰符:
private final - 源码定位:
L26 - 说明:
TODO
- 类型:
-
playerList- 类型:
PlayerList - 修饰符:
private final - 源码定位:
L27 - 说明:
TODO
- 类型:
-
broadcastIntervalMs- 类型:
int - 修饰符:
private final - 源码定位:
L28 - 说明:
TODO
- 类型:
-
wantsToRun- 类型:
boolean - 修饰符:
private volatile - 源码定位:
L29 - 说明:
TODO
- 类型:
-
serverSocket- 类型:
ServerSocket - 修饰符:
private - 源码定位:
L30 - 说明:
TODO
- 类型:
-
clientSockets- 类型:
CopyOnWriteArrayList<Socket> - 修饰符:
private final - 源码定位:
L31 - 说明:
TODO
- 类型:
内部类/嵌套类型
net.minecraft.server.chase.ChaseServer.PlayerPosition- 类型:
record - 修饰符:
private - 源码定位:
L139 - 说明:
TODO
- 类型:
构造器
public ChaseServer(String serverBindAddress, int serverPort, PlayerList playerList, int broadcastIntervalMs) @ L33
- 构造器名:ChaseServer
- 源码定位:L33
- 修饰符:public
参数:
- serverBindAddress: String
- serverPort: int
- playerList: PlayerList
- broadcastIntervalMs: int
说明:
TODO
方法
下面的方法块按源码顺序生成。
public void start() @ L40
- 方法名:start
- 源码定位:L40
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
private void runSender() @ L55
- 方法名:runSender
- 源码定位:L55
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
public void stop() @ L94
- 方法名:stop
- 源码定位:L94
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
private void runAcceptor() @ L100
- 方法名:runAcceptor
- 源码定位:L100
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
private ChaseServer.PlayerPosition getPlayerPosition() @ L126
- 方法名:getPlayerPosition
- 源码定位:L126
- 返回类型:ChaseServer.PlayerPosition
- 修饰符:private
参数:
- 无
说明:
TODO
代码
public class ChaseServer {
private static final Logger LOGGER = LogUtils.getLogger();
private final String serverBindAddress;
private final int serverPort;
private final PlayerList playerList;
private final int broadcastIntervalMs;
private volatile boolean wantsToRun;
private @Nullable ServerSocket serverSocket;
private final CopyOnWriteArrayList<Socket> clientSockets = new CopyOnWriteArrayList<>();
public ChaseServer(String serverBindAddress, int serverPort, PlayerList playerList, int broadcastIntervalMs) {
this.serverBindAddress = serverBindAddress;
this.serverPort = serverPort;
this.playerList = playerList;
this.broadcastIntervalMs = broadcastIntervalMs;
}
public void start() throws IOException {
if (this.serverSocket != null && !this.serverSocket.isClosed()) {
LOGGER.warn("Remote control server was asked to start, but it is already running. Will ignore.");
} else {
this.wantsToRun = true;
this.serverSocket = new ServerSocket(this.serverPort, 50, InetAddress.getByName(this.serverBindAddress));
Thread acceptor = new Thread(this::runAcceptor, "chase-server-acceptor");
acceptor.setDaemon(true);
acceptor.start();
Thread sender = new Thread(this::runSender, "chase-server-sender");
sender.setDaemon(true);
sender.start();
}
}
private void runSender() {
ChaseServer.PlayerPosition oldPlayerPosition = null;
while (this.wantsToRun) {
if (!this.clientSockets.isEmpty()) {
ChaseServer.PlayerPosition playerPosition = this.getPlayerPosition();
if (playerPosition != null && !playerPosition.equals(oldPlayerPosition)) {
oldPlayerPosition = playerPosition;
byte[] messageBytes = playerPosition.format().getBytes(StandardCharsets.US_ASCII);
for (Socket clientSocket : this.clientSockets) {
if (!clientSocket.isClosed()) {
Util.ioPool().execute(() -> {
try {
OutputStream output = clientSocket.getOutputStream();
output.write(messageBytes);
output.flush();
} catch (IOException var3x) {
LOGGER.info("Remote control client socket got an IO exception and will be closed", (Throwable)var3x);
IOUtils.closeQuietly(clientSocket);
}
});
}
}
}
List<Socket> closed = this.clientSockets.stream().filter(Socket::isClosed).collect(Collectors.toList());
this.clientSockets.removeAll(closed);
}
if (this.wantsToRun) {
try {
Thread.sleep(this.broadcastIntervalMs);
} catch (InterruptedException var6) {
}
}
}
}
public void stop() {
this.wantsToRun = false;
IOUtils.closeQuietly(this.serverSocket);
this.serverSocket = null;
}
private void runAcceptor() {
try {
while (this.wantsToRun) {
if (this.serverSocket != null) {
LOGGER.info("Remote control server is listening for connections on port {}", this.serverPort);
Socket clientSocket = this.serverSocket.accept();
LOGGER.info("Remote control server received client connection on port {}", clientSocket.getPort());
this.clientSockets.add(clientSocket);
}
}
} catch (ClosedByInterruptException var6) {
if (this.wantsToRun) {
LOGGER.info("Remote control server closed by interrupt");
}
} catch (IOException var7) {
if (this.wantsToRun) {
LOGGER.error("Remote control server closed because of an IO exception", (Throwable)var7);
}
} finally {
IOUtils.closeQuietly(this.serverSocket);
}
LOGGER.info("Remote control server is now stopped");
this.wantsToRun = false;
}
private ChaseServer.@Nullable PlayerPosition getPlayerPosition() {
List<ServerPlayer> players = this.playerList.getPlayers();
if (players.isEmpty()) {
return null;
} else {
ServerPlayer player = players.get(0);
String dimensionName = ChaseCommand.DIMENSION_NAMES.inverse().get(player.level().dimension());
return dimensionName == null
? null
: new ChaseServer.PlayerPosition(dimensionName, player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
}
}
private record PlayerPosition(String dimensionName, double x, double y, double z, float yRot, float xRot) {
private String format() {
return String.format(Locale.ROOT, "t %s %.2f %.2f %.2f %.2f %.2f\n", this.dimensionName, this.x, this.y, this.z, this.yRot, this.xRot);
}
}
}引用的其他类
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Util.ioPool()
- 引用位置: