WorldMapManager class

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

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

extends: TickingThread

Поля (71)

МодификаторыТипИмя
CodecMapCodec<WorldMapManager.MarkerReference> CODEC
public static final BuilderCodec<WorldMapManager.PlayerMarkerReference> CODEC
final int IMAGE_KEEP_ALIVE
private final MapImage image
private final AtomicInteger keepAlive
private String markerId
private UUID player
Long2ObjectOpenHashMap var1
ObjectIterator var1
int var1
PlayerRef var1
UserMapMarker var10
UserMarkerValidator.RemoveResult var10
Store var13
UserMapMarkersStore var14
DisplayNameComponent var15
boolean var2
WorldMapSettings var2
ObjectIterator var2
List var2
boolean var2
Player var2
PlayerConfigData var2
Player var2
int var3
var3
var3
var3
Entry var3
ObjectIterator var3
LongSet var3
WorldMapManager.ImageEntry var3
WorldMapManager.ImageEntry var3
Ref var3
Ref var3
CompletableFuture var3
String var3
var3
PlayerConfigData var3
PlayerWorldData var3
int var4
var4
var4
LongSet var4
Entry var4
int var4
CompletableFuture var4
UserMarkerValidator.PlaceResult var4
Store var4
PlayerWorldData var4
String var4
var4
ArrayList var4
WorldWorldMapConfig var5
int var5
long var5
CompletableFuture var5
World var5
UserMapMarker var5
ServerWorldMapConfig var6
int var6
CompletableFuture var6
Player var6
WorldMarkersResource var6
MapImage var7
PlayerWorldData var7
UserMapMarker var7
boolean var8
String var9
WorldMapManager.MarkerAndItsStore var9
private String world

Методы (64)

МодификаторыВозвратСигнатура
public ImageEntrypublic ImageEntry(MapImage var1)
private record MarkerAndItsStorerecord MarkerAndItsStore(UserMapMarker marker, UserMapMarkersStore store)
private PlayerMarkerReferenceprivate PlayerMarkerReference()
public PlayerMarkerReferencepublic PlayerMarkerReference(@Nonnull UUID var1, @Nonnull String var2, @Nonnull String var3)
public boolean addMarkerOverrideboolean addMarkerOverride(@Nonnull String var1, @Nonnull MapMarkerOverride var2)
public void addMarkerProvidervoid addMarkerProvider(@Nonnull String var1, @Nonnull WorldMapManager.MarkerProvider var2)
private void applyWorldMapOverridesvoid applyWorldMapOverrides(@Nonnull IWorldMap var1)
private void assertThreadvoid assertThread()
private void cancelQueuedGenerationsvoid cancelQueuedGenerations()
public void clearImagesvoid clearImages()
public void clearImagesInChunksvoid clearImagesInChunks(@Nonnull LongSet var1)
private void completeBatchvoid completeBatch(@Nonnull Long2ObjectOpenHashMap<CompletableFuture<MapImage>> var1, @Nullable WorldMap var2)
private void flushGenerationQueuevoid flushGenerationQueue()
for for(Player var5 : var0)
public void generatevoid generate()
public String getMarkerIdpublic String getMarkerId()
abstract String getMarkerIdString getMarkerId()
public Map<String, WorldMapManager.MarkerProvider> getMarkerProvidersMap<String, WorldMapManager.MarkerProvider> getMarkerProviders()
public UUID getPlayerpublic UUID getPlayer()
public Map<String, MapMarker> getPointsOfInterestMap<String, MapMarker> getPointsOfInterest()
public void handleUserCreateMarkervoid handleUserCreateMarker(PlayerRef var1, CreateUserMarker var2)
public void handleUserRemoveMarkervoid handleUserRemoveMarker(PlayerRef var1, RemoveMapMarker var2)
if if(this.generator != null)
if if(var1 != null)
if if(var5 != null)
if if(var3 > var4)
if if(this.unloadDelay <= 0.0F)
if if(var3x != null)
if if(var1 != 0)
if if(var4 > 0)
if if(var3 != null)
if if(var4 != null)
if if(var6 != null)
if if(var1 != var2)
if if(var2)
if if(var3 != null)
if if(var4 instanceof UserMarkerValidator.CanSpawn var5)
if if(var3 != null)
if if(!var8)
if if(var9 == null)
if if(var5 != null)
if if(var3 != null)
if if(var1 != null)
if if(var3 == null)
if if(var4 == null)
public boolean isWorldMapEnabledboolean isWorldMapEnabled()
static boolean isWorldMapImageVisibleToAnyPlayerboolean isWorldMapImageVisibleToAnyPlayer(@Nonnull List<Player> var0, long var1, @Nonnull WorldMapSettings var3)
public void removepublic void remove()
abstract void removevoid remove()
public void removeAllMarkerOverridesvoid removeAllMarkerOverrides()
private static void removeMarkerFromDataprivate static void removeMarkerFromData(@Nonnull PlayerConfigData var0, @Nonnull String var1, @Nonnull String var2)
abstract removeMarkerFromData removeMarkerFromData(var2, var3, this.markerId)
abstract removeMarkerFromData removeMarkerFromData(var3, var4, this.markerId)
private void removeMarkerFromOfflinePlayerprivate void removeMarkerFromOfflinePlayer()
private void removeMarkerFromOnlinePlayerprivate void removeMarkerFromOnlinePlayer(@Nonnull Player var1)
public boolean removeMarkerOverrideboolean removeMarkerOverride(@Nonnull String var1)
public boolean removeMarkerOverrideboolean removeMarkerOverride(@Nonnull String var1, @Nonnull MapMarkerOverride var2)
public void sendSettingsvoid sendSettings()
static void sendSettingsToAllWorldsvoid sendSettingsToAllWorlds()
public void setGeneratorvoid setGenerator(@Nullable IWorldMap var1)
public boolean shouldTickboolean shouldTick()
public void unloadImagesvoid unloadImages()
abstract void updatevoid update(@Nonnull World var1, @Nonnull Player var2, @Nonnull MarkersCollector var3)
public void updateTickingStatevoid updateTickingState(boolean var1)

Исходный код

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

class="kw">import com.hypixel.fastutil.longs.Long2ObjectConcurrentHashMap;
class="kw">import com.hypixel.hytale.codec.Codec;
class="kw">import com.hypixel.hytale.codec.KeyedCodec;
class="kw">import com.hypixel.hytale.codec.builder.BuilderCodec;
class="kw">import com.hypixel.hytale.codec.lookup.CodecMapCodec;
class="kw">import com.hypixel.hytale.common.util.CompletableFutureUtil;
class="kw">import com.hypixel.hytale.component.Ref;
class="kw">import com.hypixel.hytale.component.Store;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
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.Color;
class="kw">import com.hypixel.hytale.protocol.packets.player.RemoveMapMarker;
class="kw">import com.hypixel.hytale.protocol.packets.worldmap.CreateUserMarker;
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.server.core.HytaleServer;
class="kw">import com.hypixel.hytale.server.core.Message;
class="kw">import com.hypixel.hytale.server.core.config.ServerWorldMapConfig;
class="kw">import com.hypixel.hytale.server.core.config.WorldWorldMapConfig;
class="kw">import com.hypixel.hytale.server.core.entity.entities.Player;
class="kw">import com.hypixel.hytale.server.core.entity.entities.player.data.PlayerConfigData;
class="kw">import com.hypixel.hytale.server.core.entity.entities.player.data.PlayerWorldData;
class="kw">import com.hypixel.hytale.server.core.modules.entity.component.DisplayNameComponent;
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.World;
class="kw">import com.hypixel.hytale.server.core.universe.world.map.WorldMap;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.MapMarkerOverride;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.MarkersCollector;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.providers.DeathMarkerProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.providers.OtherPlayersMarkerProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.providers.POIMarkerProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.providers.PersonalMarkersProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.providers.RespawnMarkerProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.providers.SharedMarkersProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.providers.SpawnMarkerProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.user.UserMapMarker;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.user.UserMapMarkersStore;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.user.UserMarkerValidator;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.worldstore.WorldMarkersResource;
class="kw">import com.hypixel.hytale.server.core.util.thread.TickingThread;
class="kw">import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
class="kw">import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
class="kw">import it.unimi.dsi.fastutil.longs.LongSet;
class="kw">import it.unimi.dsi.fastutil.longs.LongSets;
class="kw">import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry;
class="kw">import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
class="kw">import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
class="kw">import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectIterator;
class="kw">import java.util.ArrayList;
class="kw">import java.util.List;
class="kw">import java.util.Map;
class="kw">import java.util.UUID;
class="kw">import java.util.concurrent.CompletableFuture;
class="kw">import java.util.concurrent.ConcurrentHashMap;
class="kw">import java.util.concurrent.atomic.AtomicInteger;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;

class="kw">public class WorldMapManager class="kw">extends TickingThread {
   class="kw">private class="kw">static class="kw">final int IMAGE_KEEP_ALIVE = 60;
   class="kw">private class="kw">static class="kw">final float DEFAULT_UNLOAD_DELAY = 1.0F;
   class="kw">private class="kw">static class="kw">final int MAX_GENERATIONS_PER_TICK = 64;
   @Nonnull
   class="kw">private class="kw">final HytaleLogger logger;
   @Nonnull
   class="kw">private class="kw">final World world;
   class="kw">private class="kw">final Long2ObjectConcurrentHashMap<WorldMapManager.ImageEntry> images = new Long2ObjectConcurrentHashMap<>(
      true, ChunkUtil.indexChunk(Integer.MIN_VALUE, Integer.MIN_VALUE)
   );
   class="kw">private class="kw">final Long2ObjectConcurrentHashMap<CompletableFuture<MapImage>> generating = new Long2ObjectConcurrentHashMap<>(
      true, ChunkUtil.indexChunk(Integer.MIN_VALUE, Integer.MIN_VALUE)
   );
   class="kw">private class="kw">final Long2ObjectConcurrentHashMap<CompletableFuture<MapImage>> generationQueue = new Long2ObjectConcurrentHashMap<>(
      true, ChunkUtil.indexChunk(Integer.MIN_VALUE, Integer.MIN_VALUE)
   );
   class="kw">private class="kw">final Map<String, WorldMapManager.MarkerProvider> markerProviders = new ConcurrentHashMap<>();
   class="kw">private class="kw">final Map<String, MapMarker> pointsOfInterest = new ConcurrentHashMap<>();
   class="kw">private class="kw">final Map<String, MapMarkerOverride> markerOverrides = new ConcurrentHashMap<>();
   class="kw">private class="kw">final Object2ObjectMap<String, MapMarkerOverride> markerOverridesLocal = new Object2ObjectOpenHashMap();
   class="kw">private class="kw">final Object2ObjectMap<String, MapMarkerOverride> markerOverridesLocalView = Object2ObjectMaps.unmodifiable(this.markerOverridesLocal);
   @Nonnull
   class="kw">private WorldMapSettings worldMapSettings = WorldMapSettings.DISABLED;
   @Nullable
   class="kw">private IWorldMap generator;
   @Nonnull
   class="kw">private CompletableFuture<Void> generatorLoaded = new CompletableFuture<>();
   class="kw">private float unloadDelay = 1.0F;

   class="kw">public WorldMapManager(@Nonnull World var1) {
      super("WorldMap - " + var1.getName(), 10, true);
      this.logger = HytaleLogger.get("World|" + var1.getName() + "|M");
      this.world = var1;
      this.addMarkerProvider("spawn", SpawnMarkerProvider.INSTANCE);
      this.addMarkerProvider("playerIcons", OtherPlayersMarkerProvider.INSTANCE);
      this.addMarkerProvider("death", DeathMarkerProvider.INSTANCE);
      this.addMarkerProvider("respawn", RespawnMarkerProvider.INSTANCE);
      this.addMarkerProvider("personal", PersonalMarkersProvider.INSTANCE);
      this.addMarkerProvider("shared", SharedMarkersProvider.INSTANCE);
      this.addMarkerProvider("poi", POIMarkerProvider.INSTANCE);
   }

   @Nullable
   class="kw">public IWorldMap getGenerator() {
      class="kw">return this.generator;
   }

   class="kw">public void setGenerator(@Nullable IWorldMap var1) {
      boolean var2 = this.shouldTick();
      if (this.generator != null) {
         this.generator.shutdown();
      }

      this.generator = var1;
      if (var1 != null) {
         this.logger.at(Level.INFO).log("Initializing world map generator: %s", var1.toString());
         this.generatorLoaded.complete(null);
         this.generatorLoaded = new CompletableFuture<>();
         this.applyWorldMapOverrides(var1);
         this.images.clear();
         this.generating.clear();
         this.cancelQueuedGenerations();

         for (Player var4 : this.world.getPlayers()) {
            var4.getWorldMapTracker().clear();
         }

         this.updateTickingState(var2);
         this.sendSettings();
         this.logger.at(Level.INFO).log("Generating Points of Interest...");
         CompletableFutureUtil._catch(var1.generatePointsOfInterest(this.world).thenAcceptAsync(var1x -> {
            this.pointsOfInterest.putAll((Map<? class="kw">extends String, ? class="kw">extends MapMarker>)var1x);
            this.logger.at(Level.INFO).log("Finished Generating Points of Interest!");
         }));
      } else {
         this.logger.at(Level.INFO).log("World map disabled!");
         this.worldMapSettings = WorldMapSettings.DISABLED;
         this.sendSettings();
      }
   }

   class="kw">private void applyWorldMapOverrides(@Nonnull IWorldMap var1) {
      WorldMapSettings var2 = var1.getWorldMapSettings();
      int var3 = var2.getViewRadiusMin();
      int var4 = var2.getViewRadiusMax();
      WorldWorldMapConfig var5 = this.world.getWorldConfig().getWorldMapConfig();
      if (var5 != null) {
         var3 = var5.getViewRadiusMin();
         var4 = var5.getViewRadiusMax();
      }

      ServerWorldMapConfig var6 = HytaleServer.get().getConfig().getWorldMapConfig();
      var3 = Math.max(var3, var6.getViewRadiusMin());
      var4 = Math.min(var4, var6.getViewRadiusMax());
      if (var3 > var4) {
         var3 = var4;
      }

      this.worldMapSettings = var2.withViewRadiusLimits(var3, var4);
   }

   @Override
   class="kw">protected boolean isIdle() {
      class="kw">return this.world.getPlayerCount() == 0;
   }

   @Override
   class="kw">protected void tick(float var1) {
      this.markerOverridesLocal.clear();
      this.markerOverridesLocal.putAll(this.markerOverrides);

      for (Player var3 : this.world.getPlayers()) {
         var3.getWorldMapTracker().tick(var1);
      }

      this.flushGenerationQueue();
      this.unloadDelay -= var1;
      if (this.unloadDelay <= 0.0F) {
         this.unloadDelay = 1.0F;
         this.unloadImages();
      }
   }

   @Override
   class="kw">protected void onShutdown() {
   }

   class="kw">private void flushGenerationQueue() {
      if (this.generator != null && !this.generationQueue.isEmpty()) {
         Long2ObjectOpenHashMap var1 = new Long2ObjectOpenHashMap(64);
         ObjectIterator var2 = this.generationQueue.long2ObjectEntrySet().iterator();

         while (var2.hasNext() && var1.size() < 64) {
            Entry var3 = (Entry<CompletableFuture<MapImage>>)var2.next();
            var1.put(var3.getLongKey(), (CompletableFuture)var3.getValue());
            var2.remove();
         }

         if (!var1.isEmpty()) {
            int var5 = MathUtil.fastFloor(32.0F * this.worldMapSettings.getImageScale());
            LongSet var4 = LongSets.unmodifiable(new LongOpenHashSet(var1.keySet()));
            this.generator.generate(this.world, var5, var5, var4).handle((var2x, var3x) -> {
               if (var3x != null) {
                  ((HytaleLogger.Api)this.logger.at(Level.SEVERE).withCause(var3x)).log("World map generation batch failed");
               }

               this.completeBatch(var1, var3x != null ? null : var2x);
               class="kw">return null;
            });
         }
      }
   }

   class="kw">private void cancelQueuedGenerations() {
      ObjectIterator var1 = this.generationQueue.long2ObjectEntrySet().iterator();

      while (var1.hasNext()) {
         ((CompletableFuture)((Entry)var1.next()).getValue()).complete(null);
      }

      this.generationQueue.clear();
   }

   class="kw">private void completeBatch(@Nonnull Long2ObjectOpenHashMap<CompletableFuture<MapImage>> var1, @Nullable WorldMap var2) {
      ObjectIterator var3 = var1.long2ObjectEntrySet().iterator();

      while (var3.hasNext()) {
         Entry var4 = (Entry<CompletableFuture<MapImage>>)var3.next();
         long var5 = var4.getLongKey();
         MapImage var7 = var2 != null ? (MapImage)var2.getChunks().get(var5) : null;
         if (this.generating.remove(var5) != null && var7 != null) {
            this.images.put(var5, new WorldMapManager.ImageEntry(var7));
         }

         ((CompletableFuture)var4.getValue()).complete(var7);
      }
   }

   class="kw">public void unloadImages() {
      int var1 = this.images.size();
      if (var1 != 0) {
         List var2 = this.world.getPlayers();
         LongSet var3 = new LongOpenHashSet();
         this.images.forEach((var3x, var5) -> {
            if (this.isWorldMapEnabled() && isWorldMapImageVisibleToAnyPlayer(var2, var3x, this.worldMapSettings)) {
               var5.keepAlive.set(60);
            } else {
               if (var5.keepAlive.decrementAndGet() <= 0) {
                  var3.add(var3x);
               }
            }
         });
         if (!var3.isEmpty()) {
            var3.forEach(var1x -> {
               this.logger.at(Level.FINE).log("Unloading world map image: %s", var1x);
               this.images.remove(var1x);
            });
         }

         int var4 = var3.size();
         if (var4 > 0) {
            this.logger.at(Level.FINE).log("Cleaned %s world map images from memory, with %s images remaining in memory.", var4, var1 - var4);
         }
      }
   }

   class="kw">public boolean isWorldMapEnabled() {
      class="kw">return this.worldMapSettings.getSettingsPacket().enabled;
   }

   class="kw">public class="kw">static boolean isWorldMapImageVisibleToAnyPlayer(@Nonnull List<Player> var0, long var1, @Nonnull WorldMapSettings var3) {
      for (Player var5 : var0) {
         int var6 = var3.getViewRadius(var5.getViewRadius());
         if (var5.getWorldMapTracker().shouldBeVisible(var6, var1)) {
            class="kw">return true;
         }
      }

      class="kw">return false;
   }

   @Nonnull
   class="kw">public World getWorld() {
      class="kw">return this.world;
   }

   @Nonnull
   class="kw">public WorldMapSettings getWorldMapSettings() {
      class="kw">return this.worldMapSettings;
   }

   class="kw">public Map<String, WorldMapManager.MarkerProvider> getMarkerProviders() {
      class="kw">return this.markerProviders;
   }

   class="kw">public void addMarkerProvider(@Nonnull String var1, @Nonnull WorldMapManager.MarkerProvider var2) {
      this.markerProviders.put(var1, var2);
   }

   class="kw">public Map<String, MapMarker> getPointsOfInterest() {
      class="kw">return this.pointsOfInterest;
   }

   @Nullable
   class="kw">public MapImage getImageIfInMemory(int var1, int var2) {
      class="kw">return this.getImageIfInMemory(ChunkUtil.indexChunk(var1, var2));
   }

   @Nullable
   class="kw">public MapImage getImageIfInMemory(long var1) {
      WorldMapManager.ImageEntry var3 = this.images.get(var1);
      class="kw">return var3 != null ? var3.image : null;
   }

   @Nonnull
   class="kw">public CompletableFuture<MapImage> getImageAsync(int var1, int var2) {
      class="kw">return this.getImageAsync(ChunkUtil.indexChunk(var1, var2));
   }

   @Nonnull
   class="kw">public CompletableFuture<MapImage> getImageAsync(long var1) {
      WorldMapManager.ImageEntry var3 = this.images.get(var1);
      if (var3 != null) {
         class="kw">return CompletableFuture.completedFuture(var3.image);
      }

      CompletableFuture var4 = this.generating.get(var1);
      if (var4 != null) {
         class="kw">return var4;
      }

      CompletableFuture var5 = new CompletableFuture<>();
      CompletableFuture var6 = this.generating.putIfAbsent(var1, var5);
      if (var6 != null) {
         class="kw">return var6;
      }

      this.generationQueue.put(var1, var5);
      if (this.generationQueue.size() == 1) {
         this.flushGenerationQueue();
      }

      class="kw">return var5;
   }

   class="kw">public void generate() {
   }

   class="kw">public void sendSettings() {
      for (Player var2 : this.world.getPlayers()) {
         var2.getWorldMapTracker().sendSettings(this.world);
      }
   }

   class="kw">public boolean shouldTick() {
      class="kw">return this.world.getWorldConfig().isCompassUpdating() || this.isWorldMapEnabled();
   }

   @Nonnull
   class="kw">public Map<String, MapMarkerOverride> getMarkerOverridesView() {
      this.assertThread();
      class="kw">return this.markerOverridesLocalView;
   }

   class="kw">public boolean addMarkerOverride(@Nonnull String var1, @Nonnull MapMarkerOverride var2) {
      class="kw">return !var1.isEmpty() && !var2.isEmpty() ? this.markerOverrides.putIfAbsent(var1, var2) == null : false;
   }

   class="kw">public boolean removeMarkerOverride(@Nonnull String var1) {
      class="kw">return var1.isEmpty() ? false : this.markerOverrides.remove(var1) != null;
   }

   class="kw">public boolean removeMarkerOverride(@Nonnull String var1, @Nonnull MapMarkerOverride var2) {
      class="kw">return !var1.isEmpty() && !var2.isEmpty() ? this.markerOverrides.remove(var1, var2) : false;
   }

   class="kw">public void removeAllMarkerOverrides() {
      this.markerOverrides.clear();
   }

   class="kw">public void updateTickingState(boolean var1) {
      boolean var2 = this.shouldTick();
      if (var1 != var2) {
         if (var2) {
            this.start();
         } else {
            this.stop();
         }
      }
   }

   class="kw">public void handleUserCreateMarker(PlayerRef var1, CreateUserMarker var2) {
      Ref var3 = var1.getReference();
      if (var3 != null) {
         UserMarkerValidator.PlaceResult var4 = UserMarkerValidator.validatePlacing(var3, var2);
         if (var4 class="kw">instanceof UserMarkerValidator.CanSpawn var5) {
            Store var13 = var3.getStore();
            UserMapMarkersStore var14 = var5.markersStore();
            DisplayNameComponent var15 = var13.getComponent(var3, DisplayNameComponent.getComponentType());
            String var9 = var15 == null ? var1.getUsername() : var15.getDisplayName().getRawText();
            UserMapMarker var10 = new UserMapMarker();
            var10.setId("user_" + (var2.shared ? "shared" : "personal") + "_" + UUID.randomUUID());
            var10.setPosition(var2.x, var2.z);
            var10.setName(var2.name);
            var10.setIcon(var2.markerImage == null ? "User1.png" : var2.markerImage);
            var10.setColorTint(var2.tintColor == null ? new Color((byte)0, (byte)0, (byte)0) : var2.tintColor);
            var10.withCreatedByName(var9);
            var10.withCreatedByUuid(var1.getUuid());
            var14.addUserMapMarker(var10);
         } else {
            if (var4 class="kw">instanceof UserMarkerValidator.Fail(Message var7)) {
               var1.sendMessage(var7.color("#ffc800"));
            }
         }
      }
   }

   class="kw">public void handleUserRemoveMarker(PlayerRef var1, RemoveMapMarker var2) {
      Ref var3 = var1.getReference();
      if (var3 != null) {
         Store var4 = var3.getStore();
         World var5 = var4.getExternalData().getWorld();
         Player var6 = var4.getComponent(var3, Player.getComponentType());
         PlayerWorldData var7 = var6.getPlayerConfigData().getPerWorldData(var5.getName());
         boolean var8 = var7.removeLastDeath(var2.markerId);
         if (!var8) {
            WorldMapManager.MarkerAndItsStore var9 = this.findUserMapMarker(var2.markerId, var6, var5);
            if (var9 == null) {
               var1.sendMessage(Message.translation("server.worldmap.markers.edit.notFound").color("#ffc800"));
               HytaleLogger.getLogger()
                  .at(Level.WARNING)
                  .log("Couldn't find marker to remove '%s' from %s %s", var2.markerId, var1.getUsername(), var1.getUuid());
            } else {
               UserMarkerValidator.RemoveResult var10 = UserMarkerValidator.validateRemove(var3, var9.marker);
               if (!(var10 class="kw">instanceof UserMarkerValidator.CanRemove)) {
                  if (var10 class="kw">instanceof UserMarkerValidator.Fail(Message var12)) {
                     var1.sendMessage(var12.color("#ffc800"));
                  }
               } else {
                  var9.store.removeUserMapMarker(var9.marker.getId());
               }
            }
         }
      }
   }

   @Nullable
   class="kw">private WorldMapManager.MarkerAndItsStore findUserMapMarker(String var1, Player var2, World var3) {
      PlayerWorldData var4 = var2.getPlayerConfigData().getPerWorldData(var3.getName());
      UserMapMarker var5 = var4.getUserMapMarker(var1);
      if (var5 != null) {
         class="kw">return new WorldMapManager.MarkerAndItsStore(var5, var4);
      }

      WorldMarkersResource var6 = var3.getChunkStore().getStore().getResource(WorldMarkersResource.getResourceType());
      UserMapMarker var7 = var6.getUserMapMarker(var1);
      class="kw">return var7 != null ? new WorldMapManager.MarkerAndItsStore(var7, var6) : null;
   }

   class="kw">public void clearImages() {
      this.images.clear();
      this.generating.clear();
      this.cancelQueuedGenerations();
   }

   class="kw">public void clearImagesInChunks(@Nonnull LongSet var1) {
      var1.forEach(var1x -> {
         this.images.remove(var1x);
         this.generating.remove(var1x);
         CompletableFuture var3 = this.generationQueue.remove(var1x);
         if (var3 != null) {
            var3.complete(null);
         }
      });
   }

   class="kw">private void assertThread() {
      if (!this.isInThread()) {
         throw new IllegalStateException("Assert not in WorldMapManager thread! Called from: " + Thread.currentThread());
      }
   }

   class="kw">public class="kw">static void sendSettingsToAllWorlds() {
      for (World var1 : Universe.get().getWorlds().values()) {
         var1.execute(() -> var1.getWorldMapManager().sendSettings());
      }
   }

   class="kw">static {
      WorldMapManager.MarkerReference.CODEC.register("Player", WorldMapManager.PlayerMarkerReference.class, WorldMapManager.PlayerMarkerReference.CODEC);
   }

   class="kw">public class="kw">static class ImageEntry {
      class="kw">private class="kw">final AtomicInteger keepAlive = new AtomicInteger();
      class="kw">private class="kw">final MapImage image;

      class="kw">public ImageEntry(MapImage var1) {
         this.image = var1;
      }
   }

   class="kw">private record MarkerAndItsStore(UserMapMarker marker, UserMapMarkersStore store) {
      class="kw">private MarkerAndItsStore {
      }
   }

   class="kw">public class="kw">interface MarkerProvider {
      void update(@Nonnull World var1, @Nonnull Player var2, @Nonnull MarkersCollector var3);
   }

   class="kw">public class="kw">interface MarkerReference {
      CodecMapCodec<WorldMapManager.MarkerReference> CODEC = new CodecMapCodec<>();

      String getMarkerId();

      void remove();
   }

   class="kw">public class="kw">static class PlayerMarkerReference class="kw">implements WorldMapManager.MarkerReference {
      class="kw">public class="kw">static class="kw">final BuilderCodec<WorldMapManager.PlayerMarkerReference> CODEC = BuilderCodec.<WorldMapManager.PlayerMarkerReference>builder(
            WorldMapManager.PlayerMarkerReference.class, WorldMapManager.PlayerMarkerReference::new
         )
         .addField(new KeyedCodec<>("Player", Codec.UUID_BINARY), (var0, var1) -> var0.player = var1, var0 -> var0.player)
         .addField(new KeyedCodec<>("World", Codec.STRING), (var0, var1) -> var0.world = var1, var0 -> var0.world)
         .addField(new KeyedCodec<>("MarkerId", Codec.STRING), (var0, var1) -> var0.markerId = var1, var0 -> var0.markerId)
         .build();
      class="kw">private UUID player;
      class="kw">private String world;
      class="kw">private String markerId;

      class="kw">private PlayerMarkerReference() {
      }

      class="kw">public PlayerMarkerReference(@Nonnull UUID var1, @Nonnull String var2, @Nonnull String var3) {
         this.player = var1;
         this.world = var2;
         this.markerId = var3;
      }

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

      @Override
      class="kw">public String getMarkerId() {
         class="kw">return this.markerId;
      }

      @Override
      class="kw">public void remove() {
         PlayerRef var1 = Universe.get().getPlayer(this.player);
         if (var1 != null) {
            Player var2 = var1.getComponent(Player.getComponentType());
            this.removeMarkerFromOnlinePlayer(var2);
         } else {
            this.removeMarkerFromOfflinePlayer();
         }
      }

      class="kw">private void removeMarkerFromOnlinePlayer(@Nonnull Player var1) {
         PlayerConfigData var2 = var1.getPlayerConfigData();
         String var3 = this.world;
         if (var3 == null) {
            var3 = var1.getWorld().getName();
         }

         removeMarkerFromData(var2, var3, this.markerId);
      }

      class="kw">private void removeMarkerFromOfflinePlayer() {
         Universe.get().getPlayerStorage().update(this.player, var1 -> {
            Player var2 = var1.getComponent(Player.getComponentType());
            PlayerConfigData var3 = var2.getPlayerConfigData();
            String var4 = this.world;
            if (var4 == null) {
               var4 = var3.getWorld();
            }

            removeMarkerFromData(var3, var4, this.markerId);
         });
      }

      class="kw">private class="kw">static void removeMarkerFromData(@Nonnull PlayerConfigData var0, @Nonnull String var1, @Nonnull String var2) {
         PlayerWorldData var3 = var0.getPerWorldData(var1);
         ArrayList var4 = new ArrayList<>(var3.getUserMapMarkers());
         var4.removeIf(var1x -> var2.equals(var1x.getId()));
         var3.setUserMapMarkers(var4);
      }
   }
}