Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ public int execute(CommandContext<CommandSourceStack> context) {
try {
// Execute the Minecraft command to kill all text_display entities
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "minecraft:kill @e[type=text_display]");


plugin.getSpawnerManager().reloadAllHolograms();

// Send success message to player
plugin.getMessageService().sendMessage(sender, "hologram.cleared");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ public int execute(CommandContext<CommandSourceStack> context) {
try {
// Execute the Minecraft command to kill all text_display entities
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "minecraft:kill @e[type=text_display]");


plugin.getSpawnerManager().reloadAllHolograms();

// Send success message to player
plugin.getMessageService().sendMessage(sender, "hologram.cleared");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,20 @@ private static String formatOneDecimal(double value) {
// Public update API
// -------------------------------------------------------------------------

public boolean isAlive() {
TextDisplay display = textDisplay.get();
return display != null && display.isValid();
}

public void updateText() {
TextDisplay display = textDisplay.get();
if (display == null || entityType == null) return;
if (entityType == null) return;
if (display == null) return;
if (!display.isValid()) {
textDisplay.set(null);
createHologram();
return;
}

// Compute the text on the calling (region) thread – avoids doing string work
// inside the entity-thread lambda and keeps the lambda allocation tiny.
Expand All @@ -182,8 +193,14 @@ public void updateText() {
public void updateData(int stackSize, EntityType entityType, long currentExp, long maxExp, int currentItems, int maxSlots) {
TextDisplay display = textDisplay.get();

// Skip entirely when nothing has changed and the hologram already exists.
if (display != null && !display.isValid()) {
textDisplay.set(null);
display = null;
}

// Skip entirely when nothing has changed and the hologram display is still alive.
if (display != null
&& display.isValid()
&& this.stackSize == stackSize
&& this.entityType == entityType
&& this.currentExp == currentExp
Expand All @@ -205,13 +222,14 @@ public void updateData(int stackSize, EntityType entityType, long currentExp, lo
} else {
// Pre-compute text here (region thread) so the entity-thread lambda
// only needs to call display.setText() – no extra task dispatch.
final TextDisplay activeDisplay = display;
final String finalText = computeText();
Scheduler.runEntityTask(display, () -> {
if (!display.isValid()) {
Scheduler.runEntityTask(activeDisplay, () -> {
if (!activeDisplay.isValid()) {
textDisplay.set(null);
createHologram();
} else {
display.setText(finalText);
activeDisplay.setText(finalText);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
import github.nighter.smartspawner.spawner.properties.SpawnerData;
import github.nighter.smartspawner.Scheduler;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockState;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldSaveEvent;
Expand Down Expand Up @@ -65,6 +69,8 @@ public void onWorldLoad(WorldLoadEvent event) {
// Try to load any pending spawners for this world
loadPendingSpawnersForWorld(worldName);

ensureHologramsInLoadedChunks(world);

// If this is during server startup, also attempt initial load
if (!initialLoadAttempted) {
// Delay slightly to ensure world is fully ready
Expand Down Expand Up @@ -105,6 +111,47 @@ public void onWorldUnload(WorldUnloadEvent event) {
unloadSpawnersFromWorld(worldName);
}

@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onChunkLoad(ChunkLoadEvent event) {
ensureHologramsInChunk(event.getChunk());
}

private void ensureHologramsInChunk(Chunk chunk) {
if (!plugin.getConfig().getBoolean("hologram.enabled", false)) {
return;
}

World world = chunk.getWorld();
int chunkX = chunk.getX();
int chunkZ = chunk.getZ();

Scheduler.runChunkTask(world, chunkX, chunkZ, () -> {
if (!world.isChunkLoaded(chunkX, chunkZ)) {
return;
}

Chunk loadedChunk = world.getChunkAt(chunkX, chunkZ);
for (BlockState state : loadedChunk.getTileEntities(
block -> block.getType() == Material.SPAWNER, false)) {
SpawnerData spawner = plugin.getSpawnerManager()
.getSpawnerByLocation(state.getBlock().getLocation());
if (spawner != null) {
spawner.ensureHologram();
}
}
});
}

private void ensureHologramsInLoadedChunks(World world) {
if (!plugin.getConfig().getBoolean("hologram.enabled", false)) {
return;
}

for (Chunk loadedChunk : world.getLoadedChunks()) {
ensureHologramsInChunk(loadedChunk);
}
}

/**
* Attempt to perform initial spawner loading, checking for available worlds
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import lombok.Setter;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
Expand Down Expand Up @@ -392,22 +393,58 @@ public void updateHologramData() {
}

public void reloadHologramData() {
if (!plugin.getConfig().getBoolean("hologram.enabled", false)) {
removeHologram();
return;
}
if (hologram != null) {
hologram.remove();
createHologram();
}
if (!isSpawnerChunkLoaded()) {
return;
}
createHologram();
}

public void refreshHologram() {
if (plugin.getConfig().getBoolean("hologram.enabled", false)) {
if (hologram == null) {
createHologram();
}
} else if (hologram != null) {
ensureHologram();
} else {
removeHologram();
}
}

/**
* Recreate hologram display if missing or dead. No-op when display is alive.
* Must be invoked on or scheduled to the spawner's region thread.
*/
public void ensureHologram() {
if (!plugin.getConfig().getBoolean("hologram.enabled", false)) {
removeHologram();
return;
}
if (!isSpawnerChunkLoaded()) {
return;
}
if (hologram != null && hologram.isAlive()) {
return;
}
if (hologram != null) {
hologram.remove();
}
createHologram();
}

private boolean isSpawnerChunkLoaded() {
if (spawnerLocation == null || spawnerLocation.getWorld() == null) {
return false;
}
World world = spawnerLocation.getWorld();
int chunkX = spawnerLocation.getBlockX() >> 4;
int chunkZ = spawnerLocation.getBlockZ() >> 4;
return world.isChunkLoaded(chunkX, chunkZ);
}

public void removeHologram() {
if (hologram != null) {
hologram.remove();
Expand Down