From 9b21ffdf7698a43cf6172414ffe5a06fe1a8caa1 Mon Sep 17 00:00:00 2001 From: filoghost Date: Sat, 7 Aug 2021 18:39:19 +0200 Subject: [PATCH] Allow holograms to be in non-loaded worlds --- .../api/hologram/Hologram.java | 17 +++++-- .../api/hologram/HologramPosition.java | 11 ++++- .../HolographicDisplaysAPIProvider.java | 2 + .../plugin/HolographicDisplays.java | 11 ++--- ...DefaultHolographicDisplaysAPIProvider.java | 8 +++- .../plugin/api/v2/V2HologramAdapter.java | 4 +- .../plugin/commands/subs/ListCommand.java | 2 +- .../plugin/commands/subs/NearCommand.java | 2 +- .../plugin/commands/subs/ReloadCommand.java | 2 +- .../plugin/config/HologramConfig.java | 13 +---- .../plugin/hologram/api/APIHologram.java | 4 +- .../hologram/api/APIHologramPosition.java | 5 +- .../plugin/hologram/base/BaseHologram.java | 47 +++++++++++++++---- .../hologram/base/BaseHologramLine.java | 9 ++-- .../hologram/base/BaseHologramManager.java | 13 +++++ .../hologram/base/BaseHologramPosition.java | 42 +++++++++++++---- .../tracking/LocationBasedLineTracker.java | 13 +++-- .../plugin/listener/ChunkListener.java | 12 +++++ .../api/v2/V2TouchableLineAdapterTest.java | 10 +++- .../plugin/test/Mocks.java | 20 ++++++-- 20 files changed, 177 insertions(+), 70 deletions(-) diff --git a/api/src/main/java/me/filoghost/holographicdisplays/api/hologram/Hologram.java b/api/src/main/java/me/filoghost/holographicdisplays/api/hologram/Hologram.java index 616de22f..3fc4971c 100644 --- a/api/src/main/java/me/filoghost/holographicdisplays/api/hologram/Hologram.java +++ b/api/src/main/java/me/filoghost/holographicdisplays/api/hologram/Hologram.java @@ -112,12 +112,12 @@ public interface Hologram { @NotNull HologramPosition getPosition(); /** - * Returns the world of the hologram position. + * Returns the world name of the hologram position. * - * @return the world of the hologram position + * @return the world name of the hologram position * @since 1 */ - @NotNull World getPositionWorld(); + @NotNull String getPositionWorldName(); /** * Returns the X coordinate of the hologram position. @@ -151,6 +151,17 @@ public interface Hologram { */ void setPosition(@NotNull HologramPosition position); + /** + * Moves the hologram to the given position. + * + * @param worldName the world name where the hologram should be moved + * @param x the X coordinate + * @param y the Y coordinate + * @param z the Z coordinate + * @since 1 + */ + void setPosition(@NotNull String worldName, double x, double y, double z); + /** * Moves the hologram to the given position. * diff --git a/api/src/main/java/me/filoghost/holographicdisplays/api/hologram/HologramPosition.java b/api/src/main/java/me/filoghost/holographicdisplays/api/hologram/HologramPosition.java index cf64879b..0a48646c 100644 --- a/api/src/main/java/me/filoghost/holographicdisplays/api/hologram/HologramPosition.java +++ b/api/src/main/java/me/filoghost/holographicdisplays/api/hologram/HologramPosition.java @@ -9,6 +9,7 @@ import me.filoghost.holographicdisplays.api.internal.HolographicDisplaysAPIProvi import org.bukkit.Location; import org.bukkit.World; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface HologramPosition { @@ -16,11 +17,19 @@ public interface HologramPosition { return HolographicDisplaysAPIProvider.getImplementation().createHologramPosition(world, x, y, z); } + static @NotNull HologramPosition create(@NotNull String worldName, double x, double y, double z) { + return HolographicDisplaysAPIProvider.getImplementation().createHologramPosition(worldName, x, y, z); + } + static @NotNull HologramPosition fromLocation(@NotNull Location location) { return HolographicDisplaysAPIProvider.getImplementation().createHologramPosition(location); } - @NotNull World getWorld(); + @NotNull String getWorldName(); + + void setWorldName(@NotNull String worldName); + + @Nullable World getWorldIfLoaded(); void setWorld(@NotNull World world); diff --git a/api/src/main/java/me/filoghost/holographicdisplays/api/internal/HolographicDisplaysAPIProvider.java b/api/src/main/java/me/filoghost/holographicdisplays/api/internal/HolographicDisplaysAPIProvider.java index 8ee7252d..cd4a22a7 100644 --- a/api/src/main/java/me/filoghost/holographicdisplays/api/internal/HolographicDisplaysAPIProvider.java +++ b/api/src/main/java/me/filoghost/holographicdisplays/api/internal/HolographicDisplaysAPIProvider.java @@ -35,6 +35,8 @@ public abstract class HolographicDisplaysAPIProvider { public abstract HologramPosition createHologramPosition(World world, double x, double y, double z); + public abstract HologramPosition createHologramPosition(String worldName, double x, double y, double z); + public abstract HologramPosition createHologramPosition(Location location); } diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/HolographicDisplays.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/HolographicDisplays.java index e4b69b16..8edfe62c 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/HolographicDisplays.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/HolographicDisplays.java @@ -110,7 +110,7 @@ public class HolographicDisplays extends FCommonsPlugin { new DatabaseLegacyUpgrade(configManager, errorCollector).tryRun(); // Load the configuration - load(true, errorCollector); + load(errorCollector); // Add packet listener for currently online players (may happen if the plugin is disabled and re-enabled) for (Player player : Bukkit.getOnlinePlayers()) { @@ -155,7 +155,7 @@ public class HolographicDisplays extends FCommonsPlugin { HologramsAPIProvider.setImplementation(new V2HologramsAPIProvider(apiHologramManager, placeholderRegistry)); } - public void load(boolean deferHologramsCreation, ErrorCollector errorCollector) { + public void load(ErrorCollector errorCollector) { internalHologramManager.clearAll(); configManager.reloadStaticReplacements(errorCollector); @@ -167,12 +167,7 @@ public class HolographicDisplays extends FCommonsPlugin { bungeeServerTracker.restart(Settings.bungeeRefreshSeconds, TimeUnit.SECONDS); HologramDatabase hologramDatabase = configManager.loadHologramDatabase(errorCollector); - if (deferHologramsCreation) { - // For the initial load: holograms are loaded later, when the worlds are ready - Bukkit.getScheduler().runTask(this, () -> hologramDatabase.createHolograms(internalHologramManager, errorCollector)); - } else { - hologramDatabase.createHolograms(internalHologramManager, errorCollector); - } + hologramDatabase.createHolograms(internalHologramManager, errorCollector); } @Override diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/api/current/DefaultHolographicDisplaysAPIProvider.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/api/current/DefaultHolographicDisplaysAPIProvider.java index f8485d1f..f7410a0d 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/api/current/DefaultHolographicDisplaysAPIProvider.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/api/current/DefaultHolographicDisplaysAPIProvider.java @@ -43,7 +43,13 @@ public class DefaultHolographicDisplaysAPIProvider extends HolographicDisplaysAP @Override public HologramPosition createHologramPosition(World world, double x, double y, double z) { - return new APIHologramPosition(world, x, y, z); + Preconditions.notNull(world, "world"); + return new APIHologramPosition(world.getName(), x, y, z); + } + + @Override + public HologramPosition createHologramPosition(String worldName, double x, double y, double z) { + return new APIHologramPosition(worldName, x, y, z); } @Override diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/api/v2/V2HologramAdapter.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/api/v2/V2HologramAdapter.java index bab8caac..cc28e860 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/api/v2/V2HologramAdapter.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/api/v2/V2HologramAdapter.java @@ -81,7 +81,7 @@ public class V2HologramAdapter implements Hologram { @Override public Location getLocation() { - return new Location(v3Hologram.getPositionWorld(), v3Hologram.getPositionX(), v3Hologram.getPositionY(), v3Hologram.getPositionZ()); + return new Location(v3Hologram.getPositionWorldIfLoaded(), v3Hologram.getPositionX(), v3Hologram.getPositionY(), v3Hologram.getPositionZ()); } @Override @@ -101,7 +101,7 @@ public class V2HologramAdapter implements Hologram { @Override public World getWorld() { - return v3Hologram.getPositionWorld(); + return v3Hologram.getPositionWorldIfLoaded(); } @Override diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/commands/subs/ListCommand.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/commands/subs/ListCommand.java index eed5d7e7..67970b63 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/commands/subs/ListCommand.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/commands/subs/ListCommand.java @@ -59,7 +59,7 @@ public class ListCommand extends HologramSubCommand { sender.sendMessage(ColorScheme.SECONDARY_DARKER + "- " + ColorScheme.SECONDARY_BOLD + hologram.getName() + " " + ColorScheme.SECONDARY_DARKER + "at" + " x: " + position.getBlockX() + ", y: " + position.getBlockY() + ", z: " + position.getBlockZ() - + " (lines: " + hologram.getLineCount() + ", world: \"" + position.getWorld().getName() + "\")"); + + " (lines: " + hologram.getLineCount() + ", world: \"" + position.getWorldName() + "\")"); } } diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/commands/subs/NearCommand.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/commands/subs/NearCommand.java index 130504f6..90c3184a 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/commands/subs/NearCommand.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/commands/subs/NearCommand.java @@ -45,7 +45,7 @@ public class NearCommand extends HologramSubCommand { for (InternalHologram hologram : hologramEditor.getHolograms()) { BaseHologramPosition position = hologram.getBasePosition(); - if (position.getWorld().equals(world) && position.distance(player.getLocation()) <= radius) { + if (position.isInWorld(world) && position.distance(player.getLocation()) <= radius) { nearHolograms.add(hologram); } } diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/commands/subs/ReloadCommand.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/commands/subs/ReloadCommand.java index 086b14e4..8a0d51b7 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/commands/subs/ReloadCommand.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/commands/subs/ReloadCommand.java @@ -29,7 +29,7 @@ public class ReloadCommand extends HologramSubCommand { @Override public void execute(CommandSender sender, String[] args, SubCommandContext context) { PrintableErrorCollector errorCollector = new PrintableErrorCollector(); - holographicDisplays.load(false, errorCollector); + holographicDisplays.load(errorCollector); if (!errorCollector.hasErrors()) { sender.sendMessage(ColorScheme.PRIMARY + "Configuration reloaded successfully."); diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/HologramConfig.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/HologramConfig.java index 4a6b9785..7e040b26 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/HologramConfig.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/HologramConfig.java @@ -11,8 +11,6 @@ import me.filoghost.holographicdisplays.plugin.hologram.base.BaseHologramPositio import me.filoghost.holographicdisplays.plugin.hologram.internal.InternalHologram; import me.filoghost.holographicdisplays.plugin.hologram.internal.InternalHologramLine; import me.filoghost.holographicdisplays.plugin.hologram.internal.InternalHologramManager; -import org.bukkit.Bukkit; -import org.bukkit.World; import java.util.ArrayList; import java.util.List; @@ -38,7 +36,7 @@ public class HologramConfig { BaseHologramPosition position = hologram.getBasePosition(); this.positionConfigSection = new ConfigSection(); - positionConfigSection.setString("world", position.getWorld().getName()); + positionConfigSection.setString("world", position.getWorldName()); positionConfigSection.setDouble("x", position.getX()); positionConfigSection.setDouble("y", position.getY()); positionConfigSection.setDouble("z", position.getZ()); @@ -81,14 +79,7 @@ public class HologramConfig { double x = positionConfigSection.getRequiredDouble("x"); double y = positionConfigSection.getRequiredDouble("y"); double z = positionConfigSection.getRequiredDouble("z"); - - World world = Bukkit.getWorld(worldName); - if (world == null) { - throw new HologramLoadException("world \"" + worldName + "\" is not currently loaded"); - } - - return new BaseHologramPosition(world, x, y, z); - + return new BaseHologramPosition(worldName, x, y, z); } catch (ConfigValueException e) { throw new HologramLoadException("invalid position attribute \"" + e.getConfigPath() + "\"", e); } diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/api/APIHologram.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/api/APIHologram.java index 278a2248..da362e40 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/api/APIHologram.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/api/APIHologram.java @@ -136,12 +136,12 @@ public class APIHologram extends BaseHologram implements Hologr @Override public @NotNull HologramPosition getPosition() { - return new APIHologramPosition(getPositionWorld(), getPositionX(), getPositionY(), getPositionZ()); + return new APIHologramPosition(getPositionWorldName(), getPositionX(), getPositionY(), getPositionZ()); } @Override public void setPosition(@NotNull HologramPosition position) { - super.setPosition(position.getWorld(), position.getX(), position.getY(), position.getZ()); + super.setPosition(position.getWorldName(), position.getX(), position.getY(), position.getZ()); } @Override diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/api/APIHologramPosition.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/api/APIHologramPosition.java index 824ba234..73c7f19b 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/api/APIHologramPosition.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/api/APIHologramPosition.java @@ -8,12 +8,11 @@ package me.filoghost.holographicdisplays.plugin.hologram.api; import me.filoghost.holographicdisplays.api.hologram.HologramPosition; import me.filoghost.holographicdisplays.plugin.hologram.base.BaseHologramPosition; import org.bukkit.Location; -import org.bukkit.World; public class APIHologramPosition extends BaseHologramPosition implements HologramPosition { - public APIHologramPosition(World world, double x, double y, double z) { - super(world, x, y, z); + public APIHologramPosition(String worldName, double x, double y, double z) { + super(worldName, x, y, z); } public APIHologramPosition(Location location) { diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologram.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologram.java index 8e28e199..afa1a126 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologram.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologram.java @@ -9,17 +9,20 @@ import me.filoghost.fcommons.Preconditions; import me.filoghost.holographicdisplays.plugin.config.Settings; import me.filoghost.holographicdisplays.plugin.hologram.tracking.LineTrackerManager; import me.filoghost.holographicdisplays.plugin.util.CachedBoolean; +import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Objects; public abstract class BaseHologram extends BaseHologramComponent { @@ -27,16 +30,17 @@ public abstract class BaseHologram extends BaseH private final List unmodifiableLinesView; private final LineTrackerManager lineTrackerManager; - private World world; + private @Nullable World world; + private String worldName; private double x, y, z; private int chunkX, chunkZ; - private final CachedBoolean isInLoadedChunk = new CachedBoolean(() -> world.isChunkLoaded(chunkX, chunkZ)); + private final CachedBoolean isInLoadedChunk = new CachedBoolean(() -> world != null && world.isChunkLoaded(chunkX, chunkZ)); public BaseHologram(BaseHologramPosition position, LineTrackerManager lineTrackerManager) { this.lines = new ArrayList<>(); this.unmodifiableLinesView = Collections.unmodifiableList(lines); this.lineTrackerManager = lineTrackerManager; - setPosition(position.getWorld(), position.getX(), position.getY(), position.getZ()); + setPosition(position); } protected abstract boolean isVisibleTo(Player player); @@ -129,13 +133,17 @@ public abstract class BaseHologram extends BaseH } public BaseHologramPosition getBasePosition() { - return new BaseHologramPosition(getPositionWorld(), getPositionX(), getPositionY(), getPositionZ()); + return new BaseHologramPosition(getPositionWorldName(), getPositionX(), getPositionY(), getPositionZ()); } - public @NotNull World getPositionWorld() { + public @Nullable World getPositionWorldIfLoaded() { return world; } + public @NotNull String getPositionWorldName() { + return worldName; + } + public double getPositionX() { return x; } @@ -150,16 +158,22 @@ public abstract class BaseHologram extends BaseH public void setPosition(@NotNull BaseHologramPosition position) { Preconditions.notNull(position, "position"); - setPosition(position.getWorld(), position.getX(), position.getY(), position.getZ()); + setPosition(position.getWorldName(), position.getX(), position.getY(), position.getZ()); } public void setPosition(@NotNull Location location) { Preconditions.notNull(location, "location"); - setPosition(location.getWorld(), location.getX(), location.getY(), location.getZ()); + Preconditions.notNull(location.getWorld(), "location's world"); + setPosition(location.getWorld().getName(), location.getX(), location.getY(), location.getZ()); } public void setPosition(@NotNull World world, double x, double y, double z) { Preconditions.notNull(world, "world"); + setPosition(world.getName(), x, y, z); + } + + public void setPosition(@NotNull String worldName, double x, double y, double z) { + Preconditions.notNull(worldName, "worldName"); checkNotDeleted(); this.x = x; @@ -168,8 +182,9 @@ public abstract class BaseHologram extends BaseH int chunkX = getChunkCoordinate(x); int chunkZ = getChunkCoordinate(z); - if (this.world != world || this.chunkX != chunkX || this.chunkZ != chunkZ) { - this.world = world; + if (!Objects.equals(this.worldName, worldName) || this.chunkX != chunkX || this.chunkZ != chunkZ) { + this.world = Bukkit.getWorld(worldName); + this.worldName = worldName; this.chunkX = chunkX; this.chunkZ = chunkZ; this.isInLoadedChunk.invalidate(); @@ -201,6 +216,20 @@ public abstract class BaseHologram extends BaseH } } + protected void onWorldLoad(World world) { + if (BaseHologramPosition.isSameWorld(world, this.worldName)) { + this.world = world; + isInLoadedChunk.invalidate(); + } + } + + protected void onWorldUnload(World world) { + if (BaseHologramPosition.isSameWorld(world, this.worldName)) { + this.world = null; + isInLoadedChunk.set(false); + } + } + protected void onChunkLoad(Chunk chunk) { if (world == chunk.getWorld() && chunkX == chunk.getX() && chunkZ == chunk.getZ()) { isInLoadedChunk.set(true); diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologramLine.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologramLine.java index 9ac20e8d..a592549f 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologramLine.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologramLine.java @@ -12,6 +12,7 @@ import org.bukkit.GameMode; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.Nullable; public abstract class BaseHologramLine extends BaseHologramComponent implements EditableHologramLine { @@ -44,6 +45,10 @@ public abstract class BaseHologramLine extends BaseHologramComponent implements setChanged(); } + public @Nullable World getWorldIfLoaded() { + return hologram.getPositionWorldIfLoaded(); + } + public double getX() { return x; } @@ -56,10 +61,6 @@ public abstract class BaseHologramLine extends BaseHologramComponent implements return z; } - public World getWorld() { - return hologram.getPositionWorld(); - } - public boolean isInLoadedChunk() { return hologram.isInLoadedChunk(); } diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologramManager.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologramManager.java index 22af5938..16da33b8 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologramManager.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologramManager.java @@ -6,6 +6,7 @@ package me.filoghost.holographicdisplays.plugin.hologram.base; import org.bukkit.Chunk; +import org.bukkit.World; import java.util.ArrayList; import java.util.Collections; @@ -39,6 +40,18 @@ public abstract class BaseHologramManager> { } } + public void onWorldLoad(World world) { + for (H hologram : holograms) { + hologram.onWorldLoad(world); + } + } + + public void onWorldUnload(World world) { + for (H hologram : holograms) { + hologram.onWorldUnload(world); + } + } + public void onChunkLoad(Chunk chunk) { for (H hologram : holograms) { hologram.onChunkLoad(chunk); diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologramPosition.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologramPosition.java index 2df24988..eb4fb887 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologramPosition.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/base/BaseHologramPosition.java @@ -6,19 +6,23 @@ package me.filoghost.holographicdisplays.plugin.hologram.base; import me.filoghost.fcommons.Preconditions; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.util.NumberConversions; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Locale; public class BaseHologramPosition { - private World world; + private String worldName; private double x, y, z; - public BaseHologramPosition(World world, double x, double y, double z) { - Preconditions.notNull(world, "world"); - this.world = world; + public BaseHologramPosition(String worldName, double x, double y, double z) { + Preconditions.notNull(worldName, "worldName"); + this.worldName = worldName; this.x = x; this.y = y; this.z = z; @@ -27,19 +31,32 @@ public class BaseHologramPosition { public BaseHologramPosition(Location location) { Preconditions.notNull(location, "location"); Preconditions.notNull(location.getWorld(), "location's world"); - this.world = location.getWorld(); + this.worldName = location.getWorld().getName(); this.x = location.getX(); this.y = location.getY(); this.z = location.getZ(); } - public @NotNull World getWorld() { - return world; + public @NotNull String getWorldName() { + return worldName; + } + + public void setWorldName(@NotNull String worldName) { + Preconditions.notNull(worldName, "worldName"); + this.worldName = worldName; + } + + public boolean isInWorld(World world) { + return world != null && isSameWorld(world, this.worldName); + } + + public @Nullable World getWorldIfLoaded() { + return Bukkit.getWorld(worldName); } public void setWorld(@NotNull World world) { Preconditions.notNull(world, "world"); - this.world = world; + this.worldName = world.getName(); } public double getX() { @@ -96,17 +113,22 @@ public class BaseHologramPosition { } public @NotNull Location toLocation() { - return new Location(world, x, y, z); + return new Location(getWorldIfLoaded(), x, y, z); } @Override public String toString() { return "HologramPosition{" - + "world=" + world + + "worldName=" + worldName + ", x=" + x + ", y=" + y + ", z=" + z + "}"; } + static boolean isSameWorld(World world, String worldName) { + // Use the same comparison used by Bukkit.getWorld(...) + return world.getName().toLowerCase(Locale.ENGLISH).equals(worldName.toLowerCase(Locale.ENGLISH)); + } + } diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/tracking/LocationBasedLineTracker.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/tracking/LocationBasedLineTracker.java index a522ff23..21767312 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/tracking/LocationBasedLineTracker.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/hologram/tracking/LocationBasedLineTracker.java @@ -9,7 +9,6 @@ import me.filoghost.holographicdisplays.common.nms.NMSManager; import me.filoghost.holographicdisplays.common.nms.NMSPacketList; import me.filoghost.holographicdisplays.plugin.hologram.base.BaseHologramLine; import org.bukkit.Location; -import org.bukkit.World; import org.bukkit.entity.Player; import org.jetbrains.annotations.MustBeInvokedByOverriders; @@ -17,7 +16,6 @@ abstract class LocationBasedLineTracker extends Line private static final int ENTITY_VIEW_RANGE = 64; - private World world; protected double locationX; protected double locationY; protected double locationZ; @@ -30,12 +28,10 @@ abstract class LocationBasedLineTracker extends Line @MustBeInvokedByOverriders @Override protected void detectChanges() { - World world = line.getWorld(); double locationX = line.getX(); double locationY = line.getY(); double locationZ = line.getZ(); - if (this.world != world || this.locationX != locationX || this.locationY != locationY || this.locationZ != locationZ) { - this.world = world; + if (this.locationX != locationX || this.locationY != locationY || this.locationZ != locationZ) { this.locationX = locationX; this.locationY = locationY; this.locationZ = locationZ; @@ -52,11 +48,14 @@ abstract class LocationBasedLineTracker extends Line @Override protected final boolean shouldTrackPlayer(Player player) { Location playerLocation = player.getLocation(); + if (playerLocation.getWorld() != line.getWorldIfLoaded()) { + return false; + } + double diffX = Math.abs(playerLocation.getX() - locationX); double diffZ = Math.abs(playerLocation.getZ() - locationZ); - return playerLocation.getWorld() == world - && diffX <= (double) ENTITY_VIEW_RANGE + return diffX <= (double) ENTITY_VIEW_RANGE && diffZ <= (double) ENTITY_VIEW_RANGE && line.isVisibleTo(player); } diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/listener/ChunkListener.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/listener/ChunkListener.java index b687c198..901d4b8a 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/listener/ChunkListener.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/listener/ChunkListener.java @@ -14,6 +14,8 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.event.world.WorldLoadEvent; +import org.bukkit.event.world.WorldUnloadEvent; import org.bukkit.plugin.Plugin; public class ChunkListener implements Listener { @@ -28,6 +30,16 @@ public class ChunkListener implements Listener { this.apiHologramManager = apiHologramManager; } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onWorldLoad(WorldUnloadEvent event) { + internalHologramManager.onWorldLoad(event.getWorld()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onWorldLoad(WorldLoadEvent event) { + internalHologramManager.onWorldUnload(event.getWorld()); + } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onChunkUnload(ChunkUnloadEvent event) { internalHologramManager.onChunkUnload(event.getChunk()); diff --git a/plugin/src/test/java/me/filoghost/holographicdisplays/plugin/api/v2/V2TouchableLineAdapterTest.java b/plugin/src/test/java/me/filoghost/holographicdisplays/plugin/api/v2/V2TouchableLineAdapterTest.java index 39bdcec5..2c6b7dd3 100644 --- a/plugin/src/test/java/me/filoghost/holographicdisplays/plugin/api/v2/V2TouchableLineAdapterTest.java +++ b/plugin/src/test/java/me/filoghost/holographicdisplays/plugin/api/v2/V2TouchableLineAdapterTest.java @@ -10,12 +10,13 @@ import com.gmail.filoghost.holographicdisplays.api.line.TextLine; import me.filoghost.holographicdisplays.api.hologram.ClickListener; import me.filoghost.holographicdisplays.plugin.hologram.api.APIHologram; import me.filoghost.holographicdisplays.plugin.hologram.api.APIHologramManager; -import me.filoghost.holographicdisplays.plugin.hologram.base.BaseHologramPosition; import me.filoghost.holographicdisplays.plugin.hologram.api.APITextLine; +import me.filoghost.holographicdisplays.plugin.hologram.base.BaseHologramPosition; import me.filoghost.holographicdisplays.plugin.test.Mocks; import me.filoghost.holographicdisplays.plugin.test.TestAPIHologramManager; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.*; @@ -26,10 +27,15 @@ class V2TouchableLineAdapterTest { APIHologramManager apiHologramManager = new TestAPIHologramManager(); APIHologram hologram = apiHologramManager.createHologram( - new BaseHologramPosition(Mocks.WORLD, 0, 0, 0), + new BaseHologramPosition("world", 0, 0, 0), Mocks.PLUGIN ); + @BeforeAll + static void beforeAll() { + Mocks.prepareEnvironment(); + } + @Test void setNullV2TouchHandler() { APITextLine v3Line = hologram.appendTextLine(""); diff --git a/plugin/src/test/java/me/filoghost/holographicdisplays/plugin/test/Mocks.java b/plugin/src/test/java/me/filoghost/holographicdisplays/plugin/test/Mocks.java index cad3ddb5..307951f6 100644 --- a/plugin/src/test/java/me/filoghost/holographicdisplays/plugin/test/Mocks.java +++ b/plugin/src/test/java/me/filoghost/holographicdisplays/plugin/test/Mocks.java @@ -5,20 +5,32 @@ */ package me.filoghost.holographicdisplays.plugin.test; -import org.bukkit.World; +import org.bukkit.Bukkit; +import org.bukkit.Server; import org.bukkit.plugin.Plugin; +import java.util.logging.Logger; + import static org.mockito.Mockito.*; public class Mocks { + private static final Logger SERVER_LOGGER; + public static final Server SERVER; public static final Plugin PLUGIN; - public static final World WORLD; static { + SERVER_LOGGER = mock(Logger.class); + SERVER = mock(Server.class); + when(SERVER.getLogger()).thenReturn(SERVER_LOGGER); PLUGIN = mock(Plugin.class); when(PLUGIN.getName()).thenReturn("HolographicDisplays"); - WORLD = mock(World.class); - when(WORLD.getName()).thenReturn("world"); } + + public static void prepareEnvironment() { + if (Bukkit.getServer() == null) { + Bukkit.setServer(Mocks.SERVER); + } + } + }