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);
+ }
+}