maptool icon indicating copy to clipboard operation
maptool copied to clipboard

[Bug]: NPE when clients mouse-off an NPC token they don't own

Open fishface60 opened this issue 1 year ago • 0 comments

Describe the Bug

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Cannot invoke "net.rptools.maptool.client.ui.htmlframe.HTMLOverlayManager.updateContents(String, boolean)" because "overlay" is null
	at net.rptools.maptool.client.ui.sheet.stats.StatSheet.lambda$clearContent$1([StatSheet.java:77](http://statsheet.java:77/))
	at com.sun.javafx.application.PlatformImpl.lambda$runLater$10([PlatformImpl.java:456](http://platformimpl.java:456/))
	at java.base/[java.security](http://java.security/).AccessController.doPrivileged(Unknown Source)
	at com.sun.javafx.application.PlatformImpl.lambda$runLater$11([PlatformImpl.java:455](http://platformimpl.java:455/))
	at [com.sun.glass](http://com.sun.glass/).ui.InvokeLaterDispatcher$[Future.run](http://future.run/)([InvokeLaterDispatcher.java:95](http://invokelaterdispatcher.java:95/))
	at [com.sun.glass](http://com.sun.glass/).ui.gtk.GtkApplication._runLoop(Native Method)
	at [com.sun.glass](http://com.sun.glass/).ui.gtk.GtkApplication.lambda$runLoop$11([GtkApplication.java:316](http://gtkapplication.java:316/))
	at java.base/[java.lang.Thread.run](http://java.lang.thread.run/)(Unknown Source)

To Reproduce

  1. Create a new campaign.
  2. Add an add-on with stat sheets.
  3. Place an NPC token
  4. Start a server
  5. Connect a player client to the server
  6. Have the player repeatedly mouse-over the NPC token and mouse-off again.

Expected Behaviour

No errors spammed to the client's logs

Screenshots

No response

MapTool Info

First observed in v1.14.3 but present in develop

Desktop

Ubuntu 24.04.1 LTS

Additional Context

This is probably sufficient to fix it.

diff --git a/src/main/java/net/rptools/maptool/client/ui/sheet/stats/StatSheet.java b/src/main/java/net/rptools/maptool/client/ui/sheet/stats/StatSheet.java
index 331e168ac..ed0a337ca 100644
--- a/src/main/java/net/rptools/maptool/client/ui/sheet/stats/StatSheet.java
+++ b/src/main/java/net/rptools/maptool/client/ui/sheet/stats/StatSheet.java
@@ -77,7 +78,9 @@ public void clearContent() {
               MapTool.getFrame()
                   .getOverlayPanel()
                   .getOverlay(AppConstants.INTERNAL_MAP_UNDER_POINTER_HTML_OVERLAY_NAME);
-          overlay.updateContents("", true);
+         if (overlay != null) {
+            overlay.updateContents("", true);
+         }
         });
   }
 }

The code path for the overlay being null is:

  1. When the player moved their mouse over the token the StatSheetListener onHoverEnter evaluated:

    if (MapTool.getPlayer().isGM()            
        || AppUtil.playerOwns(token)          
        || token.getType() != Type.NPC) {     
      statSheet.setContent(                   
          event.token(),                      
          ssManager.getStatSheetContent(ssId),
          ssRecord.entry(),                   
          ssProperties.location());           
    }                                         
    

    so while statSheet was not null it still didn't set the stat sheet, creating the overlay if it didn't already exist.

  2. When the player moved their mouse off the token StatSheetListener onHoverExit checked if the stat sheet was null, seeing that there was a stat sheet it proceeded to attempt to clear the stat sheet.

  3. Because the stat sheet was never created

    var overlay =
    MapTool.getFrame()
        .getOverlayPanel()
        .getOverlay(AppConstants.INTERNAL_MAP_UNDER_POINTER_HTML_OVERLAY_NAME);
    

    returns a null overlay.

fishface60 avatar Sep 30 '24 20:09 fishface60