diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/multiplayer/MultiplayerPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/multiplayer/MultiplayerPage.java index 8d63fbe87..7a18cf11a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/multiplayer/MultiplayerPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/multiplayer/MultiplayerPage.java @@ -186,6 +186,11 @@ public class MultiplayerPage extends Control implements DecoratorPage, PageAware clients.add(event); }); }); + session.getServer().onClientDisconnected().register(event -> { + runInFX(() -> { + clients.remove(event); + }); + }); initCatoSession(session); } catch (Exception e) { LOG.log(Level.WARNING, "Failed to create session", e); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/multiplayer/MultiplayerPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/multiplayer/MultiplayerPageSkin.java index 9467be464..59422f594 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/multiplayer/MultiplayerPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/multiplayer/MultiplayerPageSkin.java @@ -182,11 +182,13 @@ public class MultiplayerPageSkin extends SkinBase { i18n("multiplayer.state.master", control.getSession() == null ? "" : control.getSession().getName(), control.getGamePort()), control.gamePortProperty(), control.sessionProperty())); + Label membersLabel = new Label(i18n("multiplayer.session.create.members")); + VBox clientsPane = new VBox(8); - clients = MappedObservableList.create(control.getClients(), client -> new ClientItem(client)); + clients = MappedObservableList.create(control.getClients(), ClientItem::new); Bindings.bindContent(clientsPane.getChildren(), clients); - masterPane.getChildren().setAll(masterHintPane, label, clientsPane); + masterPane.getChildren().setAll(masterHintPane, label, membersLabel, clientsPane); } BorderPane slavePane = new BorderPane(); @@ -303,6 +305,7 @@ public class MultiplayerPageSkin extends SkinBase { private static class ClientItem extends StackPane { ClientItem(MultiplayerChannel.CatoClient client) { BorderPane pane = new BorderPane(); + pane.setPadding(new Insets(8)); pane.setLeft(new Label(client.getUsername())); RipplerContainer container = new RipplerContainer(pane); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/multiplayer/MultiplayerServer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/multiplayer/MultiplayerServer.java index 035da0d1b..28e91db07 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/multiplayer/MultiplayerServer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/multiplayer/MultiplayerServer.java @@ -36,6 +36,7 @@ public class MultiplayerServer extends Thread { private final int gamePort; private final EventManager onClientAdded = new EventManager<>(); + private final EventManager onClientDisconnected = new EventManager<>(); private final EventManager onKeepAlive = new EventManager<>(); public MultiplayerServer(int gamePort) { @@ -49,6 +50,10 @@ public class MultiplayerServer extends Thread { return onClientAdded; } + public EventManager onClientDisconnected() { + return onClientDisconnected; + } + public EventManager onKeepAlive() { return onKeepAlive; } @@ -88,6 +93,7 @@ public class MultiplayerServer extends Thread { } private void handleClient(Socket targetSocket) { + String clientName = null; LOG.info("Accepted client " + targetSocket.getRemoteSocketAddress()); try (Socket clientSocket = targetSocket; BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); @@ -109,6 +115,7 @@ public class MultiplayerServer extends Thread { writer.newLine(); writer.flush(); + clientName = joinRequest.getUsername(); onClientAdded.fireEvent(new CatoClient(this, joinRequest.getUsername())); } else if (request instanceof KeepAliveRequest) { writer.write(JsonUtils.UGLY_GSON.toJson(new KeepAliveResponse(System.currentTimeMillis()))); @@ -124,6 +131,10 @@ public class MultiplayerServer extends Thread { LOG.log(Level.WARNING, "Failed to handle client socket.", e); } catch (JsonParseException e) { LOG.log(Level.SEVERE, "Failed to parse client request. This should not happen.", e); + } finally { + if (clientName != null) { + onClientDisconnected.fireEvent(new CatoClient(this, clientName)); + } } } }