Refactor hologram position fields into separate class

This commit is contained in:
filoghost 2021-08-08 12:50:55 +02:00
parent 150cc4c62b
commit 7fb38d82e4
3 changed files with 151 additions and 60 deletions

View File

@ -8,8 +8,6 @@ package me.filoghost.holographicdisplays.plugin.hologram.base;
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;
@ -22,25 +20,19 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
public abstract class BaseHologram<T extends EditableHologramLine> extends BaseHologramComponent {
private final WorldAwareHologramPosition position;
private final List<T> lines;
private final List<T> unmodifiableLinesView;
private final LineTrackerManager lineTrackerManager;
private @Nullable World world;
private String worldName;
private double x, y, z;
private int chunkX, chunkZ;
private final CachedBoolean isInLoadedChunk = new CachedBoolean(() -> world != null && world.isChunkLoaded(chunkX, chunkZ));
public BaseHologram(BaseHologramPosition position, LineTrackerManager lineTrackerManager) {
this.position = new WorldAwareHologramPosition(position);
this.lines = new ArrayList<>();
this.unmodifiableLinesView = Collections.unmodifiableList(lines);
this.lineTrackerManager = lineTrackerManager;
setPosition(position);
}
protected abstract boolean isVisibleTo(Player player);
@ -133,27 +125,27 @@ public abstract class BaseHologram<T extends EditableHologramLine> extends BaseH
}
public BaseHologramPosition getBasePosition() {
return new BaseHologramPosition(getPositionWorldName(), getPositionX(), getPositionY(), getPositionZ());
return position.toBasePosition();
}
public @Nullable World getPositionWorldIfLoaded() {
return world;
return position.getWorldIfLoaded();
}
public @NotNull String getPositionWorldName() {
return worldName;
return position.getWorldName();
}
public double getPositionX() {
return x;
return position.getX();
}
public double getPositionY() {
return y;
return position.getY();
}
public double getPositionZ() {
return z;
return position.getZ();
}
public void setPosition(@NotNull BaseHologramPosition position) {
@ -176,33 +168,16 @@ public abstract class BaseHologram<T extends EditableHologramLine> extends BaseH
Preconditions.notNull(worldName, "worldName");
checkNotDeleted();
this.x = x;
this.y = y;
this.z = z;
int chunkX = getChunkCoordinate(x);
int chunkZ = getChunkCoordinate(z);
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();
}
position.set(worldName, x, y, z);
updateLinePositions();
}
private int getChunkCoordinate(double positionCoordinate) {
return Location.locToBlock(positionCoordinate) >> 4;
}
/**
* When spawning at a location, the top part of the first line should be exactly on that location.
* The second line is below the first, and so on.
*/
private void updateLinePositions() {
double currentLineY = y;
double currentLineY = position.getY();
for (int i = 0; i < lines.size(); i++) {
T line = lines.get(i);
@ -212,44 +187,34 @@ public abstract class BaseHologram<T extends EditableHologramLine> extends BaseH
currentLineY -= Settings.spaceBetweenLines;
}
line.setPosition(x, currentLineY, z);
line.setPosition(position.getX(), currentLineY, position.getZ());
}
}
protected void onWorldLoad(World world) {
if (BaseHologramPosition.isSameWorld(world, this.worldName)) {
this.world = world;
isInLoadedChunk.invalidate();
}
position.onWorldLoad(world);
}
protected void onWorldUnload(World world) {
if (BaseHologramPosition.isSameWorld(world, this.worldName)) {
this.world = null;
isInLoadedChunk.set(false);
}
position.onWorldUnload(world);
}
protected void onChunkLoad(Chunk chunk) {
if (world == chunk.getWorld() && chunkX == chunk.getX() && chunkZ == chunk.getZ()) {
isInLoadedChunk.set(true);
}
position.onChunkLoad(chunk);
}
protected void onChunkUnload(Chunk chunk) {
if (world == chunk.getWorld() && chunkX == chunk.getX() && chunkZ == chunk.getZ()) {
isInLoadedChunk.set(false);
}
position.onChunkUnload(chunk);
}
protected boolean isInLoadedChunk() {
return isInLoadedChunk.get();
return position.isChunkLoaded();
}
@Override
public String toString() {
return "Hologram{"
+ "position=" + getBasePosition()
+ "position=" + position
+ ", lines=" + lines
+ ", deleted=" + isDeleted()
+ "}";

View File

@ -17,10 +17,18 @@ import java.util.Locale;
public class BaseHologramPosition {
private String worldName;
private @NotNull String worldName;
private double x, y, z;
public BaseHologramPosition(String worldName, double x, double y, double z) {
public BaseHologramPosition(BaseHologramPosition position) {
Preconditions.notNull(position, "position");
this.worldName = position.worldName;
this.x = position.x;
this.y = position.y;
this.z = position.z;
}
public BaseHologramPosition(@NotNull String worldName, double x, double y, double z) {
Preconditions.notNull(worldName, "worldName");
this.worldName = worldName;
this.x = x;
@ -47,7 +55,12 @@ public class BaseHologramPosition {
}
public boolean isInWorld(World world) {
return world != null && isSameWorld(world, this.worldName);
return world != null && isInWorld(world.getName());
}
public boolean isInWorld(String worldName) {
// Use the same comparison used by Bukkit.getWorld(...)
return worldName != null && worldName.toLowerCase(Locale.ENGLISH).equals(this.worldName.toLowerCase(Locale.ENGLISH));
}
public @Nullable World getWorldIfLoaded() {
@ -89,6 +102,13 @@ public class BaseHologramPosition {
this.z += z;
}
public void set(String worldName, double x, double y, double z) {
this.worldName = worldName;
this.x = x;
this.y = y;
this.z = z;
}
public int getBlockX() {
return Location.locToBlock(x);
}
@ -126,9 +146,4 @@ public class BaseHologramPosition {
+ "}";
}
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));
}
}

View File

@ -0,0 +1,111 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.plugin.hologram.base;
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.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class WorldAwareHologramPosition {
private final BaseHologramPosition basePosition;
private @Nullable World world;
private int chunkX, chunkZ;
private final CachedBoolean chunkLoaded;
WorldAwareHologramPosition(BaseHologramPosition basePosition) {
this.basePosition = new BaseHologramPosition(basePosition);
this.world = Bukkit.getWorld(basePosition.getWorldName());
this.chunkX = getChunkCoordinate(basePosition.getX());
this.chunkZ = getChunkCoordinate(basePosition.getZ());
this.chunkLoaded = new CachedBoolean(() -> world != null && world.isChunkLoaded(chunkX, chunkZ));
}
final void set(String worldName, double x, double y, double z) {
boolean worldChanged = !basePosition.isInWorld(worldName);
int chunkX = getChunkCoordinate(x);
int chunkZ = getChunkCoordinate(z);
basePosition.set(worldName, x, y, z);
if (worldChanged || this.chunkX != chunkX || this.chunkZ != chunkZ) {
if (worldChanged) {
this.world = Bukkit.getWorld(worldName);
}
this.chunkX = chunkX;
this.chunkZ = chunkZ;
this.chunkLoaded.invalidate();
}
}
private int getChunkCoordinate(double positionCoordinate) {
return Location.locToBlock(positionCoordinate) >> 4;
}
void onWorldLoad(World world) {
if (basePosition.isInWorld(world)) {
this.world = world;
chunkLoaded.invalidate();
}
}
void onWorldUnload(World world) {
if (basePosition.isInWorld(world)) {
this.world = null;
chunkLoaded.set(false);
}
}
void onChunkLoad(Chunk chunk) {
if (world != null && world == chunk.getWorld() && chunkX == chunk.getX() && chunkZ == chunk.getZ()) {
chunkLoaded.set(true);
}
}
void onChunkUnload(Chunk chunk) {
if (world != null && world == chunk.getWorld() && chunkX == chunk.getX() && chunkZ == chunk.getZ()) {
chunkLoaded.set(false);
}
}
boolean isChunkLoaded() {
return chunkLoaded.get();
}
@Nullable World getWorldIfLoaded() {
return world;
}
@NotNull String getWorldName() {
return basePosition.getWorldName();
}
double getX() {
return basePosition.getX();
}
double getY() {
return basePosition.getY();
}
double getZ() {
return basePosition.getZ();
}
BaseHologramPosition toBasePosition() {
return new BaseHologramPosition(basePosition);
}
@Override
public String toString() {
return basePosition.toString();
}
}