@@ -428,19 +428,32 @@ public void activate(org.bukkit.entity.Entity entity) {
428428
429429 @ Override
430430 public void addEntityToWorld (org .bukkit .entity .Entity entity , SpawnReason custom , Consumer <Boolean > isAdded ) {
431+ boolean canvasPlayer = "Canvas" .equals (Bukkit .getName ()) && entity instanceof Player ;
431432 Runnable task = () -> {
432433 Entity handle = getHandle (entity );
433434 ServerLevel level = (ServerLevel ) handle .level ();
435+ ServerPlayer player = canvasPlayer ? (ServerPlayer ) handle : null ;
436+ Collection <Connection > regionConnections = player == null ? null : getCanvasRegionConnections (level );
437+ Connection connection = player == null ? null : getCanvasConnection (player );
438+ boolean addedConnection = regionConnections != null && connection != null
439+ && !regionConnections .contains (connection ) && regionConnections .add (connection );
434440 int viewDistance = -1 ;
435441 ChunkMap chunkMap = null ;
436442 if (entity instanceof Player ) {
437443 chunkMap = level .getChunkSource ().chunkMap ;
438444 viewDistance = chunkMap .serverViewDistance ;
439445 chunkMap .serverViewDistance = -1 ;
440446 }
441- boolean success = level .addFreshEntity (handle , custom );
442- if (chunkMap != null ) {
443- chunkMap .serverViewDistance = viewDistance ;
447+ boolean success ;
448+ try {
449+ success = level .addFreshEntity (handle , custom );
450+ } finally {
451+ if (addedConnection ) {
452+ regionConnections .remove (connection );
453+ }
454+ if (chunkMap != null ) {
455+ chunkMap .serverViewDistance = viewDistance ;
456+ }
444457 }
445458 isAdded .accept (success );
446459 };
@@ -453,6 +466,28 @@ public void addEntityToWorld(org.bukkit.entity.Entity entity, SpawnReason custom
453466 }
454467 }
455468
469+ private static Connection getCanvasConnection (ServerPlayer player ) {
470+ if (CANVAS_CONNECTION == null )
471+ return null ;
472+ try {
473+ return (Connection ) CANVAS_CONNECTION .invoke (player .connection );
474+ } catch (Throwable e ) {
475+ e .printStackTrace ();
476+ return null ;
477+ }
478+ }
479+
480+ private static Collection <Connection > getCanvasRegionConnections (ServerLevel level ) {
481+ if (CANVAS_CURRENT_WORLD_DATA == null || CANVAS_REGION_CONNECTIONS == null )
482+ return null ;
483+ try {
484+ return (Collection <Connection >) CANVAS_REGION_CONNECTIONS .invoke (CANVAS_CURRENT_WORLD_DATA .invoke (level ));
485+ } catch (Throwable e ) {
486+ e .printStackTrace ();
487+ return null ;
488+ }
489+ }
490+
456491 @ Override
457492 public void addOrRemoveFromPlayerList (org .bukkit .entity .Entity entity , boolean remove ) {
458493 if (entity == null )
@@ -2941,6 +2976,13 @@ public <U> void acceptEmpty(MemoryModuleType<U> type) {
29412976 private static final MethodHandle BRAIN_SENSORS_GETTER = NMS .getGetter (Brain .class , "sensors" );
29422977 private static final MethodHandle BRAIN_SETTER = NMS .getFirstSetter (LivingEntity .class , Brain .class );
29432978 private static final MethodHandle BUKKITENTITY_FIELD_SETTER = NMS .getSetter (Entity .class , "bukkitEntity" );
2979+ private static final MethodHandle CANVAS_CONNECTION = "Canvas" .equals (Bukkit .getName ())
2980+ ? NMS .getGetter (ServerGamePacketListenerImpl .class .getSuperclass (), "connection" , false )
2981+ : null ;
2982+ private static final MethodHandle CANVAS_CURRENT_WORLD_DATA = "Canvas" .equals (Bukkit .getName ())
2983+ ? NMS .getMethodHandle (Level .class , "getCurrentWorldData" , false )
2984+ : null ;
2985+ private static final MethodHandle CANVAS_REGION_CONNECTIONS = loadCanvasRegionConnectionsGetter ();
29442986 private static final MethodHandle CHUNKMAP_UPDATE_PLAYER_STATUS = NMS .getMethodHandle (ChunkMap .class ,
29452987 "updatePlayerStatus" , true , ServerPlayer .class , boolean .class );
29462988 private static final MethodHandle CLIENT_LOADED_TIMEOUT_TIMER = NMS .getSetter (ServerGamePacketListenerImpl .class ,
@@ -3032,6 +3074,17 @@ public <U> void acceptEmpty(MemoryModuleType<U> type) {
30323074 public static final MethodHandle WAITING_FOR_RESPAWN = NMS .getSetter (ServerGamePacketListenerImpl .class ,
30333075 "waitingForRespawn" );
30343076
3077+ private static MethodHandle loadCanvasRegionConnectionsGetter () {
3078+ if (!"Canvas" .equals (Bukkit .getName ()))
3079+ return null ;
3080+ try {
3081+ return NMS .getGetter (Class .forName ("io.papermc.paper.threadedregions.RegionizedWorldData" ), "connections" ,
3082+ false );
3083+ } catch (ClassNotFoundException e ) {
3084+ return null ;
3085+ }
3086+ }
3087+
30353088 static {
30363089 if (NMS .getMethodHandle (CraftBlock .class , "getNMS" , false ) != null ) {
30373090 GET_BLOCK_STATE = NMS .getMethodHandle (CraftBlock .class , "getNMS" , false );
0 commit comments