From 87305f601ff9e4e0faa416c6f1bc32afef38cfa4 Mon Sep 17 00:00:00 2001 From: sauliuskarmanovas <38034030+sauliuskarmanovas@users.noreply.github.com> Date: Sat, 1 Apr 2023 19:06:40 +0300 Subject: [PATCH 1/5] Send a message to GM when we're done loading --- .../maptool/client/ui/zone/ZoneRenderer.java | 14 ++++++++++++++ .../net/rptools/maptool/language/i18n.properties | 1 + 2 files changed, 15 insertions(+) diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java b/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java index 2c8d24a31e..23ce71b772 100644 --- a/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java +++ b/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java @@ -72,6 +72,7 @@ import net.rptools.maptool.model.zones.*; import net.rptools.maptool.util.GraphicsUtil; import net.rptools.maptool.util.ImageManager; +import net.rptools.maptool.util.MessageUtil; import net.rptools.maptool.util.StringUtil; import net.rptools.maptool.util.TokenUtil; import net.rptools.parser.ParserException; @@ -1965,6 +1966,19 @@ public boolean isLoading() { if (isLoaded) { // Notify the token tree that it should update MapTool.getFrame().updateTokenTree(); + + // If we're in a server send a message to GM that we're done loading + if (MapTool.getConnection() != null) { + String mesg = + MessageUtil.getFormattedSystemMsg( + I18N.getText( + "msg.info.playerFinishedLoadingZone", + MapTool.getPlayer().getName(), + zone.getDisplayName())); + + TextMessage msg = TextMessage.gm(null, mesg); + MapTool.addMessage(msg); + } } return !isLoaded; } diff --git a/src/main/resources/net/rptools/maptool/language/i18n.properties b/src/main/resources/net/rptools/maptool/language/i18n.properties index 3921e337cc..fc29cada13 100644 --- a/src/main/resources/net/rptools/maptool/language/i18n.properties +++ b/src/main/resources/net/rptools/maptool/language/i18n.properties @@ -2122,6 +2122,7 @@ msg.info.noCampaignPreview = No campaign preview available. msg.info.playerBooted = {0} has been disconnected. msg.info.playerConnected = {0} has connected. msg.info.playerDisconnected = {0} is disconnected. +msg.info.playerFinishedLoadingZone = {0} has finsihed loading into zone {1}. msg.info.restoreLayout = Restore layout msg.info.restoreLayout.description = Restore the MapTool user interface to the default layout. msg.info.screenshotSaved = Saved screenshot. From 541bb4948931349a407997aaab6b3d5278f74fc7 Mon Sep 17 00:00:00 2001 From: sauliuskarmanovas <38034030+sauliuskarmanovas@users.noreply.github.com> Date: Tue, 4 Apr 2023 23:23:11 +0300 Subject: [PATCH 2/5] Show players current zone and loading status in connections window --- .../maptool/client/ClientMessageHandler.java | 25 +++++++++++ .../client/ServerCommandClientImpl.java | 11 +++++ .../client/events/PlayerStatusChanged.java | 19 +++++++++ .../maptool/client/ui/MapToolFrame.java | 17 ++++++++ .../ui/connections/ClientConnectionPanel.java | 10 +++++ .../connections/PlayerListCellRenderer.java | 41 +++++++++++++++++++ .../maptool/client/ui/zone/ZoneRenderer.java | 26 ++++++------ .../rptools/maptool/model/player/Player.java | 32 ++++++++++++++- .../rptools/maptool/server/MapToolServer.java | 7 ++++ .../rptools/maptool/server/ServerCommand.java | 3 ++ .../maptool/server/ServerMessageHandler.java | 15 +++++++ src/main/proto/data_transfer_objects.proto | 2 + src/main/proto/message.proto | 1 + src/main/proto/message_types.proto | 6 +++ .../rptools/maptool/language/i18n.properties | 3 +- 15 files changed, 202 insertions(+), 16 deletions(-) create mode 100644 src/main/java/net/rptools/maptool/client/events/PlayerStatusChanged.java create mode 100644 src/main/java/net/rptools/maptool/client/ui/connections/PlayerListCellRenderer.java diff --git a/src/main/java/net/rptools/maptool/client/ClientMessageHandler.java b/src/main/java/net/rptools/maptool/client/ClientMessageHandler.java index a62716b928..20f8b2b18b 100644 --- a/src/main/java/net/rptools/maptool/client/ClientMessageHandler.java +++ b/src/main/java/net/rptools/maptool/client/ClientMessageHandler.java @@ -24,6 +24,7 @@ import javax.swing.SwingUtilities; import net.rptools.clientserver.simple.MessageHandler; import net.rptools.lib.MD5Key; +import net.rptools.maptool.client.events.PlayerStatusChanged; import net.rptools.maptool.client.functions.ExecFunction; import net.rptools.maptool.client.functions.MacroLinkFunction; import net.rptools.maptool.client.ui.MapToolFrame; @@ -159,6 +160,7 @@ public void handleMessage(String id, byte[] message) { case UPDATE_GM_MACROS_MSG -> handle(msg.getUpdateGmMacrosMsg()); case UPDATE_EXPOSED_AREA_META_MSG -> handle(msg.getUpdateExposedAreaMetaMsg()); case UPDATE_TOKEN_MOVE_MSG -> handle(msg.getUpdateTokenMoveMsg()); + case UPDATE_PLAYER_STATUS_MSG -> handle(msg.getUpdatePlayerStatusMsg()); default -> log.warn(msgType + "not handled."); } log.info(id + " handled: " + msgType); @@ -999,4 +1001,27 @@ private void handle(BootPlayerMsg bootPlayerMsg) { MapTool.showInformation("You have been booted from the server."); }); } + + private void handle(UpdatePlayerStatusMsg updatePlayerStatusMsg) { + var playerName = updatePlayerStatusMsg.getPlayer(); + var zoneGUID = GUID.valueOf(updatePlayerStatusMsg.getZoneGuid()); + var loaded = updatePlayerStatusMsg.getLoaded(); + + Player player = + MapTool.getPlayerList().stream() + .filter(x -> x.getName().equals(playerName)) + .findFirst() + .orElse(null); + + if (player == null) { + log.info("UpdatePlayerStatusMsg failed. No player with name: '" + playerName + "'"); + return; + } + + player.setZoneId(zoneGUID); + player.setLoaded(loaded); + + final var eventBus = new MapToolEventBus().getMainEventBus(); + eventBus.post(new PlayerStatusChanged(player)); + } } diff --git a/src/main/java/net/rptools/maptool/client/ServerCommandClientImpl.java b/src/main/java/net/rptools/maptool/client/ServerCommandClientImpl.java index 74c744d286..0f83ff82f1 100644 --- a/src/main/java/net/rptools/maptool/client/ServerCommandClientImpl.java +++ b/src/main/java/net/rptools/maptool/client/ServerCommandClientImpl.java @@ -35,6 +35,7 @@ import net.rptools.maptool.model.gamedata.proto.GameDataDto; import net.rptools.maptool.model.gamedata.proto.GameDataValueDto; import net.rptools.maptool.model.library.addon.TransferableAddOnLibrary; +import net.rptools.maptool.model.player.Player; import net.rptools.maptool.server.Mapper; import net.rptools.maptool.server.ServerCommand; import net.rptools.maptool.server.ServerMessageHandler; @@ -788,6 +789,16 @@ public void updateTokenProperty( TokenPropertyValueDto.newBuilder().setDoubleValue(value2.doubleValue()).build()); } + @Override + public void updatePlayerStatus(Player player) { + var msg = + UpdatePlayerStatusMsg.newBuilder() + .setPlayer(player.getName()) + .setZoneGuid(player.getZoneId().toString()) + .setLoaded(player.getLoaded()); + makeServerCall(Message.newBuilder().setUpdatePlayerStatusMsg(msg).build()); + } + /** * Some events become obsolete very quickly, such as dragging a token around. This queue always * has exactly one element, the more current version of the event. The event is then dispatched at diff --git a/src/main/java/net/rptools/maptool/client/events/PlayerStatusChanged.java b/src/main/java/net/rptools/maptool/client/events/PlayerStatusChanged.java new file mode 100644 index 0000000000..a76b45709a --- /dev/null +++ b/src/main/java/net/rptools/maptool/client/events/PlayerStatusChanged.java @@ -0,0 +1,19 @@ +/* + * This software Copyright by the RPTools.net development team, and + * licensed under the Affero GPL Version 3 or, at your option, any later + * version. + * + * MapTool Source Code is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public + * License * along with this source Code. If not, please visit + * and specifically the Affero license + * text at . + */ +package net.rptools.maptool.client.events; + +import net.rptools.maptool.model.player.Player; + +public record PlayerStatusChanged(Player player) {} diff --git a/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java b/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java index 826d193ea3..db387c6b6d 100644 --- a/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java +++ b/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java @@ -42,6 +42,7 @@ import net.rptools.lib.MD5Key; import net.rptools.maptool.client.*; import net.rptools.maptool.client.AppActions.ClientAction; +import net.rptools.maptool.client.events.PlayerStatusChanged; import net.rptools.maptool.client.events.ZoneActivated; import net.rptools.maptool.client.events.ZoneDeactivated; import net.rptools.maptool.client.swing.AboutDialog; @@ -1511,6 +1512,21 @@ private void stopTokenDrag() { } } + /** + * Changes the player status to loading given Zone and dispatches event and messages to server + * + * @param zone Zone that the player started to load + */ + private void updatePlayerStatus(Zone zone) { + var player = MapTool.getPlayer(); + player.setZoneId(zone.getId()); + player.setLoaded(false); + + var eventBus = new MapToolEventBus().getMainEventBus(); + eventBus.post(new PlayerStatusChanged(player)); + MapTool.serverCommand().updatePlayerStatus(player); + } + /** * Set the current ZoneRenderer * @@ -1519,6 +1535,7 @@ private void stopTokenDrag() { public void setCurrentZoneRenderer(ZoneRenderer renderer) { // Flush first so that the new zone renderer can inject the newly needed images if (renderer != null) { + updatePlayerStatus(renderer.getZone()); ImageManager.flush(renderer.getZone().getAllAssetIds()); } else { ImageManager.flush(); diff --git a/src/main/java/net/rptools/maptool/client/ui/connections/ClientConnectionPanel.java b/src/main/java/net/rptools/maptool/client/ui/connections/ClientConnectionPanel.java index 4db2b6b98a..3a2638b04d 100644 --- a/src/main/java/net/rptools/maptool/client/ui/connections/ClientConnectionPanel.java +++ b/src/main/java/net/rptools/maptool/client/ui/connections/ClientConnectionPanel.java @@ -32,6 +32,7 @@ import net.rptools.maptool.client.AppActions; import net.rptools.maptool.client.events.PlayerConnected; import net.rptools.maptool.client.events.PlayerDisconnected; +import net.rptools.maptool.client.events.PlayerStatusChanged; import net.rptools.maptool.client.events.ServerStopped; import net.rptools.maptool.client.swing.PopupListener; import net.rptools.maptool.events.MapToolEventBus; @@ -81,6 +82,7 @@ public ClientConnectionPanel() { listModel = new DefaultListModel<>(); list.setModel(listModel); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.setCellRenderer(new PlayerListCellRenderer()); list.addMouseListener(createPopupListener()); @@ -110,6 +112,14 @@ private void onPlayerConnected(PlayerConnected event) { listModel.addElement(event.player()); } + @Subscribe + private void onPlayerStatusChanged(PlayerStatusChanged event) { + var index = listModel.indexOf(event.player()); + if (index != -1) { + listModel.set(index, event.player()); + } + } + @Subscribe private void onPlayerDisconnected(PlayerDisconnected event) { listModel.removeElement(event.player()); diff --git a/src/main/java/net/rptools/maptool/client/ui/connections/PlayerListCellRenderer.java b/src/main/java/net/rptools/maptool/client/ui/connections/PlayerListCellRenderer.java new file mode 100644 index 0000000000..65ff110126 --- /dev/null +++ b/src/main/java/net/rptools/maptool/client/ui/connections/PlayerListCellRenderer.java @@ -0,0 +1,41 @@ +/* + * This software Copyright by the RPTools.net development team, and + * licensed under the Affero GPL Version 3 or, at your option, any later + * version. + * + * MapTool Source Code is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public + * License * along with this source Code. If not, please visit + * and specifically the Affero license + * text at . + */ +package net.rptools.maptool.client.ui.connections; + +import java.awt.Component; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import net.rptools.maptool.client.MapTool; +import net.rptools.maptool.language.I18N; +import net.rptools.maptool.model.player.Player; + +public class PlayerListCellRenderer extends DefaultListCellRenderer { + @Override + public Component getListCellRendererComponent( + JList list, Object value, int index, boolean isSelected, boolean hasFocus) { + if (value instanceof Player player) { + var zone = + player.getZoneId() == null ? null : MapTool.getCampaign().getZone(player.getZoneId()); + + String text = + I18N.getText( + player.getLoaded() ? "connections.playerIsInZone" : "connections.playerIsLoadingZone", + player.toString(), + zone == null ? null : zone.getDisplayName()); + return super.getListCellRendererComponent(list, text, index, isSelected, hasFocus); + } + return super.getListCellRendererComponent(list, value, index, isSelected, hasFocus); + } +} diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java b/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java index 23ce71b772..6572781e1e 100644 --- a/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java +++ b/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java @@ -40,6 +40,7 @@ import net.rptools.lib.CodeTimer; import net.rptools.lib.MD5Key; import net.rptools.maptool.client.*; +import net.rptools.maptool.client.events.PlayerStatusChanged; import net.rptools.maptool.client.functions.TokenMoveFunctions; import net.rptools.maptool.client.swing.ImageBorder; import net.rptools.maptool.client.swing.ImageLabel; @@ -72,7 +73,6 @@ import net.rptools.maptool.model.zones.*; import net.rptools.maptool.util.GraphicsUtil; import net.rptools.maptool.util.ImageManager; -import net.rptools.maptool.util.MessageUtil; import net.rptools.maptool.util.StringUtil; import net.rptools.maptool.util.TokenUtil; import net.rptools.parser.ParserException; @@ -1966,23 +1966,21 @@ public boolean isLoading() { if (isLoaded) { // Notify the token tree that it should update MapTool.getFrame().updateTokenTree(); - - // If we're in a server send a message to GM that we're done loading - if (MapTool.getConnection() != null) { - String mesg = - MessageUtil.getFormattedSystemMsg( - I18N.getText( - "msg.info.playerFinishedLoadingZone", - MapTool.getPlayer().getName(), - zone.getDisplayName())); - - TextMessage msg = TextMessage.gm(null, mesg); - MapTool.addMessage(msg); - } + updatePlayerStatus(); } return !isLoaded; } + private void updatePlayerStatus() { + var player = MapTool.getPlayer(); + player.setZoneId(zone.getId()); + player.setLoaded(true); + + var eventBus = new MapToolEventBus().getMainEventBus(); + eventBus.post(new PlayerStatusChanged(player)); + MapTool.serverCommand().updatePlayerStatus(player); + } + protected void renderDrawableOverlay( Graphics g, DrawableRenderer renderer, PlayerView view, List drawnElements) { Rectangle viewport = diff --git a/src/main/java/net/rptools/maptool/model/player/Player.java b/src/main/java/net/rptools/maptool/model/player/Player.java index c48f089f29..e5c41bfbe5 100644 --- a/src/main/java/net/rptools/maptool/model/player/Player.java +++ b/src/main/java/net/rptools/maptool/model/player/Player.java @@ -15,6 +15,7 @@ package net.rptools.maptool.model.player; import net.rptools.maptool.language.I18N; +import net.rptools.maptool.model.GUID; import net.rptools.maptool.server.proto.PlayerDto; import net.rptools.maptool.util.cipher.CipherUtil; @@ -43,6 +44,8 @@ public String toString() { private String name; // Primary Key private String role; + private GUID zoneId; + private boolean loaded; private transient CipherUtil.Key password; private transient Role actualRole; @@ -55,6 +58,8 @@ public Player() { this.name = name; this.role = role.name(); this.password = password; + this.zoneId = null; + this.loaded = true; } protected void setRole(Role role) { @@ -62,6 +67,22 @@ protected void setRole(Role role) { actualRole = role; } + public GUID getZoneId() { + return zoneId; + } + + public void setZoneId(GUID zoneId) { + this.zoneId = zoneId; + } + + public boolean getLoaded() { + return loaded; + } + + public void setLoaded(boolean loaded) { + this.loaded = loaded; + } + @Override public boolean equals(Object obj) { if (!(obj instanceof Player)) { @@ -114,10 +135,19 @@ public static Player fromDto(PlayerDto dto) { var player = new Player(); player.name = dto.getName(); player.role = dto.getRole(); + player.zoneId = dto.getZoneGuid().equals("") ? null : GUID.valueOf(dto.getZoneGuid()); + player.loaded = dto.getLoaded(); + return player; } public PlayerDto toDto() { - return PlayerDto.newBuilder().setName(name).setRole(role).build(); + var builder = PlayerDto.newBuilder().setName(name).setRole(role).setLoaded(loaded); + + if (zoneId != null) { + builder.setZoneGuid(zoneId.toString()); + } + + return builder.build(); } } diff --git a/src/main/java/net/rptools/maptool/server/MapToolServer.java b/src/main/java/net/rptools/maptool/server/MapToolServer.java index 76695650ba..1adba157aa 100644 --- a/src/main/java/net/rptools/maptool/server/MapToolServer.java +++ b/src/main/java/net/rptools/maptool/server/MapToolServer.java @@ -31,6 +31,7 @@ import net.rptools.maptool.common.MapToolConstants; import net.rptools.maptool.language.I18N; import net.rptools.maptool.model.Campaign; +import net.rptools.maptool.model.GUID; import net.rptools.maptool.model.TextMessage; import net.rptools.maptool.model.player.PlayerDatabase; import net.rptools.maptool.model.player.PlayerDatabaseFactory; @@ -137,6 +138,12 @@ public boolean isPlayerConnected(String id) { return conn.getPlayer(id) != null; } + public void updatePlayerStatus(String playerName, GUID zoneId, boolean loaded) { + var player = conn.getPlayer(playerName); + player.setLoaded(loaded); + player.setZoneId(zoneId); + } + public void setCampaign(Campaign campaign) { // Don't allow null campaigns, but allow the campaign to be cleared out if (campaign == null) { diff --git a/src/main/java/net/rptools/maptool/server/ServerCommand.java b/src/main/java/net/rptools/maptool/server/ServerCommand.java index ab4d28d4cf..ae411df169 100644 --- a/src/main/java/net/rptools/maptool/server/ServerCommand.java +++ b/src/main/java/net/rptools/maptool/server/ServerCommand.java @@ -28,6 +28,7 @@ import net.rptools.maptool.model.gamedata.proto.GameDataDto; import net.rptools.maptool.model.gamedata.proto.GameDataValueDto; import net.rptools.maptool.model.library.addon.TransferableAddOnLibrary; +import net.rptools.maptool.model.player.Player; public interface ServerCommand { void bootPlayer(String player); @@ -228,4 +229,6 @@ void updateTokenProperty( void updateTokenProperty(Token token, Token.Update update, String value1, boolean value2); void updateTokenProperty(Token token, Token.Update update, String value, BigDecimal value2); + + void updatePlayerStatus(Player player); } diff --git a/src/main/java/net/rptools/maptool/server/ServerMessageHandler.java b/src/main/java/net/rptools/maptool/server/ServerMessageHandler.java index 8fd0d7d506..5153530f86 100644 --- a/src/main/java/net/rptools/maptool/server/ServerMessageHandler.java +++ b/src/main/java/net/rptools/maptool/server/ServerMessageHandler.java @@ -253,6 +253,11 @@ public void handleMessage(String id, byte[] message) { handle(msg.getUpdateExposedAreaMetaMsg()); sendToClients(id, msg); } + case UPDATE_PLAYER_STATUS_MSG -> { + handle(id, msg.getUpdatePlayerStatusMsg()); + sendToClients(id, msg); + } + default -> log.warn(msgType + "not handled."); } log.info("from " + id + " handled: " + msgType); @@ -575,6 +580,16 @@ private void handle(BootPlayerMsg bootPlayerMsg) { server.releaseClientConnection(server.getConnectionId(bootPlayerMsg.getPlayerName())); } + private void handle(String id, UpdatePlayerStatusMsg updatePlayerStatusMsg) { + var playerName = updatePlayerStatusMsg.getPlayer(); + var zoneId = + updatePlayerStatusMsg.getZoneGuid().equals("") + ? null + : GUID.valueOf(updatePlayerStatusMsg.getZoneGuid()); + var loaded = updatePlayerStatusMsg.getLoaded(); + server.updatePlayerStatus(playerName, zoneId, loaded); + } + private void sendToClients(String excludedId, Message message) { server.getConnection().broadcastMessage(new String[] {excludedId}, message); } diff --git a/src/main/proto/data_transfer_objects.proto b/src/main/proto/data_transfer_objects.proto index ee99389697..c47dfcd865 100644 --- a/src/main/proto/data_transfer_objects.proto +++ b/src/main/proto/data_transfer_objects.proto @@ -443,6 +443,8 @@ message TextMessageDto { message PlayerDto { string name = 1; string role = 2; + string zone_guid = 3; + bool loaded = 4; } enum AssetDtoType { diff --git a/src/main/proto/message.proto b/src/main/proto/message.proto index 5f348d1fa6..5deea9c19c 100644 --- a/src/main/proto/message.proto +++ b/src/main/proto/message.proto @@ -88,5 +88,6 @@ message Message { RemoveDataStoreMsg remove_data_store_msg = 71; RemoveDataNamespaceMsg remove_data_namespace_msg = 72; RemoveDataMsg remove_data_msg = 73; + UpdatePlayerStatusMsg update_player_status_msg = 74; } } diff --git a/src/main/proto/message_types.proto b/src/main/proto/message_types.proto index 452764efdf..d2e4c92345 100644 --- a/src/main/proto/message_types.proto +++ b/src/main/proto/message_types.proto @@ -376,4 +376,10 @@ message RemoveDataMsg { string type = 1; string namespace = 2; string name = 3; +} + +message UpdatePlayerStatusMsg { + string player = 1; + string zone_guid = 2; + bool loaded = 3; } \ No newline at end of file diff --git a/src/main/resources/net/rptools/maptool/language/i18n.properties b/src/main/resources/net/rptools/maptool/language/i18n.properties index fc29cada13..2a5636bd92 100644 --- a/src/main/resources/net/rptools/maptool/language/i18n.properties +++ b/src/main/resources/net/rptools/maptool/language/i18n.properties @@ -2122,7 +2122,6 @@ msg.info.noCampaignPreview = No campaign preview available. msg.info.playerBooted = {0} has been disconnected. msg.info.playerConnected = {0} has connected. msg.info.playerDisconnected = {0} is disconnected. -msg.info.playerFinishedLoadingZone = {0} has finsihed loading into zone {1}. msg.info.restoreLayout = Restore layout msg.info.restoreLayout.description = Restore the MapTool user interface to the default layout. msg.info.screenshotSaved = Saved screenshot. @@ -2195,6 +2194,8 @@ panel.Chat.description = Dockable chat window. panel.Connections = Connections connections.tab.connected = Connected connections.tab.pending = Pending +connections.playerIsInZone = {0} is in zone {1}. +connections.playerIsLoadingZone = {0} is loading zone {1}. pendingConnection.label.playerName = Name pendingConnection.label.pin = PIN pendingConnection.column.title = Players attempting to connect From 9c53b05576b15b6ba9b06b877fd79f17fe0a89c5 Mon Sep 17 00:00:00 2001 From: sauliuskarmanovas <38034030+sauliuskarmanovas@users.noreply.github.com> Date: Wed, 5 Apr 2023 19:07:16 +0300 Subject: [PATCH 3/5] Added to status bar a count of how many players are done loading --- .../client/swing/PlayersLoadingStatusBar.java | 101 ++++++++++++++++++ .../maptool/client/ui/MapToolFrame.java | 10 ++ .../maptool/client/ui/theme/Icons.java | 2 + .../client/ui/theme/RessourceManager.java | 4 + .../rptools/maptool/client/image/loading.png | Bin 0 -> 425 bytes .../rptools/maptool/language/i18n.properties | 7 +- 6 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 src/main/java/net/rptools/maptool/client/swing/PlayersLoadingStatusBar.java create mode 100644 src/main/resources/net/rptools/maptool/client/image/loading.png diff --git a/src/main/java/net/rptools/maptool/client/swing/PlayersLoadingStatusBar.java b/src/main/java/net/rptools/maptool/client/swing/PlayersLoadingStatusBar.java new file mode 100644 index 0000000000..e7ab249af9 --- /dev/null +++ b/src/main/java/net/rptools/maptool/client/swing/PlayersLoadingStatusBar.java @@ -0,0 +1,101 @@ +/* + * This software Copyright by the RPTools.net development team, and + * licensed under the Affero GPL Version 3 or, at your option, any later + * version. + * + * MapTool Source Code is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public + * License * along with this source Code. If not, please visit + * and specifically the Affero license + * text at . + */ +package net.rptools.maptool.client.swing; + +import com.google.common.eventbus.Subscribe; +import java.awt.Dimension; +import javax.swing.Icon; +import javax.swing.JLabel; +import net.rptools.maptool.client.MapTool; +import net.rptools.maptool.client.events.PlayerConnected; +import net.rptools.maptool.client.events.PlayerDisconnected; +import net.rptools.maptool.client.events.PlayerStatusChanged; +import net.rptools.maptool.client.events.ServerStopped; +import net.rptools.maptool.client.ui.theme.Icons; +import net.rptools.maptool.client.ui.theme.RessourceManager; +import net.rptools.maptool.events.MapToolEventBus; +import net.rptools.maptool.language.I18N; + +/** */ +public class PlayersLoadingStatusBar extends JLabel { + private static final Dimension minSize = new Dimension(60, 10); + private static Icon checkmarkIcon; + private static Icon loadingIcon; + + static { + checkmarkIcon = RessourceManager.getSmallIcon(Icons.STATUSBAR_PLAYERS_DONE_LOADING); + loadingIcon = RessourceManager.getSmallIcon(Icons.STATUSBAR_PLAYERS_LOADING); + } + + public PlayersLoadingStatusBar() { + refreshCount(); + new MapToolEventBus().getMainEventBus().register(this); + } + + private void refreshCount() { + var players = MapTool.getPlayerList(); + var total = players.size(); + var loaded = players.stream().filter(x -> x.getLoaded()).count(); + + String tooltip = I18N.getText("ConnectionStatusPanel.playersLoadedZone", loaded, total); + String text = loaded + "/" + total; + + if (total == loaded) { + setIcon(checkmarkIcon); + } else { + setIcon(loadingIcon); + } + this.setText(text); + this.setToolTipText(tooltip); + } + + /* + * (non-Javadoc) + * + * @see javax.swing.JComponent#getMinimumSize() + */ + public Dimension getMinimumSize() { + return minSize; + } + + /* + * (non-Javadoc) + * + * @see javax.swing.JComponent#getPreferredSize() + */ + public Dimension getPreferredSize() { + return getMinimumSize(); + } + + @Subscribe + private void onPlayerConnected(PlayerConnected event) { + refreshCount(); + } + + @Subscribe + private void onPlayerStatusChanged(PlayerStatusChanged event) { + refreshCount(); + } + + @Subscribe + private void onPlayerDisconnected(PlayerDisconnected event) { + refreshCount(); + } + + @Subscribe + private void onServerStopped(ServerStopped event) { + refreshCount(); + } +} diff --git a/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java b/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java index db387c6b6d..a6a4feb99f 100644 --- a/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java +++ b/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java @@ -54,6 +54,7 @@ import net.rptools.maptool.client.swing.ImageCacheStatusBar; import net.rptools.maptool.client.swing.ImageChooserDialog; import net.rptools.maptool.client.swing.MemoryStatusBar; +import net.rptools.maptool.client.swing.PlayersLoadingStatusBar; import net.rptools.maptool.client.swing.PositionalLayout; import net.rptools.maptool.client.swing.ProgressStatusBar; import net.rptools.maptool.client.swing.SpacerStatusBar; @@ -167,6 +168,7 @@ public class MapToolFrame extends DefaultDockableHolder implements WindowListene private AssetCacheStatusBar assetCacheStatusBar; private ImageCacheStatusBar imageCacheStatusBar; private AppHomeDiskSpaceStatusBar appHomeDiskSpaceStatusBar; + private PlayersLoadingStatusBar playersLoadingStatusBar; private ZoomStatusBar zoomStatusBar; private JLabel chatActionLabel; private boolean fullScreenToolsShown; @@ -389,6 +391,7 @@ public MapToolFrame(JMenuBar menuBar) { statusPanel.addPanel(getAppHomeDiskSpaceStatusBar()); statusPanel.addPanel(getCoordinateStatusBar()); statusPanel.addPanel(getZoomStatusBar()); + statusPanel.addPanel(getPlayersLoadingStatusBar()); statusPanel.addPanel(MemoryStatusBar.getInstance()); // statusPanel.addPanel(progressBar); statusPanel.addPanel(connectionStatusPanel); @@ -916,6 +919,13 @@ public void showControlPanel(JPanel... panels) { visibleControlPanel = layoutPanel; } + public PlayersLoadingStatusBar getPlayersLoadingStatusBar() { + if (playersLoadingStatusBar == null) { + playersLoadingStatusBar = new PlayersLoadingStatusBar(); + } + return playersLoadingStatusBar; + } + public ZoomStatusBar getZoomStatusBar() { if (zoomStatusBar == null) { zoomStatusBar = new ZoomStatusBar(); diff --git a/src/main/java/net/rptools/maptool/client/ui/theme/Icons.java b/src/main/java/net/rptools/maptool/client/ui/theme/Icons.java index 9d4b7bf217..5bd99e6141 100644 --- a/src/main/java/net/rptools/maptool/client/ui/theme/Icons.java +++ b/src/main/java/net/rptools/maptool/client/ui/theme/Icons.java @@ -102,6 +102,8 @@ public enum Icons { STATUSBAR_ASSET_CACHE, STATUSBAR_FREE_SPACE, STATUSBAR_IMAGE_CACHE, + STATUSBAR_PLAYERS_DONE_LOADING, + STATUSBAR_PLAYERS_LOADING, STATUSBAR_RECEIVE_OFF, STATUSBAR_RECEIVE_ON, STATUSBAR_SERVER_CONNECTED, diff --git a/src/main/java/net/rptools/maptool/client/ui/theme/RessourceManager.java b/src/main/java/net/rptools/maptool/client/ui/theme/RessourceManager.java index 154397c24a..a98db2f7b3 100644 --- a/src/main/java/net/rptools/maptool/client/ui/theme/RessourceManager.java +++ b/src/main/java/net/rptools/maptool/client/ui/theme/RessourceManager.java @@ -130,6 +130,8 @@ public class RessourceManager { put(Icons.STATUSBAR_ASSET_CACHE, IMAGE_DIR + "asset-status.png"); put(Icons.STATUSBAR_FREE_SPACE, IMAGE_DIR + "disk-space.png"); put(Icons.STATUSBAR_IMAGE_CACHE, IMAGE_DIR + "thumbnail-status.png"); + put(Icons.STATUSBAR_PLAYERS_DONE_LOADING, IMAGE_DIR + "currentIndicator.png"); + put(Icons.STATUSBAR_PLAYERS_LOADING, IMAGE_DIR + "loading.png"); put(Icons.STATUSBAR_RECEIVE_OFF, IMAGE_DIR + "activityOff.png"); put(Icons.STATUSBAR_RECEIVE_ON, IMAGE_DIR + "receiveOn.png"); put(Icons.STATUSBAR_SERVER_CONNECTED, IMAGE_DIR + "computer_on.png"); @@ -318,6 +320,8 @@ public class RessourceManager { put(Icons.STATUSBAR_ASSET_CACHE, ROD_ICONS + "bottom/Assets Cache.svg"); put(Icons.STATUSBAR_FREE_SPACE, ROD_ICONS + "bottom/Free Space.svg"); put(Icons.STATUSBAR_IMAGE_CACHE, ROD_ICONS + "bottom/Image Thumbs Cache.svg"); + put(Icons.STATUSBAR_PLAYERS_DONE_LOADING, ROD_ICONS + "misc/Select All Tokens.svg"); + put(Icons.STATUSBAR_PLAYERS_LOADING, ROD_ICONS + "bottom/Assets Cache.svg"); put(Icons.STATUSBAR_RECEIVE_OFF, ROD_ICONS + "bottom/Receive Data - Inactive.svg"); put(Icons.STATUSBAR_RECEIVE_ON, ROD_ICONS + "bottom/Receive Data - Active.svg"); put(Icons.STATUSBAR_SERVER_CONNECTED, ROD_ICONS + "bottom/Server Status - Connected.svg"); diff --git a/src/main/resources/net/rptools/maptool/client/image/loading.png b/src/main/resources/net/rptools/maptool/client/image/loading.png new file mode 100644 index 0000000000000000000000000000000000000000..6b9540e50e93bbc474c7bde4d90b9f70392ffe78 GIT binary patch literal 425 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6zM9{GlY#sL0X`wF z;tCe3R&h3Q-TwW%iuYY!a`(2Rfr?6`g?5W+(i)#dck+%tnJsCos~V=~)?`$=+R zhzqwS#^*XupKP^qyU+P6=~wSezjkk#g_ef1k$#wyMPZavTVcS)MNPiiMpYh;YsT0Xfqro) z3GxeO_)i%S)}ChwG|R)&#W6%;YH1%M7lQ%^bM3Wf|K+E-Wu@?O?S2-LGT{~TiQkF) z8+I}=y>gIcTlrhrh{>O|W&5goTeqKD=~NtL9#DP7bL$SncrgJ!UgsB=mVO1A$>8bg K=d#Wzp$P!Dy~T0> literal 0 HcmV?d00001 diff --git a/src/main/resources/net/rptools/maptool/language/i18n.properties b/src/main/resources/net/rptools/maptool/language/i18n.properties index 2a5636bd92..889da73515 100644 --- a/src/main/resources/net/rptools/maptool/language/i18n.properties +++ b/src/main/resources/net/rptools/maptool/language/i18n.properties @@ -227,9 +227,10 @@ ConnectionInfoDialog.address.external = External Address: ConnectionInfoDialog.port = Port: ConnectionInfoDialog.discovering = Discovering... -ConnectionStatusPanel.notConnected = Not connected -ConnectionStatusPanel.runningServer = Running a Server -ConnectionStatusPanel.serverConnected = Connected to Server +ConnectionStatusPanel.notConnected = Not connected +ConnectionStatusPanel.runningServer = Running a Server +ConnectionStatusPanel.playersLoadedZone = {0} out of {1} players have loaded their zone +ConnectionStatusPanel.serverConnected = Connected to Server CoordinateStatusBar.mapCoordinates = Map Coordinates From 2aa3397b068fb1b5d2b91191c65b76ba884a247c Mon Sep 17 00:00:00 2001 From: Saulius Karmanovas Date: Wed, 5 Apr 2023 22:42:19 +0300 Subject: [PATCH 4/5] Show more info in the tooltip of the player status indicator --- .../client/swing/PlayersLoadingStatusBar.java | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/rptools/maptool/client/swing/PlayersLoadingStatusBar.java b/src/main/java/net/rptools/maptool/client/swing/PlayersLoadingStatusBar.java index e7ab249af9..c84b81ce29 100644 --- a/src/main/java/net/rptools/maptool/client/swing/PlayersLoadingStatusBar.java +++ b/src/main/java/net/rptools/maptool/client/swing/PlayersLoadingStatusBar.java @@ -27,6 +27,7 @@ import net.rptools.maptool.client.ui.theme.RessourceManager; import net.rptools.maptool.events.MapToolEventBus; import net.rptools.maptool.language.I18N; +import net.rptools.maptool.model.player.Player; /** */ public class PlayersLoadingStatusBar extends JLabel { @@ -49,7 +50,29 @@ private void refreshCount() { var total = players.size(); var loaded = players.stream().filter(x -> x.getLoaded()).count(); - String tooltip = I18N.getText("ConnectionStatusPanel.playersLoadedZone", loaded, total); + var sb = + new StringBuilder(I18N.getText("ConnectionStatusPanel.playersLoadedZone", loaded, total)); + + var self = MapTool.getPlayer(); + + for (Player player : players) { + // The Player in the list is a seperate entity to the one from MapTool.getPlayer() + // So it doesn't have the correct status data. + if(player.getName().equals(self.getName())){ + player = self; + } + var zone = + player.getZoneId() == null ? null : MapTool.getCampaign().getZone(player.getZoneId()); + + var text = + I18N.getText( + player.getLoaded() ? "connections.playerIsInZone" : "connections.playerIsLoadingZone", + player.toString(), + zone == null ? null : zone.getDisplayName()); + sb.append("\n"); + sb.append(text); + } + String text = loaded + "/" + total; if (total == loaded) { @@ -58,7 +81,7 @@ private void refreshCount() { setIcon(loadingIcon); } this.setText(text); - this.setToolTipText(tooltip); + this.setToolTipText(sb.toString()); } /* From 22225ff236db5f202e8d0101f3ddbb27f68b08c6 Mon Sep 17 00:00:00 2001 From: sauliuskarmanovas <38034030+sauliuskarmanovas@users.noreply.github.com> Date: Thu, 20 Apr 2023 23:03:37 +0300 Subject: [PATCH 5/5] Added events and a listener for the player to react when the zone starts loading / loads --- .../net/rptools/maptool/client/MapTool.java | 3 + .../maptool/client/events/ZoneLoaded.java | 19 +++++ .../maptool/client/events/ZoneLoading.java | 19 +++++ .../client/swing/PlayersLoadingStatusBar.java | 6 +- .../maptool/client/ui/MapToolFrame.java | 20 +---- .../maptool/client/ui/zone/ZoneRenderer.java | 15 +--- .../model/player/PlayerZoneListener.java | 80 +++++++++++++++++++ 7 files changed, 130 insertions(+), 32 deletions(-) create mode 100644 src/main/java/net/rptools/maptool/client/events/ZoneLoaded.java create mode 100644 src/main/java/net/rptools/maptool/client/events/ZoneLoading.java create mode 100644 src/main/java/net/rptools/maptool/model/player/PlayerZoneListener.java diff --git a/src/main/java/net/rptools/maptool/client/MapTool.java b/src/main/java/net/rptools/maptool/client/MapTool.java index de1e40d7e5..e6ed632de2 100644 --- a/src/main/java/net/rptools/maptool/client/MapTool.java +++ b/src/main/java/net/rptools/maptool/client/MapTool.java @@ -92,6 +92,7 @@ import net.rptools.maptool.model.player.Player; import net.rptools.maptool.model.player.PlayerDatabase; import net.rptools.maptool.model.player.PlayerDatabaseFactory; +import net.rptools.maptool.model.player.PlayerZoneListener; import net.rptools.maptool.model.player.Players; import net.rptools.maptool.model.zones.TokensAdded; import net.rptools.maptool.model.zones.TokensRemoved; @@ -155,6 +156,7 @@ public class MapTool { private static List playerList; private static LocalPlayer player; + private static PlayerZoneListener playerZoneListener; private static MapToolConnection conn; private static ClientMessageHandler handler; @@ -668,6 +670,7 @@ private static void initialize() { try { player = new LocalPlayer("", Player.Role.GM, ServerConfig.getPersonalServerGMPassword()); + playerZoneListener = new PlayerZoneListener(); Campaign cmpgn = CampaignFactory.createBasicCampaign(); // This was previously being done in the server thread and didn't always get done // before the campaign was accessed by the postInitialize() method below. diff --git a/src/main/java/net/rptools/maptool/client/events/ZoneLoaded.java b/src/main/java/net/rptools/maptool/client/events/ZoneLoaded.java new file mode 100644 index 0000000000..7b2178c6da --- /dev/null +++ b/src/main/java/net/rptools/maptool/client/events/ZoneLoaded.java @@ -0,0 +1,19 @@ +/* + * This software Copyright by the RPTools.net development team, and + * licensed under the Affero GPL Version 3 or, at your option, any later + * version. + * + * MapTool Source Code is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public + * License * along with this source Code. If not, please visit + * and specifically the Affero license + * text at . + */ +package net.rptools.maptool.client.events; + +import net.rptools.maptool.model.Zone; + +public record ZoneLoaded(Zone zone) {} diff --git a/src/main/java/net/rptools/maptool/client/events/ZoneLoading.java b/src/main/java/net/rptools/maptool/client/events/ZoneLoading.java new file mode 100644 index 0000000000..10fd977f35 --- /dev/null +++ b/src/main/java/net/rptools/maptool/client/events/ZoneLoading.java @@ -0,0 +1,19 @@ +/* + * This software Copyright by the RPTools.net development team, and + * licensed under the Affero GPL Version 3 or, at your option, any later + * version. + * + * MapTool Source Code is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public + * License * along with this source Code. If not, please visit + * and specifically the Affero license + * text at . + */ +package net.rptools.maptool.client.events; + +import net.rptools.maptool.model.Zone; + +public record ZoneLoading(Zone zone) {} diff --git a/src/main/java/net/rptools/maptool/client/swing/PlayersLoadingStatusBar.java b/src/main/java/net/rptools/maptool/client/swing/PlayersLoadingStatusBar.java index c84b81ce29..70ddb6e92e 100644 --- a/src/main/java/net/rptools/maptool/client/swing/PlayersLoadingStatusBar.java +++ b/src/main/java/net/rptools/maptool/client/swing/PlayersLoadingStatusBar.java @@ -52,13 +52,13 @@ private void refreshCount() { var sb = new StringBuilder(I18N.getText("ConnectionStatusPanel.playersLoadedZone", loaded, total)); - + var self = MapTool.getPlayer(); for (Player player : players) { // The Player in the list is a seperate entity to the one from MapTool.getPlayer() - // So it doesn't have the correct status data. - if(player.getName().equals(self.getName())){ + // So it doesn't have the correct status data. + if (player.getName().equals(self.getName())) { player = self; } var zone = diff --git a/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java b/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java index a6a4feb99f..c398f3be41 100644 --- a/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java +++ b/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java @@ -42,9 +42,9 @@ import net.rptools.lib.MD5Key; import net.rptools.maptool.client.*; import net.rptools.maptool.client.AppActions.ClientAction; -import net.rptools.maptool.client.events.PlayerStatusChanged; import net.rptools.maptool.client.events.ZoneActivated; import net.rptools.maptool.client.events.ZoneDeactivated; +import net.rptools.maptool.client.events.ZoneLoading; import net.rptools.maptool.client.swing.AboutDialog; import net.rptools.maptool.client.swing.AppHomeDiskSpaceStatusBar; import net.rptools.maptool.client.swing.AssetCacheStatusBar; @@ -1522,21 +1522,6 @@ private void stopTokenDrag() { } } - /** - * Changes the player status to loading given Zone and dispatches event and messages to server - * - * @param zone Zone that the player started to load - */ - private void updatePlayerStatus(Zone zone) { - var player = MapTool.getPlayer(); - player.setZoneId(zone.getId()); - player.setLoaded(false); - - var eventBus = new MapToolEventBus().getMainEventBus(); - eventBus.post(new PlayerStatusChanged(player)); - MapTool.serverCommand().updatePlayerStatus(player); - } - /** * Set the current ZoneRenderer * @@ -1545,7 +1530,8 @@ private void updatePlayerStatus(Zone zone) { public void setCurrentZoneRenderer(ZoneRenderer renderer) { // Flush first so that the new zone renderer can inject the newly needed images if (renderer != null) { - updatePlayerStatus(renderer.getZone()); + new MapToolEventBus().getMainEventBus().post(new ZoneLoading(renderer.getZone())); + ImageManager.flush(renderer.getZone().getAllAssetIds()); } else { ImageManager.flush(); diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java b/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java index 6572781e1e..9f3494d0d4 100644 --- a/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java +++ b/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java @@ -40,7 +40,7 @@ import net.rptools.lib.CodeTimer; import net.rptools.lib.MD5Key; import net.rptools.maptool.client.*; -import net.rptools.maptool.client.events.PlayerStatusChanged; +import net.rptools.maptool.client.events.ZoneLoaded; import net.rptools.maptool.client.functions.TokenMoveFunctions; import net.rptools.maptool.client.swing.ImageBorder; import net.rptools.maptool.client.swing.ImageLabel; @@ -1966,21 +1966,12 @@ public boolean isLoading() { if (isLoaded) { // Notify the token tree that it should update MapTool.getFrame().updateTokenTree(); - updatePlayerStatus(); + + new MapToolEventBus().getMainEventBus().post(new ZoneLoaded(zone)); } return !isLoaded; } - private void updatePlayerStatus() { - var player = MapTool.getPlayer(); - player.setZoneId(zone.getId()); - player.setLoaded(true); - - var eventBus = new MapToolEventBus().getMainEventBus(); - eventBus.post(new PlayerStatusChanged(player)); - MapTool.serverCommand().updatePlayerStatus(player); - } - protected void renderDrawableOverlay( Graphics g, DrawableRenderer renderer, PlayerView view, List drawnElements) { Rectangle viewport = diff --git a/src/main/java/net/rptools/maptool/model/player/PlayerZoneListener.java b/src/main/java/net/rptools/maptool/model/player/PlayerZoneListener.java new file mode 100644 index 0000000000..df701f5cee --- /dev/null +++ b/src/main/java/net/rptools/maptool/model/player/PlayerZoneListener.java @@ -0,0 +1,80 @@ +/* + * This software Copyright by the RPTools.net development team, and + * licensed under the Affero GPL Version 3 or, at your option, any later + * version. + * + * MapTool Source Code is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public + * License * along with this source Code. If not, please visit + * and specifically the Affero license + * text at . + */ +package net.rptools.maptool.model.player; + +import com.google.common.eventbus.Subscribe; +import net.rptools.maptool.client.MapTool; +import net.rptools.maptool.client.events.PlayerStatusChanged; +import net.rptools.maptool.client.events.ZoneLoaded; +import net.rptools.maptool.client.events.ZoneLoading; +import net.rptools.maptool.events.MapToolEventBus; + +public class PlayerZoneListener { + public PlayerZoneListener() { + new MapToolEventBus().getMainEventBus().register(this); + } + + @Subscribe + public void OnZoneLoading(ZoneLoading event) { + var player = MapTool.getPlayer(); + player.setLoaded(false); + player.setZoneId(event.zone().getId()); + + // To keep everything tidy we're also updating the player entry + // in the player list since they are seperate entities + var playerListPlayer = + MapTool.getPlayerList().stream() + .filter(x -> x.getName().equals(player.getName())) + .findAny() + .orElse(null); + + // On startup when we start to load the grassland zone the player list is still empty so we skip + if (playerListPlayer != null) { + playerListPlayer.setLoaded(false); + playerListPlayer.setZoneId(event.zone().getId()); + } + + final var eventBus = new MapToolEventBus().getMainEventBus(); + eventBus.post(new PlayerStatusChanged(player)); + + MapTool.serverCommand().updatePlayerStatus(player); + } + + @Subscribe + public void OnZoneLoaded(ZoneLoaded event) { + var player = MapTool.getPlayer(); + player.setLoaded(true); + player.setZoneId(event.zone().getId()); + + // To keep everything tidy we're also updating the player entry + // in the player list since they are seperate entities + var playerListPlayer = + MapTool.getPlayerList().stream() + .filter(x -> x.getName().equals(player.getName())) + .findAny() + .orElse(null); + + // On startup when we load the grassland zone the player list is still empty so we skip this + if (playerListPlayer != null) { + playerListPlayer.setLoaded(true); + playerListPlayer.setZoneId(event.zone().getId()); + } + + final var eventBus = new MapToolEventBus().getMainEventBus(); + eventBus.post(new PlayerStatusChanged(player)); + + MapTool.serverCommand().updatePlayerStatus(player); + } +}