Repository navigation
perf: cheaper item-scan key checks and kept ItemsAdder templates - #98
Conversation
The TLibs item scan calls TagManager and LegacyFishScan matches() on every non-air slot ten times a second. Both copied the whole item meta (every component plus the custom data tag) just to test one key. They now read the key through ItemStack#getPersistentDataContainer, the read-only view, with the same keys and the same answers. ItemRef now keeps one built template per ItemsAdder ref and hands every caller its own clone, so food rebuilds stop asking ItemsAdder for a new copy each time. Only refs TLibs routes to ItemsAdder are kept: v. and modeled. are cheap, m. can roll random MMOItems stats, and prefixes with a TLibs path handler (c.) may differ per build. Failed builds (null, air, TLibs' dirt fallback) are never kept. The templates are only on while Cooking listens for ItemsAdderLoadDataEvent, and are cleared on every ItemsAdder load, on /cooking reload and when TLibs swaps its creator. needsLoreRebuild uses a precompiled colour-code pattern instead of compiling it per lore line; the output is identical. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Cache eligible item templates src/main/java/net/tfminecraft/cooking/utils/ItemRef.java, src/test/java/net/tfminecraft/cooking/utils/ItemRefTemplateCacheTest.java |
ItemRef caches eligible ItemsAdder item templates and returns cloned copies. Tests cover cache eligibility, reuse, invalidation, and build failures. |
Connect cache to ItemsAdder lifecycle src/main/java/net/tfminecraft/cooking/utils/ItemsAdderReloadHook.java, src/main/java/net/tfminecraft/cooking/Cooking.java, src/test/java/dev/lone/itemsadder/api/Events/ItemsAdderLoadDataEvent.java, src/test/java/net/tfminecraft/cooking/utils/ItemsAdderReloadHookTest.java |
Cooking registers the reload hook when ItemsAdder is available. Successful registration enables caching, and load events clear the cache. Shutdown disables caching, and configuration reload clears it. Tests cover registration and cache behaviour across load events. |
Read persistent data for item matching src/main/java/net/tfminecraft/cooking/fishing/LegacyFishScan.java, src/main/java/net/tfminecraft/cooking/fishing/SeafoodWholeItems.java, src/main/java/net/tfminecraft/cooking/manager/TagManager.java, src/test/java/net/tfminecraft/cooking/fishing/ScanMatchParityTest.java, src/test/java/net/tfminecraft/cooking/fishing/FishingRuntimeCoverageTest.java |
Fishing and tag matching read persistent data directly from item stacks. The parity tests compare updated matchers with reference checks. |
Reuse the lore colour-code pattern src/main/java/net/tfminecraft/cooking/utils/ItemUpdater.java, src/test/java/net/tfminecraft/cooking/utils/ItemLoreRebuildTest.java |
ItemUpdater reuses a compiled colour-code pattern. Tests compare the lore check with the previous rule across varied inputs. |
Priority:
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Refactor
Sequence Diagram(s)
sequenceDiagram
participant Cooking
participant ItemsAdderReloadHook
participant ItemRef
participant TLibs
Cooking->>ItemsAdderReloadHook: Register reload hook
ItemsAdderReloadHook->>ItemRef: Enable caching after registration
ItemRef->>TLibs: Build item on cache miss
ItemsAdderReloadHook->>ItemRef: Clear cache on load event
Suggested reviewers: ryanbarlow97
Merge Risk: 
Minimal · up to a7f03
-
The change reuses item templates and clears them on reload. No merge-blocking failure has been established.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
|
Dev test (TFMCDev01, 10-29 13:28–13:33 UTC, this PR's jar on its own;
|
|
@coderabbitai review |
✅ Action performed
|
Companion PR: TF-Minecraft/Magic#72 (same scan path, Magic's artifact key check).
Why
TLibs
ItemScanServicescans one player's inventory (plus any open container) every 2 ticks. It calls every registered handler'smatches()on every non-air slot, andupdate()when that returns true. Cooking registers two handlers:TagManager.matchescalledhasItemMeta()and thengetItemMeta()to test for thefood_idkey.LegacyFishScan.matchescalledgetItemMeta()on every fish.Inventory.getItemreturns a mirror, so eachgetItemMeta()builds a fullCraftMetaItem. That copies every component plus the whole custom-data tag, which is large on MMOItems and ItemsAdder items. This happened at least once per slot per handler, 10 scans a second, only to read one key.For food that matches, the update can rebuild the item.
ModelData.applythen goes throughItemRef.apply/resolve, which asked TLibs for a fresh template every time. Foria.*refs that meansCustomStack.getInstance(...).getItemStack(). Separately,ItemUpdater.needsLoreRebuildcompiled the§.regex once per lore line throughString.replaceAll.Changes
TagManager.matchesandLegacyFishScan.matchesnow read the key throughItemStack#getPersistentDataContainer(), the read-onlyPersistentDataContainerViewin Paper 1.21.10 API (confirmed in thepaper-api-1.21.10-R0.1-SNAPSHOTjar these poms compile against). They check the same keys with the same types.SeafoodWholeItems.carriesCatchDatanow takes the view interface;PersistentDataContainerextends it, so existing callers are unchanged.ItemRefkeeps ItemsAdder templates. It keeps one built template per ref string and gives every caller its ownclone().applyclones the kept template once and merges into the clone, so the kept template is never handed out or changed.ItemCreator.getItemFromPath).v.andmodeled.are not kept: they are cheap to build.m.is not kept: MMOItems builds can roll random stats or unique ids, so one kept copy would change what players get.magic.is not kept: it has no creation path.c.builds food with state, and handlers may build something different each time. This is checked on every call, so a prefix that gains a handler later stops being served from the cache.ItemsAdderReloadHooklistens forItemsAdderLoadDataEvent(first load and/iareload) and clears the cache on each one. Cooking does not compile against ItemsAdder, so the event class is loaded from ItemsAdder's own class loader and registered withregisterEvent; no pom, CI or plugin.yml change is needed. Templates are only switched on once this hook registers. Without ItemsAdder, or if the event is missing or refused, nothing is cached./cooking reload:reloadAll()clears the cache first.ItemCreator, the cache starts again from empty.onDisable: turns caching off.MMOItemsReloadEvent, but it fires only on/mi reload, not on/mi editchanges, andm.refs are not cached at all (see above). So no MMOItems hook is needed.needsLoreRebuilduses a precompiledPattern.compile("§.").String.replaceAll(regex, r)is defined asPattern.compile(regex).matcher(this).replaceAll(r), so the output is identical.Why behaviour is identical
getItemMeta().getPersistentDataContainer()read the samePublicBukkitValuescompound incustom_data, with the same type check. The droppedhasItemMeta()guard could only ever reject items whose PDC is empty, and those already answer false.ItemRefcaller run on the server thread. The cache is aConcurrentHashMapbehind a volatile reference, so a clear from any thread is safe, and a build that finishes after a clear writes into the discarded map.Testing
ScanMatchParityTestcomparesTagManager.matchesandLegacyFishScan.matchesagainst copies of the origin/main implementations. It covers null, air, items with and without meta, and the food id as text, as a number, or under another namespace. It also covers whole fish with and without catch data and the clean mark, on fish and non-fish materials.ItemRefTemplateCacheTest:applymerges never reach the template;ItemsAdderReloadHookTest: no ItemsAdder means nothing is cached; every load event clears the cache; a missing or unregistrable event class leaves caching off.ItemLoreRebuildTest.colourCodesAreStrippedExactlyAsBeforecompares against the oldreplaceAllacross about 530 lore pairs, including line breaks, surrogates, doubled§and trailing§.mvn -B -o clean verifyon Windows: 1286 tests, 0 failures, line-coverage gate passes.Dev testing on TFMCDev01 follows before this leaves draft.
🤖 Generated with Claude Code