Skip to content
Merged
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
1,657 changes: 1,657 additions & 0 deletions .github/workflows/upstream-runtime-comparison.yml

Large diffs are not rendered by default.

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions benchmark-runtime/src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: InteractionVisualizerRuntimeCompare
version: '1.0'
main: com.loohp.interactionvisualizer.benchmark.runtime.RuntimeComparisonPlugin
api-version: '26.1'
softdepend: [InteractionVisualizer]
description: Disposable target-independent runtime comparison driver for GitHub Actions
commands:
ivcompare:
description: Controls the disposable InteractionVisualizer runtime comparison
permission: interactionvisualizer.runtimecompare
permissions:
interactionvisualizer.runtimecompare:
default: op
21 changes: 21 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,18 @@ val benchmarkSourceSet = sourceSets.create("benchmark") {
runtimeClasspath += output + compileClasspath
}

val runtimeComparisonSourceSet = sourceSets.create("runtimeComparison") {
java.setSrcDirs(listOf("benchmark-runtime/src/main/java"))
resources.setSrcDirs(listOf("benchmark-runtime/src/main/resources"))
compileClasspath += configurations.compileClasspath.get()
runtimeClasspath += output + compileClasspath
}

sourceSets.test {
compileClasspath += runtimeComparisonSourceSet.output
runtimeClasspath += runtimeComparisonSourceSet.output
}

val benchmarkJar = tasks.register<Jar>("benchmarkJar") {
description = "Builds the standalone Paper A/B benchmark plugin (never shipped in production)."
group = LifecycleBasePlugin.VERIFICATION_GROUP
Expand All @@ -90,6 +102,14 @@ val benchmarkJar = tasks.register<Jar>("benchmarkJar") {
}
}

val runtimeComparisonJar = tasks.register<Jar>("runtimeComparisonJar") {
description = "Builds the target-independent Paper runtime comparison driver."
group = LifecycleBasePlugin.VERIFICATION_GROUP
dependsOn(runtimeComparisonSourceSet.classesTaskName)
archiveClassifier = "runtime-compare"
from(runtimeComparisonSourceSet.output)
}

tasks.withType<JavaCompile>().configureEach {
options.release = 25
options.encoding = "UTF-8"
Expand Down Expand Up @@ -237,6 +257,7 @@ tasks.check {
dependsOn(verifyPaperOnlyArchitecture)
dependsOn(verifyCustomContentIsolation)
dependsOn(testLegacyTextComponentCacheDisabled)
dependsOn(runtimeComparisonJar)
}

tasks.named<ShadowJar>("shadowJar") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.loohp.interactionvisualizer.managers.DisplayManager;
import com.loohp.interactionvisualizer.managers.PreferenceManager;
import com.loohp.interactionvisualizer.managers.PerformanceMetrics;
import com.loohp.interactionvisualizer.managers.PlayerLocationManager;
import com.loohp.interactionvisualizer.managers.TaskManager;
import com.loohp.interactionvisualizer.managers.TileEntityManager;
import com.loohp.interactionvisualizer.metrics.Charts;
Expand All @@ -45,6 +46,7 @@
import com.loohp.interactionvisualizer.updater.Updater.UpdaterResponse;
import com.loohp.interactionvisualizer.scheduler.Scheduler;
import com.loohp.interactionvisualizer.config.SparrowConfiguration;
import com.loohp.interactionvisualizer.utils.LegacyTextComponentCache;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
Expand Down Expand Up @@ -255,7 +257,11 @@ public void onDisable() {
if (preferenceManager != null) {
preferenceManager.close();
}
TaskManager.shutdown();
DisplayManager.shutdown();
TileEntityManager.shutdown();
PlayerLocationManager.clearCache();
LegacyTextComponentCache.invalidateAll();
if (asyncExecutorManager != null) {
asyncExecutorManager.close();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ public void updateBlock(Block block) {

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

org.bukkit.block.Beehive beehiveState = (org.bukkit.block.Beehive) block.getState();
org.bukkit.block.Beehive beehiveState = (org.bukkit.block.Beehive) block.getState(false);
org.bukkit.block.data.type.Beehive beehiveData = (org.bukkit.block.data.type.Beehive) block.getBlockData();

{
Expand Down Expand Up @@ -468,7 +468,7 @@ public boolean isActive(Location loc) {

public Map<String, DisplayEntity> spawnDisplayEntitys(Block block) {
Map<String, DisplayEntity> map = new HashMap<>();
BlockData blockData = block.getState().getBlockData();
BlockData blockData = block.getBlockData();
BlockFace facing = ((Directional) blockData).getFacing();

Location loc0 = labelLocation(block.getLocation(), facing, 0.25);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ public void updateBlock(Block block) {

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

org.bukkit.block.Beehive beehiveState = (org.bukkit.block.Beehive) block.getState();
org.bukkit.block.Beehive beehiveState = (org.bukkit.block.Beehive) block.getState(false);
org.bukkit.block.data.type.Beehive beehiveData = (org.bukkit.block.data.type.Beehive) block.getBlockData();

{
Expand Down Expand Up @@ -468,7 +468,7 @@ public boolean isActive(Location loc) {

public Map<String, DisplayEntity> spawnDisplayEntitys(Block block) {
Map<String, DisplayEntity> map = new HashMap<>();
BlockData blockData = block.getState().getBlockData();
BlockData blockData = block.getBlockData();
BlockFace facing = ((Directional) blockData).getFacing();

Location loc0 = labelLocation(block.getLocation(), facing, 0.25);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ private ScheduledTask legacyRun() {
if (!block.getType().equals(Material.BLAST_FURNACE)) {
return;
}
org.bukkit.block.BlastFurnace blastfurnace = (org.bukkit.block.BlastFurnace) block.getState();
org.bukkit.block.BlastFurnace blastfurnace = (org.bukkit.block.BlastFurnace) block.getState(false);

{
Inventory inv = blastfurnace.getInventory();
Expand Down Expand Up @@ -336,7 +336,7 @@ private boolean updateHybridBlock(Block block) {
values.putAll(spawnDisplayEntitys(block));
blastfurnaceMap.put(block, values);
}
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState();
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState(false);
return FurnaceDisplayUpdater.update(furnace, values, KEY, progressBarCharacter, emptyColor,
filledColor, noFuelColor, progressBarLength, amountPending);
}
Expand Down Expand Up @@ -628,7 +628,7 @@ public Map<String, DisplayEntity> spawnDisplayEntitys(Block block) {
Map<String, DisplayEntity> map = new HashMap<>();
Location origin = block.getLocation();

BlockData blockData = block.getState().getBlockData();
BlockData blockData = block.getBlockData();
BlockFace facing = ((Directional) blockData).getFacing();
Location target = block.getRelative(facing).getLocation();
Vector direction = target.toVector().subtract(origin.toVector()).multiply(0.7);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ private ScheduledTask legacyRun() {
if (!isFurnace(block.getType())) {
return;
}
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState();
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState(false);

{
Inventory inv = furnace.getInventory();
Expand Down Expand Up @@ -335,7 +335,7 @@ private boolean updateHybridBlock(Block block) {
values.putAll(spawnDisplayEntitys(block));
furnaceMap.put(block, values);
}
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState();
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState(false);
return FurnaceDisplayUpdater.update(furnace, values, KEY, progressBarCharacter, emptyColor,
filledColor, noFuelColor, progressBarLength, amountPending);
}
Expand Down Expand Up @@ -624,7 +624,7 @@ public Map<String, DisplayEntity> spawnDisplayEntitys(Block block) {
Map<String, DisplayEntity> map = new HashMap<>();
Location origin = block.getLocation();

BlockData blockData = block.getState().getBlockData();
BlockData blockData = block.getBlockData();
BlockFace facing = ((Directional) blockData).getFacing();
Location target = block.getRelative(facing).getLocation();
Vector direction = target.toVector().subtract(origin.toVector()).multiply(0.7);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ private ScheduledTask legacyRun() {
if (!block.getType().equals(Material.SMOKER)) {
return;
}
org.bukkit.block.Smoker smoker = (org.bukkit.block.Smoker) block.getState();
org.bukkit.block.Smoker smoker = (org.bukkit.block.Smoker) block.getState(false);

{
Inventory inv = smoker.getInventory();
Expand Down Expand Up @@ -337,7 +337,7 @@ private boolean updateHybridBlock(Block block) {
values.putAll(spawnDisplayEntitys(block));
smokerMap.put(block, values);
}
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState();
org.bukkit.block.Furnace furnace = (org.bukkit.block.Furnace) block.getState(false);
return FurnaceDisplayUpdater.update(furnace, values, KEY, progressBarCharacter, emptyColor,
filledColor, noFuelColor, progressBarLength, amountPending);
}
Expand Down Expand Up @@ -636,7 +636,7 @@ public Map<String, DisplayEntity> spawnDisplayEntitys(Block block) {
Map<String, DisplayEntity> map = new HashMap<>();
Location origin = block.getLocation();

BlockData blockData = block.getState().getBlockData();
BlockData blockData = block.getBlockData();
BlockFace facing = ((Directional) blockData).getFacing();
Location target = block.getRelative(facing).getLocation();
Vector direction = target.toVector().subtract(origin.toVector()).multiply(0.7);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@
import com.loohp.interactionvisualizer.managers.PerformanceMetrics;
import com.loohp.interactionvisualizer.objectholders.EntryKey;
import com.loohp.interactionvisualizer.utils.ChatColorUtils;
import com.loohp.interactionvisualizer.utils.ComponentFont;
import com.loohp.interactionvisualizer.utils.ItemNameUtils;
import com.loohp.interactionvisualizer.utils.LegacyTextComponentCache;
import com.loohp.interactionvisualizer.scheduler.ScheduledRunnable;
import com.loohp.interactionvisualizer.scheduler.ScheduledTask;
import com.loohp.interactionvisualizer.scheduler.Scheduler;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.Color;
Expand Down Expand Up @@ -81,6 +80,7 @@ public final class DroppedItemDisplay extends VisualizerRunnableDisplay implemen
private final Map<UUID, Item> trackedItems = new HashMap<>();
private final Map<UUID, TextDisplay> labels = new HashMap<>();
private final Set<UUID> eligibleViewers = new HashSet<>();
private final Map<UUID, Player> desiredViewers = new HashMap<>();
private final Map<UUID, VisibilityState> visibilityStates = new HashMap<>();

private String regularFormatting;
Expand All @@ -95,6 +95,7 @@ public final class DroppedItemDisplay extends VisualizerRunnableDisplay implemen
private int ticksUntilUpdate;
private int despawnTicks = 6000;
private DroppedItemVisibilityPolicy visibilityPolicy = DroppedItemVisibilityPolicy.legacyDefaults();
private boolean visibilityQueuesPending;
private boolean stripColorBlacklist;
private DroppedItemBlacklist blacklist = DroppedItemBlacklist.compile(List.of(), DroppedItemDisplay::warn);

Expand Down Expand Up @@ -448,30 +449,32 @@ private static void setLabelVerticalTranslation(TextDisplay label, float targetY
}

private Collection<Player> reconcileEligibleViewers() {
Map<UUID, Player> desired = new HashMap<>();
desiredViewers.clear();
for (Player player : InteractionVisualizerAPI.getPlayerModuleList(Modules.HOLOGRAM, KEY)) {
if (player.isOnline()) {
desired.put(player.getUniqueId(), player);
desiredViewers.put(player.getUniqueId(), player);
}
}
for (UUID uuid : new HashSet<>(eligibleViewers)) {
if (!desired.containsKey(uuid)) {
Iterator<UUID> eligibleIterator = eligibleViewers.iterator();
while (eligibleIterator.hasNext()) {
UUID uuid = eligibleIterator.next();
if (!desiredViewers.containsKey(uuid)) {
Player player = Bukkit.getPlayer(uuid);
if (visibilityPolicy.controlsPerViewerVisibility()) {
removeVisibilityState(uuid, player);
} else if (player != null) {
setAllLabelsVisible(player, false);
}
eligibleViewers.remove(uuid);
eligibleIterator.remove();
}
}
for (Map.Entry<UUID, Player> entry : desired.entrySet()) {
for (Map.Entry<UUID, Player> entry : desiredViewers.entrySet()) {
if (eligibleViewers.add(entry.getKey())
&& !visibilityPolicy.controlsPerViewerVisibility()) {
setAllLabelsVisible(entry.getValue(), true);
}
}
return desired.values();
return desiredViewers.values();
}

private void switchVisibilityMode(boolean controlled) {
Expand All @@ -485,6 +488,7 @@ private void switchVisibilityMode(boolean controlled) {
state.pending.clear();
}
visibilityStates.clear();
visibilityQueuesPending = false;
}

private void showToEligibleViewers(TextDisplay label) {
Expand Down Expand Up @@ -519,7 +523,8 @@ private void reconcileLabelVisibility(Collection<Player> viewers, List<TrackedIt
UUID playerId = player.getUniqueId();
VisibilityState state = visibilityStates.computeIfAbsent(playerId,
ignored -> new VisibilityState(visibilityPolicy.bucketSize()));
Set<UUID> desired = new HashSet<>();
Set<UUID> desired = state.nextDesired;
desired.clear();
Location playerLocation = player.getLocation();
int trackingDistance = InteractionVisualizer.playerTrackingRange
.getOrDefault(player.getWorld(), DEFAULT_TRACKING_DISTANCE);
Expand All @@ -546,49 +551,65 @@ private void reconcileLabelVisibility(Collection<Player> viewers, List<TrackedIt
}
}

for (UUID itemId : new HashSet<>(state.shown)) {
Iterator<UUID> shownIterator = state.shown.iterator();
while (shownIterator.hasNext()) {
UUID itemId = shownIterator.next();
if (!desired.contains(itemId)) {
TextDisplay label = labels.get(itemId);
if (label != null && label.isValid()) {
setLabelVisible(player, label, false);
}
state.shown.remove(itemId);
shownIterator.remove();
}
}
for (UUID itemId : state.desired) {
if (!desired.contains(itemId)) {
state.pending.cancel(itemId);
}
}
state.nextDesired = state.desired;
state.desired = desired;
for (UUID itemId : desired) {
if (!state.shown.contains(itemId)) {
state.pending.request(itemId);
visibilityQueuesPending = true;
}
}
}
}

private void drainVisibilityQueues() {
if (!visibilityQueuesPending) {
return;
}
boolean stillPending = false;
for (Map.Entry<UUID, VisibilityState> entry : visibilityStates.entrySet()) {
Player player = Bukkit.getPlayer(entry.getKey());
VisibilityState state = entry.getValue();
if (player == null || !player.isOnline() || !eligibleViewers.contains(entry.getKey())) {
state.pending.clear();
continue;
}
List<UUID> ready = visibilityPolicy.rateLimitEnabled()
? state.pending.drain(
visibilityPolicy.bucketSize(), visibilityPolicy.restorePerTick(),
id -> isPendingVisibilityWanted(state, id))
: state.pending.drainAll(id -> isPendingVisibilityWanted(state, id));
List<UUID> ready = state.ready;
ready.clear();
if (visibilityPolicy.rateLimitEnabled()) {
state.pending.drainInto(
visibilityPolicy.bucketSize(), visibilityPolicy.restorePerTick(),
id -> isPendingVisibilityWanted(state, id), ready);
} else {
state.pending.drainAllInto(id -> isPendingVisibilityWanted(state, id), ready);
}
for (UUID itemId : ready) {
TextDisplay label = labels.get(itemId);
if (label != null && label.isValid()) {
setLabelVisible(player, label, true);
state.shown.add(itemId);
}
}
ready.clear();
stillPending |= state.pending.hasPending();
}
visibilityQueuesPending = stillPending;
}

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

private Set<UUID> desired = new HashSet<>();
private Set<UUID> nextDesired = new HashSet<>();
private final Set<UUID> shown = new HashSet<>();
private final VisibilityTokenBucket<UUID> pending;
private final List<UUID> ready = new ArrayList<>();

private VisibilityState(int initialTokens) {
this.pending = new VisibilityTokenBucket<>(initialTokens);
Expand Down
Loading
Loading