WorldMapTracker class

Пакет: com.hypixel.hytale.server.core.universe.world

Файл: com/hypixel/hytale/server/core/universe/world/WorldMapTracker.java

implements: Tickable

Поля (107)

МодификаторыТипИмя
final HytaleLogger LOGGER
return
return
return
return
Ref var1
int var10
int var10
int var10
int var10
int var10
int var11
int var11
boolean var11
var11
long var11
long var12
CompletableFuture var13
CompletableFuture var14
int var15
int var16
String var2
EventBus var2
World var2
Store var2
List var2
var2
var2
UpdateWorldMap var2
World var2
UpdateWorldMapSettings var2
PermissionsModule var3
WorldMapManager var3
int var3
Store var3
Set var3
var3
Set var3
var3
Set var3
var3
Set var3
var3
WorldMapSettings var4
WorldMapTracker.ZoneDiscoveryInfo var4
List var4
var4
var4
int var4
List var4
var4
var4
Ref var4
Vector3d var4
int var5
var5
var5
Player var5
DiscoverZoneEvent.Display var5
List var5
var5
int var5
var5
List var5
var5
Player var5
int var5
int var5
Set var6
Vector3d var6
World var6
PlayerRef var6
int var6
var6
LongIterator var6
List var6
var6
var6
int var6
var6
PlayerRef var6
int var6
int var6
int var7
String var7
Box2D var7
LongIterator var7
long var7
List var7
var7
int var7
WorldMapConfig var7
int var7
int var7
int var8
int var8
int var8
long var8
int var8
var8
int var8
int var8
int var9
int var9
CompletableFuture var9
var9
int var9

Методы (69)

МодификаторыВозвратСигнатура
public record ZoneDiscoveryInforecord ZoneDiscoveryInfo(@Nonnull String zoneName, @Nonnull String regionName, boolean display, @Nullable String discoverySoundEventId, @Nullable String icon, boolean major, float duration, float fadeInDuration, float fadeOutDuration)
public void clearvoid clear()
public void clearChunksvoid clearChunks(@Nonnull LongSet var1)
public WorldMapTracker.ZoneDiscoveryInfo clonepublic WorldMapTracker.ZoneDiscoveryInfo clone()
public void copyFromvoid copyFrom(@Nonnull WorldMapTracker var1)
public boolean discoverZoneboolean discoverZone(@Nonnull World var1, @Nonnull String var2)
public boolean discoverZonesboolean discoverZones(@Nonnull World var1, @Nonnull Set<String> var2)
for for(Registration var2 : this.eventRegistrations)
for for(List var9 : var5)
for for(List var13 : var7)
for for(List var18 : var5)
abstract for for(int var9 = MathUtil.floor(var2.min.x)
abstract for for(int var10 = MathUtil.floor(var2.min.y)
public int getEffectiveViewRadiusint getEffectiveViewRadius(@Nonnull World var1)
private void handleGroupPermissionsChangedvoid handleGroupPermissionsChanged(@Nonnull GroupPermissionChangeEvent var1)
private boolean hasDiscoveredZoneboolean hasDiscoveredZone(@Nonnull String var1)
if if(!this.started)
if if(this.transformComponent == null)
if if(this.transformComponent == null)
if if(this.viewRadiusOverride != null)
if if(var7 != null)
if if(var8 != Integer.MIN_VALUE)
if if(var7 == null)
if if(this.updateTimer > 0.0F)
if if(this.sentViewRadius != var4)
if if(this.sentViewRadius > var4)
if if(this.sentViewRadius < var4)
if if(this.updateTimer > 0.0F)
if if(var4 == null)
if if(var6 < 10)
if if(var5 == null)
if if(var5 != null)
if if(var9 == null)
if if(var2 == null)
if if(var5 < var4)
if if(var6 == null)
if if(var8 < var10)
if if(var7 == null)
if if(var11)
if if(var7 != null)
if if(var4 == null)
if if(var6 < var8)
if if(var5 == null)
if if(var5 != null)
if if(var1 != null)
if if(var2 != null)
if if(var4 != null)
if if(this.player != null && this.transformComponent != null)
static boolean isAllowTeleportToCoordinatesboolean isAllowTeleportToCoordinates(@Nonnull PlayerRef var0, @Nonnull Player var1)
public boolean isAllowTeleportToMarkersboolean isAllowTeleportToMarkers(@Nonnull PlayerRef var1, @Nonnull Player var2)
private int loadImagesint loadImages(@Nonnull World var1, int var2, int var3, int var4, int var5)
private int loadWorldMapint loadWorldMap(@Nonnull World var1, @Nonnull Box2D var2, int var3)
private void onZoneDiscoveredvoid onZoneDiscovered(@Nonnull Ref<EntityStore> var1, @Nonnull WorldMapTracker.ZoneDiscoveryInfo var2, @Nonnull ComponentAccessor<EntityStore> var3)
private void processPendingReloadChunksvoid processPendingReloadChunks(@Nonnull World var1)
private void resendWorldMapSettingsvoid resendWorldMapSettings(@Nonnull UUID var1)
public void sendSettingsvoid sendSettings(@Nonnull World var1)
public void setPlayerMapFiltervoid setPlayerMapFilter(Predicate<PlayerRef> var1)
public void setPlayerUuidvoid setPlayerUuid(@Nonnull UUID var1)
public void setViewRadiusOverridevoid setViewRadiusOverride(@Nullable Integer var1)
public boolean shouldBeVisibleboolean shouldBeVisible(int var1, long var2)
static boolean shouldBeVisibleboolean shouldBeVisible(int var0, int var1, int var2, int var3, int var4)
abstract return shouldBeVisiblereturn shouldBeVisible(var1, var5, var6, var7, var8)
public boolean undiscoverZoneboolean undiscoverZone(@Nonnull World var1, @Nonnull String var2)
public boolean undiscoverZonesboolean undiscoverZones(@Nonnull World var1, @Nonnull Set<String> var2)
private void unloadImagesvoid unloadImages(int var1, int var2, int var3)
public void unregisterEventsvoid unregisterEvents()
public void updateCurrentZoneAndBiomevoid updateCurrentZoneAndBiome(@Nonnull Ref<EntityStore> var1, @Nullable WorldMapTracker.ZoneDiscoveryInfo var2, @Nullable String var3, @Nonnull ComponentAccessor<EntityStore> var4)
private void updateWorldMapvoid updateWorldMap(@Nonnull World var1, float var2, @Nonnull WorldMapSettings var3, int var4, int var5, int var6)
private void writeUpdatePacketvoid writeUpdatePacket(@Nullable List<MapChunk> var1)

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.server.core.universe.world;

class="kw">import com.hypixel.hytale.common.fastutil.HLongOpenHashSet;
class="kw">import com.hypixel.hytale.common.fastutil.HLongSet;
class="kw">import com.hypixel.hytale.common.thread.ticking.Tickable;
class="kw">import com.hypixel.hytale.common.util.CompletableFutureUtil;
class="kw">import com.hypixel.hytale.component.ComponentAccessor;
class="kw">import com.hypixel.hytale.component.Ref;
class="kw">import com.hypixel.hytale.component.Store;
class="kw">import com.hypixel.hytale.event.EventBus;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.math.iterator.CircleSpiralIterator;
class="kw">import com.hypixel.hytale.math.shape.Box2D;
class="kw">import com.hypixel.hytale.math.util.ChunkUtil;
class="kw">import com.hypixel.hytale.math.util.MathUtil;
class="kw">import com.hypixel.hytale.protocol.GameMode;
class="kw">import com.hypixel.hytale.protocol.NetworkChannel;
class="kw">import com.hypixel.hytale.protocol.SoundCategory;
class="kw">import com.hypixel.hytale.protocol.packets.worldmap.ClearWorldMap;
class="kw">import com.hypixel.hytale.protocol.packets.worldmap.MapChunk;
class="kw">import com.hypixel.hytale.protocol.packets.worldmap.MapImage;
class="kw">import com.hypixel.hytale.protocol.packets.worldmap.MapMarker;
class="kw">import com.hypixel.hytale.protocol.packets.worldmap.UpdateWorldMap;
class="kw">import com.hypixel.hytale.protocol.packets.worldmap.UpdateWorldMapSettings;
class="kw">import com.hypixel.hytale.registry.Registration;
class="kw">import com.hypixel.hytale.server.core.HytaleServer;
class="kw">import com.hypixel.hytale.server.core.Message;
class="kw">import com.hypixel.hytale.server.core.asset.type.gameplay.WorldMapConfig;
class="kw">import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent;
class="kw">import com.hypixel.hytale.server.core.entity.entities.Player;
class="kw">import com.hypixel.hytale.server.core.event.events.ecs.DiscoverZoneEvent;
class="kw">import com.hypixel.hytale.server.core.event.events.permissions.GroupPermissionChangeEvent;
class="kw">import com.hypixel.hytale.server.core.event.events.permissions.PlayerGroupEvent;
class="kw">import com.hypixel.hytale.server.core.event.events.permissions.PlayerPermissionChangeEvent;
class="kw">import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
class="kw">import com.hypixel.hytale.server.core.permissions.HytalePermissions;
class="kw">import com.hypixel.hytale.server.core.permissions.PermissionsModule;
class="kw">import com.hypixel.hytale.server.core.universe.PlayerRef;
class="kw">import com.hypixel.hytale.server.core.universe.Universe;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.WorldMapManager;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.WorldMapSettings;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.MapMarkerTracker;
class="kw">import com.hypixel.hytale.server.core.util.EventTitleUtil;
class="kw">import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
class="kw">import it.unimi.dsi.fastutil.longs.LongIterator;
class="kw">import it.unimi.dsi.fastutil.longs.LongSet;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectArrayList;
class="kw">import java.util.ArrayList;
class="kw">import java.util.HashSet;
class="kw">import java.util.List;
class="kw">import java.util.Map;
class="kw">import java.util.Set;
class="kw">import java.util.UUID;
class="kw">import java.util.concurrent.CompletableFuture;
class="kw">import java.util.concurrent.locks.ReentrantReadWriteLock;
class="kw">import java.util.function.Predicate;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import org.joml.Vector3d;

class="kw">public class WorldMapTracker class="kw">implements Tickable {
   class="kw">private class="kw">static class="kw">final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
   class="kw">public class="kw">static class="kw">final float UPDATE_SPEED = 1.0F;
   class="kw">public class="kw">static class="kw">final int EMPTY_UPDATE_WORLD_MAP_SIZE = 13;
   class="kw">private class="kw">static class="kw">final int EMPTY_MAP_CHUNK_SIZE = 10;
   class="kw">private class="kw">static class="kw">final int FULL_MAP_CHUNK_SIZE = 23;
   class="kw">public class="kw">static class="kw">final int MAX_IMAGE_GENERATION = 20;
   class="kw">public class="kw">static class="kw">final int MAX_FRAME = 2621440;
   class="kw">private class="kw">final Player player;
   class="kw">private class="kw">final CircleSpiralIterator spiralIterator = new CircleSpiralIterator();
   class="kw">private class="kw">final ReentrantReadWriteLock loadedLock = new ReentrantReadWriteLock();
   class="kw">private class="kw">final HLongSet loaded = new HLongOpenHashSet();
   class="kw">private class="kw">final HLongSet pendingReloadChunks = new HLongOpenHashSet();
   class="kw">private class="kw">final Long2ObjectOpenHashMap<CompletableFuture<MapImage>> pendingReloadFutures = new Long2ObjectOpenHashMap();
   class="kw">private class="kw">final MapMarkerTracker markerTracker;
   class="kw">private class="kw">final List<Registration> eventRegistrations = new ArrayList<>();
   @Nullable
   class="kw">private UUID playerUuid;
   class="kw">private float updateTimer;
   class="kw">private Integer viewRadiusOverride;
   class="kw">private boolean started;
   class="kw">private int sentViewRadius;
   class="kw">private int lastChunkX;
   class="kw">private int lastChunkZ;
   @Nullable
   class="kw">private String currentBiomeName;
   @Nullable
   class="kw">private WorldMapTracker.ZoneDiscoveryInfo currentZone;
   @Nullable
   class="kw">private TransformComponent transformComponent;

   class="kw">private void handleGroupPermissionsChanged(@Nonnull GroupPermissionChangeEvent var1) {
      String var2 = var1.getGroupName();
      PermissionsModule var3 = PermissionsModule.get();

      for (PlayerRef var5 : Universe.get().getPlayers()) {
         Set var6 = var3.getGroupsForUser(var5.getUuid());
         if (var6.contains(var2)) {
            this.resendWorldMapSettings(var5.getUuid());
         }
      }
   }

   class="kw">public WorldMapTracker(@Nonnull Player var1) {
      this.player = var1;
      this.markerTracker = new MapMarkerTracker(this);
      EventBus var2 = HytaleServer.get().getEventBus();
      this.eventRegistrations.add(var2.register(PlayerGroupEvent.Added.class, var1x -> this.resendWorldMapSettings(var1x.getPlayerUuid())));
      this.eventRegistrations.add(var2.register(PlayerGroupEvent.Removed.class, var1x -> this.resendWorldMapSettings(var1x.getPlayerUuid())));
      this.eventRegistrations
         .add(var2.register(PlayerPermissionChangeEvent.PermissionsAdded.class, var1x -> this.resendWorldMapSettings(var1x.getPlayerUuid())));
      this.eventRegistrations
         .add(var2.register(PlayerPermissionChangeEvent.PermissionsRemoved.class, var1x -> this.resendWorldMapSettings(var1x.getPlayerUuid())));
      this.eventRegistrations.add(var2.register(GroupPermissionChangeEvent.Added.class, this::handleGroupPermissionsChanged));
      this.eventRegistrations.add(var2.register(GroupPermissionChangeEvent.Removed.class, this::handleGroupPermissionsChanged));
   }

   class="kw">public void setPlayerUuid(@Nonnull UUID var1) {
      this.playerUuid = var1;
   }

   class="kw">public void unregisterEvents() {
      for (Registration var2 : this.eventRegistrations) {
         var2.unregister();
      }

      this.eventRegistrations.clear();
   }

   @Override
   class="kw">public void tick(float var1) {
      if (!this.started) {
         this.started = true;
         LOGGER.at(Level.INFO).log("Started Generating Map!");
      }

      World var2 = this.player.getWorld();
      if (var2 != null && this.player.getPlayerConnection().getChannel(NetworkChannel.WorldMap).isWritable()) {
         if (this.transformComponent == null) {
            this.transformComponent = CompletableFuture.<TransformComponent>supplyAsync(() -> {
               Ref var1 = this.player.getReference();
               if (var1 != null && var1.isValid()) {
                  Store var2 = var1.getStore();
                  class="kw">return var2.getComponent(var1, TransformComponent.getComponentType());
               } else {
                  class="kw">return null;
               }
            }, var2).join();
            if (this.transformComponent == null) {
               class="kw">return;
            }
         }

         WorldMapManager var3 = var2.getWorldMapManager();
         WorldMapSettings var4 = var3.getWorldMapSettings();
         int var5;
         if (this.viewRadiusOverride != null) {
            var5 = this.viewRadiusOverride;
         } else {
            var5 = var4.getViewRadius(this.player.getViewRadius());
         }

         Vector3d var6 = this.transformComponent.getPosition();
         int var7 = MathUtil.floor(var6.x());
         int var8 = MathUtil.floor(var6.z());
         int var9 = var7 >> 5;
         int var10 = var8 >> 5;
         if (var2.isCompassUpdating()) {
            this.markerTracker.updatePointsOfInterest(var1, var2, var5, var9, var10);
         }

         if (var3.isWorldMapEnabled()) {
            this.updateWorldMap(var2, var1, var4, var5, var9, var10);
         }
      }
   }

   class="kw">public void updateCurrentZoneAndBiome(
      @Nonnull Ref<EntityStore> var1, @Nullable WorldMapTracker.ZoneDiscoveryInfo var2, @Nullable String var3, @Nonnull ComponentAccessor<EntityStore> var4
   ) {
      this.currentBiomeName = var3;
      this.currentZone = var2;
      Player var5 = var4.getComponent(var1, Player.getComponentType());
      assert var5 != null;
      if (!var5.isWaitingForClientReady()) {
         World var6 = var4.getExternalData().getWorld();
         if (var2 != null && this.discoverZone(var6, var2.regionName())) {
            this.onZoneDiscovered(var1, var2, var4);
         }
      }
   }

   class="kw">private void onZoneDiscovered(@Nonnull Ref<EntityStore> var1, @Nonnull WorldMapTracker.ZoneDiscoveryInfo var2, @Nonnull ComponentAccessor<EntityStore> var3) {
      WorldMapTracker.ZoneDiscoveryInfo var4 = var2.clone();
      DiscoverZoneEvent.Display var5 = new DiscoverZoneEvent.Display(var4);
      var3.invoke(var1, var5);
      if (!var5.isCancelled() && var4.display()) {
         PlayerRef var6 = var3.getComponent(var1, PlayerRef.getComponentType());
         assert var6 != null;
         EventTitleUtil.showEventTitleToPlayer(
            var6,
            Message.translation(String.format("server.map.region.%s", var4.regionName())),
            Message.translation(String.format("server.map.zone.%s", var4.zoneName())),
            var4.major(),
            var4.icon(),
            var4.duration(),
            var4.fadeInDuration(),
            var4.fadeOutDuration()
         );
         String var7 = var4.discoverySoundEventId();
         if (var7 != null) {
            int var8 = SoundEvent.getAssetMap().getIndex(var7);
            if (var8 != Integer.MIN_VALUE) {
               SoundUtil.playSoundEvent2d(var1, var8, SoundCategory.UI, var3);
            }
         }
      }
   }

   class="kw">private void updateWorldMap(@Nonnull World var1, float var2, @Nonnull WorldMapSettings var3, int var4, int var5, int var6) {
      this.processPendingReloadChunks(var1);
      Box2D var7 = var3.getWorldMapArea();
      if (var7 == null) {
         int var8 = Math.abs(this.lastChunkX - var5);
         int var9 = Math.abs(this.lastChunkZ - var6);
         int var10 = var8 <= 0 && var9 <= 0 ? 0 : (int)Math.ceil(Math.sqrt(var8 * var8 + var9 * var9));
         this.sentViewRadius = Math.max(0, this.sentViewRadius - var10);
         this.lastChunkX = var5;
         this.lastChunkZ = var6;
         this.updateTimer -= var2;
         if (this.updateTimer > 0.0F) {
            class="kw">return;
         }

         if (this.sentViewRadius != var4) {
            if (this.sentViewRadius > var4) {
               this.sentViewRadius = var4;
            }

            this.unloadImages(var4, var5, var6);
            if (this.sentViewRadius < var4) {
               this.loadImages(var1, var4, var5, var6, 20);
            }
         } else {
            this.updateTimer = 1.0F;
         }
      } else {
         this.updateTimer -= var2;
         if (this.updateTimer > 0.0F) {
            class="kw">return;
         }

         this.loadWorldMap(var1, var7, 20);
      }
   }

   class="kw">private void unloadImages(int var1, int var2, int var3) {
      List var4 = null;
      List var5 = null;
      this.loadedLock.writeLock().lock();

      try {
         int var6 = 2621427;
         LongIterator var7 = this.loaded.iterator();

         while (var7.hasNext()) {
            long var8 = var7.nextLong();
            int var10 = ChunkUtil.xOfChunkIndex(var8);
            int var11 = ChunkUtil.zOfChunkIndex(var8);
            if (!shouldBeVisible(var1, var2, var3, var10, var11)) {
               if (var4 == null) {
                  var4 = new ObjectArrayList(var6 / 10);
               }

               var4.add(new MapChunk(var10, var11, null));
               var6 -= 10;
               var7.remove();
               if (var6 < 10) {
                  var6 = 2621427;
                  if (var5 == null) {
                     var5 = new ObjectArrayList(this.loaded.size() / (var6 / 10));
                  }

                  var5.add(var4);
                  var4 = new ObjectArrayList(var6 / 10);
               }
            }
         }

         if (var5 != null) {
            for (List var9 : var5) {
               this.writeUpdatePacket(var9);
            }
         }

         this.writeUpdatePacket(var4);
      } class="kw">finally {
         this.loadedLock.writeLock().unlock();
      }
   }

   class="kw">private void processPendingReloadChunks(@Nonnull World var1) {
      List var2 = null;
      this.loadedLock.writeLock().lock();

      try {
         if (!this.pendingReloadChunks.isEmpty()) {
            int var3 = MathUtil.fastFloor(32.0F * var1.getWorldMapManager().getWorldMapSettings().getImageScale());
            int var4 = 23 + 4 * var3 * var3;
            int var5 = 2621427;
            LongIterator var6 = this.pendingReloadChunks.iterator();

            while (var6.hasNext()) {
               long var7 = var6.nextLong();
               CompletableFuture var9 = (CompletableFuture<MapImage>)this.pendingReloadFutures.get(var7);
               if (var9 == null) {
                  var9 = var1.getWorldMapManager().getImageAsync(var7);
                  this.pendingReloadFutures.put(var7, var9);
               }

               if (var9.isDone()) {
                  var6.remove();
                  this.pendingReloadFutures.remove(var7);
                  if (var2 == null) {
                     var2 = new ObjectArrayList(var5 / var4);
                  }

                  int var10 = ChunkUtil.xOfChunkIndex(var7);
                  int var11 = ChunkUtil.zOfChunkIndex(var7);
                  var2.add(new MapChunk(var10, var11, var9.getNow(null)));
                  this.loaded.add(var7);
                  var5 -= var4;
                  if (var5 < var4) {
                     this.writeUpdatePacket(var2);
                     var2 = new ObjectArrayList(2621440 - 13 / var4);
                     var5 = 2621427;
                  }
               }
            }

            this.writeUpdatePacket(var2);
            class="kw">return;
         }
      } class="kw">finally {
         this.loadedLock.writeLock().unlock();
      }
   }

   class="kw">private int loadImages(@Nonnull World var1, int var2, int var3, int var4, int var5) {
      List var6 = null;
      List var7 = null;
      this.loadedLock.writeLock().lock();

      try {
         int var8 = 2621427;
         int var9 = MathUtil.fastFloor(32.0F * var1.getWorldMapManager().getWorldMapSettings().getImageScale());
         int var10 = 23 + 4 * var9 * var9;
         boolean var11 = true;
         this.spiralIterator.init(var3, var4, this.sentViewRadius, var2);

         while (var5 > 0 && this.spiralIterator.hasNext()) {
            long var12 = this.spiralIterator.next();
            if (!this.loaded.contains(var12)) {
               var11 = false;
               CompletableFuture var14 = var1.getWorldMapManager().getImageAsync(var12);
               if (!var14.isDone()) {
                  var5--;
               } else if (this.loaded.add(var12)) {
                  if (var6 == null) {
                     var6 = new ObjectArrayList(var8 / var10);
                  }

                  int var15 = ChunkUtil.xOfChunkIndex(var12);
                  int var16 = ChunkUtil.zOfChunkIndex(var12);
                  var6.add(new MapChunk(var15, var16, var14.getNow(null)));
                  var8 -= var10;
                  if (var8 < var10) {
                     var8 = 2621427;
                     if (var7 == null) {
                        var7 = new ObjectArrayList();
                     }

                     var7.add(var6);
                     var6 = new ObjectArrayList(var8 / var10);
                  }
               }
            } else if (var11) {
               this.sentViewRadius = this.spiralIterator.getCompletedRadius();
            }
         }

         if (var11) {
            this.sentViewRadius = this.spiralIterator.getCompletedRadius();
         }

         if (var7 != null) {
            for (List var13 : var7) {
               this.writeUpdatePacket(var13);
            }
         }

         this.writeUpdatePacket(var6);
      } class="kw">finally {
         this.loadedLock.writeLock().unlock();
      }

      class="kw">return var5;
   }

   class="kw">private int loadWorldMap(@Nonnull World var1, @Nonnull Box2D var2, int var3) {
      List var4 = null;
      List var5 = null;
      this.loadedLock.writeLock().lock();

      try {
         int var6 = 2621427;
         int var7 = MathUtil.fastFloor(32.0F * var1.getWorldMapManager().getWorldMapSettings().getImageScale());
         int var8 = 23 + 4 * var7 * var7;

         for (int var9 = MathUtil.floor(var2.min.x); var9 < MathUtil.ceil(var2.max.x) && var3 > 0; var9++) {
            for (int var10 = MathUtil.floor(var2.min.y); var10 < MathUtil.ceil(var2.max.y) && var3 > 0; var10++) {
               long var11 = ChunkUtil.indexChunk(var9, var10);
               if (!this.loaded.contains(var11)) {
                  CompletableFuture var13 = CompletableFutureUtil._catch(var1.getWorldMapManager().getImageAsync(var11));
                  if (!var13.isDone()) {
                     var3--;
                  } else {
                     if (var4 == null) {
                        var4 = new ObjectArrayList(var6 / var8);
                     }

                     var4.add(new MapChunk(var9, var10, var13.getNow(null)));
                     this.loaded.add(var11);
                     var6 -= var8;
                     if (var6 < var8) {
                        var6 = 2621427;
                        if (var5 == null) {
                           var5 = new ObjectArrayList(Math.max(var6 / var8, 1));
                        }

                        var5.add(var4);
                        var4 = new ObjectArrayList(var6 / var8);
                     }
                  }
               }
            }
         }
      } class="kw">finally {
         this.loadedLock.writeLock().unlock();
      }

      if (var5 != null) {
         for (List var18 : var5) {
            this.writeUpdatePacket(var18);
         }
      }

      this.writeUpdatePacket(var4);
      class="kw">return var3;
   }

   class="kw">private void writeUpdatePacket(@Nullable List<MapChunk> var1) {
      if (var1 != null) {
         UpdateWorldMap var2 = new UpdateWorldMap(var1.toArray(MapChunk[]::new), null, null);
         LOGGER.at(Level.FINE).log("Sending world map update to %s - %d chunks", this.player.getUuid(), var1.size());
         this.player.getPlayerConnection().write(var2);
      }
   }

   @Nonnull
   class="kw">public Map<String, MapMarker> getSentMarkers() {
      class="kw">return this.markerTracker.getSentMarkers();
   }

   @Nonnull
   class="kw">public Player getPlayer() {
      class="kw">return this.player;
   }

   @Nullable
   class="kw">public TransformComponent getTransformComponent() {
      class="kw">return this.transformComponent;
   }

   class="kw">public void clear() {
      this.loadedLock.writeLock().lock();

      try {
         this.loaded.clear();
         this.sentViewRadius = 0;
         this.markerTracker.getSentMarkers().clear();
      } class="kw">finally {
         this.loadedLock.writeLock().unlock();
      }

      this.player.getPlayerConnection().write(new ClearWorldMap());
   }

   class="kw">public void clearChunks(@Nonnull LongSet var1) {
      this.loadedLock.writeLock().lock();

      try {
         var1.forEach(var1x -> {
            this.loaded.remove(var1x);
            this.pendingReloadChunks.add(var1x);
            this.pendingReloadFutures.remove(var1x);
         });
      } class="kw">finally {
         this.loadedLock.writeLock().unlock();
      }

      this.updateTimer = 0.0F;
   }

   class="kw">private void resendWorldMapSettings(@Nonnull UUID var1) {
      if (var1.equals(this.playerUuid)) {
         World var2 = this.player.getWorld();
         if (var2 != null) {
            this.sendSettings(var2);
         }
      }
   }

   class="kw">public void sendSettings(@Nonnull World var1) {
      UpdateWorldMapSettings var2 = new UpdateWorldMapSettings(var1.getWorldMapManager().getWorldMapSettings().getSettingsPacket());
      var1.execute(() -> {
         Store var3 = var1.getEntityStore().getStore();
         Ref var4 = this.player.getReference();
         if (var4 != null) {
            Player var5 = var3.getComponent(var4, Player.getComponentType());
            assert var5 != null;
            PlayerRef var6 = var3.getComponent(var4, PlayerRef.getComponentType());
            assert var6 != null;
            var2.allowTeleportToCoordinates = isAllowTeleportToCoordinates(var6, var5);
            var2.allowTeleportToMarkers = this.isAllowTeleportToMarkers(var6, var5);
            WorldMapConfig var7 = var1.getGameplayConfig().getWorldMapConfig();
            var2.allowCreatingMapMarkers = var7.getUserMapMarkerConfig().isAllowCreatingMarkers();
            var2.allowShowOnMapToggle = var7.canTogglePlayersInMap();
            var2.allowCompassTrackingToggle = var7.canTrackPlayersInCompass();
            var2.allowRemovingOtherPlayersMarkers = var7.getUserMapMarkerConfig().isAllowDeleteOtherPlayersSharedMarkers();
            var6.getPacketHandler().write(var2);
         }
      });
   }

   class="kw">private boolean hasDiscoveredZone(@Nonnull String var1) {
      class="kw">return this.player.getPlayerConfigData().getDiscoveredZones().contains(var1);
   }

   class="kw">public boolean discoverZone(@Nonnull World var1, @Nonnull String var2) {
      Set var3 = this.player.getPlayerConfigData().getDiscoveredZones();
      if (!var3.contains(var2)) {
         var3 = new HashSet<>(var3);
         var3.add(var2);
         this.player.getPlayerConfigData().setDiscoveredZones(var3);
         this.sendSettings(var1);
         class="kw">return true;
      } else {
         class="kw">return false;
      }
   }

   class="kw">public boolean undiscoverZone(@Nonnull World var1, @Nonnull String var2) {
      Set var3 = this.player.getPlayerConfigData().getDiscoveredZones();
      if (var3.contains(var2)) {
         var3 = new HashSet<>(var3);
         var3.remove(var2);
         this.player.getPlayerConfigData().setDiscoveredZones(var3);
         this.sendSettings(var1);
         class="kw">return true;
      } else {
         class="kw">return false;
      }
   }

   class="kw">public boolean discoverZones(@Nonnull World var1, @Nonnull Set<String> var2) {
      Set var3 = this.player.getPlayerConfigData().getDiscoveredZones();
      if (!var3.containsAll(var2)) {
         var3 = new HashSet<>(var3);
         var3.addAll(var2);
         this.player.getPlayerConfigData().setDiscoveredZones(var3);
         this.sendSettings(var1);
         class="kw">return true;
      } else {
         class="kw">return false;
      }
   }

   class="kw">public boolean undiscoverZones(@Nonnull World var1, @Nonnull Set<String> var2) {
      Set var3 = this.player.getPlayerConfigData().getDiscoveredZones();
      if (var3.containsAll(var2)) {
         var3 = new HashSet<>(var3);
         var3.removeAll(var2);
         this.player.getPlayerConfigData().setDiscoveredZones(var3);
         this.sendSettings(var1);
         class="kw">return true;
      } else {
         class="kw">return false;
      }
   }

   class="kw">public class="kw">static boolean isAllowTeleportToCoordinates(@Nonnull PlayerRef var0, @Nonnull Player var1) {
      class="kw">return var0.hasPermission(HytalePermissions.WORLD_MAP_COORDINATE_TELEPORT) && var1.getGameMode() != GameMode.Adventure;
   }

   class="kw">public boolean isAllowTeleportToMarkers(@Nonnull PlayerRef var1, @Nonnull Player var2) {
      class="kw">return var1.hasPermission(HytalePermissions.WORLD_MAP_MARKER_TELEPORT) && var2.getGameMode() != GameMode.Adventure;
   }

   class="kw">public void setPlayerMapFilter(Predicate<PlayerRef> var1) {
      this.markerTracker.setPlayerMapFilter(var1);
   }

   @Nullable
   class="kw">public Integer getViewRadiusOverride() {
      class="kw">return this.viewRadiusOverride;
   }

   @Nullable
   class="kw">public String getCurrentBiomeName() {
      class="kw">return this.currentBiomeName;
   }

   @Nullable
   class="kw">public WorldMapTracker.ZoneDiscoveryInfo getCurrentZone() {
      class="kw">return this.currentZone;
   }

   class="kw">public void setViewRadiusOverride(@Nullable Integer var1) {
      this.viewRadiusOverride = var1;
      this.clear();
   }

   class="kw">public int getEffectiveViewRadius(@Nonnull World var1) {
      class="kw">return this.viewRadiusOverride != null
         ? this.viewRadiusOverride
         : var1.getWorldMapManager().getWorldMapSettings().getViewRadius(this.player.getViewRadius());
   }

   class="kw">public boolean shouldBeVisible(int var1, long var2) {
      if (this.player != null && this.transformComponent != null) {
         Vector3d var4 = this.transformComponent.getPosition();
         int var5 = MathUtil.floor(var4.x()) >> 5;
         int var6 = MathUtil.floor(var4.z()) >> 5;
         int var7 = ChunkUtil.xOfChunkIndex(var2);
         int var8 = ChunkUtil.zOfChunkIndex(var2);
         class="kw">return shouldBeVisible(var1, var5, var6, var7, var8);
      } else {
         class="kw">return false;
      }
   }

   class="kw">public void copyFrom(@Nonnull WorldMapTracker var1) {
      this.loadedLock.writeLock().lock();

      try {
         var1.loadedLock.readLock().lock();

         try {
            this.loaded.addAll(var1.loaded);
            this.markerTracker.copyFrom(var1.markerTracker);
         } class="kw">finally {
            var1.loadedLock.readLock().unlock();
         }
      } class="kw">finally {
         this.loadedLock.writeLock().unlock();
      }
   }

   class="kw">public class="kw">static boolean shouldBeVisible(int var0, int var1, int var2, int var3, int var4) {
      int var5 = Math.abs(var3 - var1);
      int var6 = Math.abs(var4 - var2);
      int var7 = var5 * var5 + var6 * var6;
      class="kw">return var7 <= var0 * var0;
   }

   class="kw">public record ZoneDiscoveryInfo(
      @Nonnull String zoneName,
      @Nonnull String regionName,
      boolean display,
      @Nullable String discoverySoundEventId,
      @Nullable String icon,
      boolean major,
      float duration,
      float fadeInDuration,
      float fadeOutDuration
   ) {
      class="kw">public ZoneDiscoveryInfo {
      }

      @Nonnull
      class="kw">public WorldMapTracker.ZoneDiscoveryInfo clone() {
         class="kw">return new WorldMapTracker.ZoneDiscoveryInfo(
            this.zoneName,
            this.regionName,
            this.display,
            this.discoverySoundEventId,
            this.icon,
            this.major,
            this.duration,
            this.fadeInDuration,
            this.fadeOutDuration
         );
      }
   }
}