From 937f8dd76fa70e5cd11e281979bef2d72e94913e Mon Sep 17 00:00:00 2001 From: MrlingXD <90316914+wling-art@users.noreply.github.com> Date: Mon, 17 Aug 2026 15:42:04 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20O(n=C2=B2)=20item=20cramp=20check=20and?= =?UTF-8?q?=20cache=20per-cycle=20display=20names?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entities/ItemDisplay.java | 46 ++++++++++++++++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/common/src/main/java/com/loohp/interactionvisualizer/entities/ItemDisplay.java b/common/src/main/java/com/loohp/interactionvisualizer/entities/ItemDisplay.java index 2433f8ea..d14e47c6 100644 --- a/common/src/main/java/com/loohp/interactionvisualizer/entities/ItemDisplay.java +++ b/common/src/main/java/com/loohp/interactionvisualizer/entities/ItemDisplay.java @@ -55,8 +55,10 @@ import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -142,23 +144,28 @@ public void run() { return; } i = updateRate; + Map nameCache = new ConcurrentHashMap<>(); for (World world : Bukkit.getWorlds()) { WrappedIterable itr = NMS.getInstance().getEntities(world); Set items = new HashSet<>(); + Map> grid = new HashMap<>(); for (Entity entity : itr) { if (entity instanceof Item) { - items.add((Item) entity); + Item item = (Item) entity; + items.add(item); + Location itemLoc = item.getLocation(); + grid.computeIfAbsent(blockKey(itemLoc.getBlockX(), itemLoc.getBlockY(), itemLoc.getBlockZ()), k -> new ArrayList<>()).add(item); } } for (Item item : items) { - SyncUtils.runAsyncWithSyncCondition(item.getLocation(), item::isValid, () -> tick(item, items)); + SyncUtils.runAsyncWithSyncCondition(item.getLocation(), item::isValid, () -> tick(item, grid, nameCache)); } } } }.runTaskTimer(InteractionVisualizer.plugin, 0, 1); } - private void tick(Item item, Collection items) { + private void tick(Item item, Map> grid, Map nameCache) { try { World world = item.getWorld(); Location location = item.getLocation(); @@ -172,11 +179,11 @@ private void tick(Item item, Collection items) { itemstack = itemstack.clone(); } ItemStack finalItemstack = itemstack; - Component name = ItemNameUtils.getDisplayName(finalItemstack); + Component name = nameCache.computeIfAbsent(finalItemstack, ItemNameUtils::getDisplayName); String matchingname = getMatchingName(finalItemstack, stripColorBlacklist); if (!blacklist.test(matchingname, finalItemstack.getType())) { - if (item.getPickupDelay() >= Short.MAX_VALUE || ticks < 0 || isCramping(world, area, items)) { + if (item.getPickupDelay() >= Short.MAX_VALUE || ticks < 0 || isCramping(world, area, grid, location)) { List watcher = NMS.getInstance().resetCustomNameWatchableCollection(item); Object defaultPacket = NMS.getInstance() .createEntityMetadataPacket(item.getEntityId(), watcher); @@ -301,15 +308,40 @@ private String getMatchingName(ItemStack item, boolean stripColor) { return ""; } - private boolean isCramping(World world, BoundingBox area, Collection items) { + private boolean isCramping(World world, BoundingBox area, Map> grid, Location location) { if (cramp <= 0) { return false; } try { - return items.stream().filter(each -> each != null && each.getWorld().equals(world) && area.contains(each.getLocation().toVector())).skip(cramp).findAny().isPresent(); + int bx = location.getBlockX(); + int by = location.getBlockY(); + int bz = location.getBlockZ(); + int count = 0; + for (int dx = -1; dx <= 1; dx++) { + for (int dy = -1; dy <= 1; dy++) { + for (int dz = -1; dz <= 1; dz++) { + List bucket = grid.get(blockKey(bx + dx, by + dy, bz + dz)); + if (bucket == null) { + continue; + } + for (Item each : bucket) { + if (each != null && each.getWorld().equals(world) && area.contains(each.getLocation().toVector())) { + if (++count > cramp) { + return true; + } + } + } + } + } + } + return false; } catch (Throwable e) { return false; } } + private static long blockKey(int x, int y, int z) { + return ((x & 0x3FFFFFFL) << 38) | ((y & 0xFFFL) << 26) | (z & 0x3FFFFFFL); + } + }