Skip to content

Commit c28db01

Browse files
committed
Reduce display hot paths and retained state
1 parent 9ead6a5 commit c28db01

17 files changed

Lines changed: 1288 additions & 115 deletions

common/src/main/java/com/loohp/interactionvisualizer/InteractionVisualizer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.loohp.interactionvisualizer.managers.DisplayManager;
3535
import com.loohp.interactionvisualizer.managers.PreferenceManager;
3636
import com.loohp.interactionvisualizer.managers.PerformanceMetrics;
37+
import com.loohp.interactionvisualizer.managers.PlayerLocationManager;
3738
import com.loohp.interactionvisualizer.managers.TaskManager;
3839
import com.loohp.interactionvisualizer.managers.TileEntityManager;
3940
import com.loohp.interactionvisualizer.metrics.Charts;
@@ -45,6 +46,7 @@
4546
import com.loohp.interactionvisualizer.updater.Updater.UpdaterResponse;
4647
import com.loohp.interactionvisualizer.scheduler.Scheduler;
4748
import com.loohp.interactionvisualizer.config.SparrowConfiguration;
49+
import com.loohp.interactionvisualizer.utils.LegacyTextComponentCache;
4850
import net.kyori.adventure.text.Component;
4951
import net.kyori.adventure.text.format.NamedTextColor;
5052
import org.bukkit.Bukkit;
@@ -255,7 +257,11 @@ public void onDisable() {
255257
if (preferenceManager != null) {
256258
preferenceManager.close();
257259
}
260+
TaskManager.shutdown();
258261
DisplayManager.shutdown();
262+
TileEntityManager.shutdown();
263+
PlayerLocationManager.clearCache();
264+
LegacyTextComponentCache.invalidateAll();
259265
if (asyncExecutorManager != null) {
260266
asyncExecutorManager.close();
261267
}

common/src/main/java/com/loohp/interactionvisualizer/blocks/BeeHiveDisplay.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ public void updateBlock(Block block) {
433433

434434
Map<String, Object> map = beehiveMap.get(block);
435435

436-
org.bukkit.block.Beehive beehiveState = (org.bukkit.block.Beehive) block.getState();
436+
org.bukkit.block.Beehive beehiveState = (org.bukkit.block.Beehive) block.getState(false);
437437
org.bukkit.block.data.type.Beehive beehiveData = (org.bukkit.block.data.type.Beehive) block.getBlockData();
438438

439439
{
@@ -468,7 +468,7 @@ public boolean isActive(Location loc) {
468468

469469
public Map<String, DisplayEntity> spawnDisplayEntitys(Block block) {
470470
Map<String, DisplayEntity> map = new HashMap<>();
471-
BlockData blockData = block.getState().getBlockData();
471+
BlockData blockData = block.getBlockData();
472472
BlockFace facing = ((Directional) blockData).getFacing();
473473

474474
Location loc0 = labelLocation(block.getLocation(), facing, 0.25);

common/src/main/java/com/loohp/interactionvisualizer/blocks/BeeNestDisplay.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ public void updateBlock(Block block) {
433433

434434
Map<String, Object> map = beenestMap.get(block);
435435

436-
org.bukkit.block.Beehive beehiveState = (org.bukkit.block.Beehive) block.getState();
436+
org.bukkit.block.Beehive beehiveState = (org.bukkit.block.Beehive) block.getState(false);
437437
org.bukkit.block.data.type.Beehive beehiveData = (org.bukkit.block.data.type.Beehive) block.getBlockData();
438438

439439
{
@@ -468,7 +468,7 @@ public boolean isActive(Location loc) {
468468

469469
public Map<String, DisplayEntity> spawnDisplayEntitys(Block block) {
470470
Map<String, DisplayEntity> map = new HashMap<>();
471-
BlockData blockData = block.getState().getBlockData();
471+
BlockData blockData = block.getBlockData();
472472
BlockFace facing = ((Directional) blockData).getFacing();
473473

474474
Location loc0 = labelLocation(block.getLocation(), facing, 0.25);

common/src/main/java/com/loohp/interactionvisualizer/blocks/BlastFurnaceDisplay.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ private ScheduledTask legacyRun() {
217217
if (!block.getType().equals(Material.BLAST_FURNACE)) {
218218
return;
219219
}
220-
org.bukkit.block.BlastFurnace blastfurnace = (org.bukkit.block.BlastFurnace) block.getState();
220+
org.bukkit.block.BlastFurnace blastfurnace = (org.bukkit.block.BlastFurnace) block.getState(false);
221221

222222
{
223223
Inventory inv = blastfurnace.getInventory();
@@ -336,7 +336,7 @@ private boolean updateHybridBlock(Block block) {
336336
values.putAll(spawnDisplayEntitys(block));
337337
blastfurnaceMap.put(block, values);
338338
}
339-
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState();
339+
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState(false);
340340
return FurnaceDisplayUpdater.update(furnace, values, KEY, progressBarCharacter, emptyColor,
341341
filledColor, noFuelColor, progressBarLength, amountPending);
342342
}
@@ -628,7 +628,7 @@ public Map<String, DisplayEntity> spawnDisplayEntitys(Block block) {
628628
Map<String, DisplayEntity> map = new HashMap<>();
629629
Location origin = block.getLocation();
630630

631-
BlockData blockData = block.getState().getBlockData();
631+
BlockData blockData = block.getBlockData();
632632
BlockFace facing = ((Directional) blockData).getFacing();
633633
Location target = block.getRelative(facing).getLocation();
634634
Vector direction = target.toVector().subtract(origin.toVector()).multiply(0.7);

common/src/main/java/com/loohp/interactionvisualizer/blocks/FurnaceDisplay.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ private ScheduledTask legacyRun() {
216216
if (!isFurnace(block.getType())) {
217217
return;
218218
}
219-
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState();
219+
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState(false);
220220

221221
{
222222
Inventory inv = furnace.getInventory();
@@ -335,7 +335,7 @@ private boolean updateHybridBlock(Block block) {
335335
values.putAll(spawnDisplayEntitys(block));
336336
furnaceMap.put(block, values);
337337
}
338-
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState();
338+
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState(false);
339339
return FurnaceDisplayUpdater.update(furnace, values, KEY, progressBarCharacter, emptyColor,
340340
filledColor, noFuelColor, progressBarLength, amountPending);
341341
}
@@ -624,7 +624,7 @@ public Map<String, DisplayEntity> spawnDisplayEntitys(Block block) {
624624
Map<String, DisplayEntity> map = new HashMap<>();
625625
Location origin = block.getLocation();
626626

627-
BlockData blockData = block.getState().getBlockData();
627+
BlockData blockData = block.getBlockData();
628628
BlockFace facing = ((Directional) blockData).getFacing();
629629
Location target = block.getRelative(facing).getLocation();
630630
Vector direction = target.toVector().subtract(origin.toVector()).multiply(0.7);

common/src/main/java/com/loohp/interactionvisualizer/blocks/SmokerDisplay.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ private ScheduledTask legacyRun() {
218218
if (!block.getType().equals(Material.SMOKER)) {
219219
return;
220220
}
221-
org.bukkit.block.Smoker smoker = (org.bukkit.block.Smoker) block.getState();
221+
org.bukkit.block.Smoker smoker = (org.bukkit.block.Smoker) block.getState(false);
222222

223223
{
224224
Inventory inv = smoker.getInventory();
@@ -337,7 +337,7 @@ private boolean updateHybridBlock(Block block) {
337337
values.putAll(spawnDisplayEntitys(block));
338338
smokerMap.put(block, values);
339339
}
340-
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState();
340+
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState(false);
341341
return FurnaceDisplayUpdater.update(furnace, values, KEY, progressBarCharacter, emptyColor,
342342
filledColor, noFuelColor, progressBarLength, amountPending);
343343
}
@@ -636,7 +636,7 @@ public Map<String, DisplayEntity> spawnDisplayEntitys(Block block) {
636636
Map<String, DisplayEntity> map = new HashMap<>();
637637
Location origin = block.getLocation();
638638

639-
BlockData blockData = block.getState().getBlockData();
639+
BlockData blockData = block.getBlockData();
640640
BlockFace facing = ((Directional) blockData).getFacing();
641641
Location target = block.getRelative(facing).getLocation();
642642
Vector direction = target.toVector().subtract(origin.toVector()).multiply(0.7);

common/src/main/java/com/loohp/interactionvisualizer/entities/DroppedItemDisplay.java

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,14 @@
2121
import com.loohp.interactionvisualizer.managers.PerformanceMetrics;
2222
import com.loohp.interactionvisualizer.objectholders.EntryKey;
2323
import com.loohp.interactionvisualizer.utils.ChatColorUtils;
24-
import com.loohp.interactionvisualizer.utils.ComponentFont;
2524
import com.loohp.interactionvisualizer.utils.ItemNameUtils;
25+
import com.loohp.interactionvisualizer.utils.LegacyTextComponentCache;
2626
import com.loohp.interactionvisualizer.scheduler.ScheduledRunnable;
2727
import com.loohp.interactionvisualizer.scheduler.ScheduledTask;
2828
import com.loohp.interactionvisualizer.scheduler.Scheduler;
2929
import net.kyori.adventure.text.Component;
3030
import net.kyori.adventure.text.TextReplacementConfig;
3131
import net.kyori.adventure.text.format.NamedTextColor;
32-
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
3332
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
3433
import org.bukkit.Bukkit;
3534
import org.bukkit.Color;
@@ -81,6 +80,7 @@ public final class DroppedItemDisplay extends VisualizerRunnableDisplay implemen
8180
private final Map<UUID, Item> trackedItems = new HashMap<>();
8281
private final Map<UUID, TextDisplay> labels = new HashMap<>();
8382
private final Set<UUID> eligibleViewers = new HashSet<>();
83+
private final Map<UUID, Player> desiredViewers = new HashMap<>();
8484
private final Map<UUID, VisibilityState> visibilityStates = new HashMap<>();
8585

8686
private String regularFormatting;
@@ -95,6 +95,7 @@ public final class DroppedItemDisplay extends VisualizerRunnableDisplay implemen
9595
private int ticksUntilUpdate;
9696
private int despawnTicks = 6000;
9797
private DroppedItemVisibilityPolicy visibilityPolicy = DroppedItemVisibilityPolicy.legacyDefaults();
98+
private boolean visibilityQueuesPending;
9899
private boolean stripColorBlacklist;
99100
private DroppedItemBlacklist blacklist = DroppedItemBlacklist.compile(List.of(), DroppedItemDisplay::warn);
100101

@@ -448,30 +449,32 @@ private static void setLabelVerticalTranslation(TextDisplay label, float targetY
448449
}
449450

450451
private Collection<Player> reconcileEligibleViewers() {
451-
Map<UUID, Player> desired = new HashMap<>();
452+
desiredViewers.clear();
452453
for (Player player : InteractionVisualizerAPI.getPlayerModuleList(Modules.HOLOGRAM, KEY)) {
453454
if (player.isOnline()) {
454-
desired.put(player.getUniqueId(), player);
455+
desiredViewers.put(player.getUniqueId(), player);
455456
}
456457
}
457-
for (UUID uuid : new HashSet<>(eligibleViewers)) {
458-
if (!desired.containsKey(uuid)) {
458+
Iterator<UUID> eligibleIterator = eligibleViewers.iterator();
459+
while (eligibleIterator.hasNext()) {
460+
UUID uuid = eligibleIterator.next();
461+
if (!desiredViewers.containsKey(uuid)) {
459462
Player player = Bukkit.getPlayer(uuid);
460463
if (visibilityPolicy.controlsPerViewerVisibility()) {
461464
removeVisibilityState(uuid, player);
462465
} else if (player != null) {
463466
setAllLabelsVisible(player, false);
464467
}
465-
eligibleViewers.remove(uuid);
468+
eligibleIterator.remove();
466469
}
467470
}
468-
for (Map.Entry<UUID, Player> entry : desired.entrySet()) {
471+
for (Map.Entry<UUID, Player> entry : desiredViewers.entrySet()) {
469472
if (eligibleViewers.add(entry.getKey())
470473
&& !visibilityPolicy.controlsPerViewerVisibility()) {
471474
setAllLabelsVisible(entry.getValue(), true);
472475
}
473476
}
474-
return desired.values();
477+
return desiredViewers.values();
475478
}
476479

477480
private void switchVisibilityMode(boolean controlled) {
@@ -485,6 +488,7 @@ private void switchVisibilityMode(boolean controlled) {
485488
state.pending.clear();
486489
}
487490
visibilityStates.clear();
491+
visibilityQueuesPending = false;
488492
}
489493

490494
private void showToEligibleViewers(TextDisplay label) {
@@ -519,7 +523,8 @@ private void reconcileLabelVisibility(Collection<Player> viewers, List<TrackedIt
519523
UUID playerId = player.getUniqueId();
520524
VisibilityState state = visibilityStates.computeIfAbsent(playerId,
521525
ignored -> new VisibilityState(visibilityPolicy.bucketSize()));
522-
Set<UUID> desired = new HashSet<>();
526+
Set<UUID> desired = state.nextDesired;
527+
desired.clear();
523528
Location playerLocation = player.getLocation();
524529
int trackingDistance = InteractionVisualizer.playerTrackingRange
525530
.getOrDefault(player.getWorld(), DEFAULT_TRACKING_DISTANCE);
@@ -546,49 +551,65 @@ private void reconcileLabelVisibility(Collection<Player> viewers, List<TrackedIt
546551
}
547552
}
548553

549-
for (UUID itemId : new HashSet<>(state.shown)) {
554+
Iterator<UUID> shownIterator = state.shown.iterator();
555+
while (shownIterator.hasNext()) {
556+
UUID itemId = shownIterator.next();
550557
if (!desired.contains(itemId)) {
551558
TextDisplay label = labels.get(itemId);
552559
if (label != null && label.isValid()) {
553560
setLabelVisible(player, label, false);
554561
}
555-
state.shown.remove(itemId);
562+
shownIterator.remove();
556563
}
557564
}
558565
for (UUID itemId : state.desired) {
559566
if (!desired.contains(itemId)) {
560567
state.pending.cancel(itemId);
561568
}
562569
}
570+
state.nextDesired = state.desired;
563571
state.desired = desired;
564572
for (UUID itemId : desired) {
565573
if (!state.shown.contains(itemId)) {
566574
state.pending.request(itemId);
575+
visibilityQueuesPending = true;
567576
}
568577
}
569578
}
570579
}
571580

572581
private void drainVisibilityQueues() {
582+
if (!visibilityQueuesPending) {
583+
return;
584+
}
585+
boolean stillPending = false;
573586
for (Map.Entry<UUID, VisibilityState> entry : visibilityStates.entrySet()) {
574587
Player player = Bukkit.getPlayer(entry.getKey());
575588
VisibilityState state = entry.getValue();
576589
if (player == null || !player.isOnline() || !eligibleViewers.contains(entry.getKey())) {
590+
state.pending.clear();
577591
continue;
578592
}
579-
List<UUID> ready = visibilityPolicy.rateLimitEnabled()
580-
? state.pending.drain(
581-
visibilityPolicy.bucketSize(), visibilityPolicy.restorePerTick(),
582-
id -> isPendingVisibilityWanted(state, id))
583-
: state.pending.drainAll(id -> isPendingVisibilityWanted(state, id));
593+
List<UUID> ready = state.ready;
594+
ready.clear();
595+
if (visibilityPolicy.rateLimitEnabled()) {
596+
state.pending.drainInto(
597+
visibilityPolicy.bucketSize(), visibilityPolicy.restorePerTick(),
598+
id -> isPendingVisibilityWanted(state, id), ready);
599+
} else {
600+
state.pending.drainAllInto(id -> isPendingVisibilityWanted(state, id), ready);
601+
}
584602
for (UUID itemId : ready) {
585603
TextDisplay label = labels.get(itemId);
586604
if (label != null && label.isValid()) {
587605
setLabelVisible(player, label, true);
588606
state.shown.add(itemId);
589607
}
590608
}
609+
ready.clear();
610+
stillPending |= state.pending.hasPending();
591611
}
612+
visibilityQueuesPending = stillPending;
592613
}
593614

594615
private boolean isPendingVisibilityWanted(VisibilityState state, UUID itemId) {
@@ -627,7 +648,7 @@ private Component format(ItemStack stack, int ticksLeft) {
627648
template = amount == 1 ? singularFormatting : regularFormatting;
628649
}
629650
String rendered = template.replace("{Amount}", Integer.toString(amount)).replace("{Timer}", timer);
630-
Component component = ComponentFont.parseFont(LegacyComponentSerializer.legacySection().deserialize(rendered));
651+
Component component = LegacyTextComponentCache.parse(rendered);
631652
return component.replaceText(TextReplacementConfig.builder()
632653
.matchLiteral("{Item}")
633654
.replacement(ItemNameUtils.getDisplayName(stack))
@@ -708,8 +729,10 @@ private record TrackedItem(UUID itemId, Item item, UUID worldId, Location locati
708729
private static final class VisibilityState {
709730

710731
private Set<UUID> desired = new HashSet<>();
732+
private Set<UUID> nextDesired = new HashSet<>();
711733
private final Set<UUID> shown = new HashSet<>();
712734
private final VisibilityTokenBucket<UUID> pending;
735+
private final List<UUID> ready = new ArrayList<>();
713736

714737
private VisibilityState(int initialTokens) {
715738
this.pending = new VisibilityTokenBucket<>(initialTokens);

common/src/main/java/com/loohp/interactionvisualizer/entities/VisibilityTokenBucket.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import java.util.ArrayDeque;
1515
import java.util.ArrayList;
16+
import java.util.Collection;
1617
import java.util.Deque;
1718
import java.util.HashSet;
1819
import java.util.List;
@@ -41,14 +42,20 @@ void cancel(T value) {
4142
}
4243

4344
List<T> drain(int capacity, int refill, Predicate<T> stillWanted) {
45+
List<T> ready = new ArrayList<>();
46+
drainInto(capacity, refill, stillWanted, ready);
47+
return ready;
48+
}
49+
50+
void drainInto(int capacity, int refill, Predicate<T> stillWanted,
51+
Collection<? super T> ready) {
4452
int safeCapacity = Math.max(1, capacity);
4553
long replenished = (long) tokens + Math.max(0, refill);
4654
tokens = (int) Math.min(safeCapacity, replenished);
4755
if (tokens == 0 || pending.isEmpty()) {
48-
return List.of();
56+
return;
4957
}
5058

51-
List<T> ready = new ArrayList<>(Math.min(tokens, pending.size()));
5259
while (tokens > 0 && !pending.isEmpty()) {
5360
T value = pending.removeFirst();
5461
if (!queued.remove(value) || !stillWanted.test(value)) {
@@ -57,26 +64,29 @@ List<T> drain(int capacity, int refill, Predicate<T> stillWanted) {
5764
ready.add(value);
5865
tokens--;
5966
}
60-
return ready;
6167
}
6268

6369
List<T> drainAll(Predicate<T> stillWanted) {
64-
if (pending.isEmpty()) {
65-
return List.of();
66-
}
70+
List<T> ready = new ArrayList<>();
71+
drainAllInto(stillWanted, ready);
72+
return ready;
73+
}
6774

68-
List<T> ready = new ArrayList<>(pending.size());
75+
void drainAllInto(Predicate<T> stillWanted, Collection<? super T> ready) {
6976
while (!pending.isEmpty()) {
7077
T value = pending.removeFirst();
7178
if (queued.remove(value) && stillWanted.test(value)) {
7279
ready.add(value);
7380
}
7481
}
75-
return ready;
7682
}
7783

7884
void clear() {
7985
pending.clear();
8086
queued.clear();
8187
}
88+
89+
boolean hasPending() {
90+
return !pending.isEmpty();
91+
}
8292
}

0 commit comments

Comments
 (0)