PlayerMarkerReference class

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

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

implements: WorldMapManager.MarkerReference

Поля (15)

МодификаторыТипИмя
public static final BuilderCodec<WorldMapManager.PlayerMarkerReference> CODEC
private String markerId
private UUID player
PlayerRef var1
Player var2
PlayerConfigData var2
Player var2
String var3
var3
PlayerConfigData var3
PlayerWorldData var3
String var4
var4
ArrayList var4
private String world

Методы (11)

МодификаторыВозвратСигнатура
public String getMarkerIdpublic String getMarkerId()
public UUID getPlayerpublic UUID getPlayer()
if if(var1 != null)
if if(var3 == null)
if if(var4 == null)
public void removepublic void remove()
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)

Исходный код

Показать/скрыть
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);
      }
   }
}