Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show player loading status #3894

25 changes: 25 additions & 0 deletions src/main/java/net/rptools/maptool/client/ClientMessageHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
* <http://www.gnu.org/licenses/> and specifically the Affero license
* text at <http://www.gnu.org/licenses/agpl.html>.
*/
package net.rptools.maptool.client.events;

import net.rptools.maptool.model.player.Player;

public record PlayerStatusChanged(Player player) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* 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
* <http://www.gnu.org/licenses/> and specifically the Affero license
* text at <http://www.gnu.org/licenses/agpl.html>.
*/
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;
import net.rptools.maptool.model.player.Player;

/** */
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();

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) {
setIcon(checkmarkIcon);
} else {
setIcon(loadingIcon);
}
this.setText(text);
this.setToolTipText(sb.toString());
}

/*
* (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();
}
}
27 changes: 27 additions & 0 deletions src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -53,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;
Expand Down Expand Up @@ -166,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;
Expand Down Expand Up @@ -388,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);
Expand Down Expand Up @@ -915,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();
Expand Down Expand Up @@ -1511,6 +1522,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
*
Expand All @@ -1519,6 +1545,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());
sauliuskarmanovas marked this conversation as resolved.
Show resolved Hide resolved
ImageManager.flush(renderer.getZone().getAllAssetIds());
} else {
ImageManager.flush();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -81,6 +82,7 @@ public ClientConnectionPanel() {
listModel = new DefaultListModel<>();
list.setModel(listModel);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setCellRenderer(new PlayerListCellRenderer());

list.addMouseListener(createPopupListener());

Expand Down Expand Up @@ -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());
Expand Down
Original file line number Diff line number Diff line change
@@ -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
* <http://www.gnu.org/licenses/> and specifically the Affero license
* text at <http://www.gnu.org/licenses/agpl.html>.
*/
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);
}
}
2 changes: 2 additions & 0 deletions src/main/java/net/rptools/maptool/client/ui/theme/Icons.java
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand Down
Loading