Allow updating holograms in bulk

This improves performance when using *HolographicDisplays* drastically on many holograms.

Plugins like *EpicAnchors* might need to manage and update a lot of holograms frequently, causing SongodaCore to fetch all the holograms from the external API (My test setup reduced the time needed to update from ~30ms to ~1ms)
This commit is contained in:
Christian Koop 2021-04-21 14:36:04 +02:00 committed by Brianna
parent 040eb14982
commit dde2fd36c6
5 changed files with 71 additions and 25 deletions

View File

@ -5,6 +5,7 @@ import org.bukkit.Location;
import org.bukkit.plugin.Plugin;
import java.util.List;
import java.util.Map;
/**
* A convenience class for static access to a Holograms HookManager
@ -76,4 +77,9 @@ public class HologramManager {
if (manager.isEnabled())
manager.getCurrentHook().updateHologram(location, lines);
}
public static void bulkUpdateHolograms(Map<Location, List<String>> holograms) {
if (manager.isEnabled())
manager.getCurrentHook().bulkUpdateHolograms(holograms);
}
}

View File

@ -12,6 +12,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -30,7 +31,6 @@ public class CMIHolograms extends Holograms {
} catch (NoSuchFieldException | NoSuchMethodException e) {
e.printStackTrace();
}
}
public CMIHolograms(Plugin plugin) {
@ -116,6 +116,13 @@ public class CMIHolograms extends Holograms {
createAt(location, lines);
}
@Override
public void bulkUpdateHolograms(Map<Location, List<String>> hologramData) {
for (Map.Entry<Location, List<String>> entry : hologramData.entrySet()) {
updateHologram(entry.getKey(), entry.getValue());
}
}
private String locStr(Location loc) {
return String.format("%s-%d-%d-%d", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
}
@ -133,5 +140,4 @@ public class CMIHolograms extends Holograms {
ourHolograms.add(id);
}
}
}

View File

@ -6,6 +6,7 @@ import org.bukkit.plugin.Plugin;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public abstract class Holograms implements Hook {
@ -55,5 +56,7 @@ public abstract class Holograms implements Hook {
public abstract void updateHologram(Location location, List<String> lines);
public abstract void bulkUpdateHolograms(Map<Location, List<String>> hologramData);
public abstract void removeAllHolograms();
}

View File

@ -10,11 +10,12 @@ import org.bukkit.plugin.Plugin;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
public class HologramsHolograms extends Holograms {
HologramPlugin hologramPlugin;
HashSet<String> ourHolograms = new HashSet();
HashSet<String> ourHolograms = new HashSet<>();
public HologramsHolograms(Plugin plugin) {
super(plugin);
@ -69,16 +70,20 @@ public class HologramsHolograms extends Holograms {
public void updateHologram(Location location, List<String> lines) {
location = fixLocation(location);
Hologram hologram = hologramPlugin.getHologramManager().getHologram(locStr(location));
if (hologram != null) {
hologram.spawn();
// only update if there is a change to the text
boolean isChanged = lines.size() != hologram.getLines().size();
if (!isChanged) {
// double-check the lines
for (int i = 0; !isChanged && i < lines.size(); ++i) {
isChanged = !hologram.getLine(i).getRaw().equals(lines.get(i));
}
}
if (isChanged) {
for (HologramLine line : hologram.getLines().toArray(new HologramLine[0])) {
hologram.removeLine(line);
@ -87,17 +92,25 @@ public class HologramsHolograms extends Holograms {
hologram.addLine(new TextLine(hologram, line));
}
}
return;
}
createAt(location, lines);
}
@Override
public void bulkUpdateHolograms(Map<Location, List<String>> hologramData) {
for (Map.Entry<Location, List<String>> entry : hologramData.entrySet()) {
updateHologram(entry.getKey(), entry.getValue());
}
}
private String locStr(Location loc) {
return String.format("%s-%d-%d-%d", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
}
private void createAt(Location location, List<String> lines) {
final String id = locStr(location);
Hologram hologram = new Hologram(id, location);
for (String line : lines) {
@ -109,5 +122,4 @@ public class HologramsHolograms extends Holograms {
if (!ourHolograms.contains(id))
ourHolograms.add(id);
}
}

View File

@ -5,7 +5,10 @@ import com.gmail.filoghost.holographicdisplays.api.HologramsAPI;
import org.bukkit.Location;
import org.bukkit.plugin.Plugin;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class HolographicDisplaysHolograms extends Holograms {
@ -46,29 +49,46 @@ public class HolographicDisplaysHolograms extends Holograms {
@Override
public void updateHologram(Location location, List<String> lines) {
location = fixLocation(location);
for (Hologram hologram : HologramsAPI.getHolograms(plugin)) {
bulkUpdateHolograms(Collections.singletonMap(location, lines));
}
@Override
public void bulkUpdateHolograms(Map<Location, List<String>> hologramData) {
Collection<Hologram> holograms = HologramsAPI.getHolograms(plugin);
for (Map.Entry<Location, List<String>> entry : hologramData.entrySet()) {
Location location = fixLocation(entry.getKey());
List<String> lines = entry.getValue();
for (Hologram hologram : holograms) {
if (hologram.getX() != location.getX()
|| hologram.getY() != location.getY()
|| hologram.getZ() != location.getZ()) continue;
// only update if there is a change to the text
boolean isChanged = lines.size() != hologram.size();
if (!isChanged) {
// double-check the lines
for (int i = 0; !isChanged && i < lines.size(); ++i) {
isChanged = !hologram.getLine(i).toString().equals("CraftTextLine [text=" + lines.get(i) + "]");
}
}
if (isChanged) {
hologram.clearLines();
for (String line : lines) {
hologram.appendTextLine(line);
}
}
return;
}
createAt(location, lines);
}
}
private void createAt(Location location, List<String> lines) {
Hologram hologram = HologramsAPI.createHologram(plugin, location);
@ -79,7 +99,6 @@ public class HolographicDisplaysHolograms extends Holograms {
@Override
public void removeAllHolograms() {
HologramsAPI.getHolograms(plugin).stream().forEach(x -> x.delete());
HologramsAPI.getHolograms(plugin).forEach(Hologram::delete);
}
}