Skip to content

perf: refresh pickup lore once per player per tick - #75

Merged
XxFran10xX merged 1 commit into
mainfrom
perf/pickup-lore-once-per-tick
Nov 3, 2026
Merged

XxFran10xX merged 1 commit into
mainfrom
perf/pickup-lore-once-per-tick

Conversation

@XxFran10xX

Copy link
Copy Markdown
Contributor

What

Picking up several items in one tick now schedules one lore refresh for the player instead of one per item.

Why

Every player pickup scheduled a full-inventory lore refresh (VesselLore.updateInventory) for the next tick. Each refresh re-reads every item's lore (ArtifactLore.readAura), so picking up N items in one tick ran N identical refreshes. Coins are not affected, because DenarEconomy cancels their pickup. The cost is small (under 1.8 s/h on Main).

How

  • A per-player pending set. onPickup schedules the same SessionGuard.runLater(... updateInventory) only when none is pending, then a second runTask clears the mark.
  • Both tasks get the same next tick and consecutive task IDs, so the refresh always runs before the clear. Pickups fire from entity ticking, which runs after the scheduler heartbeat, so every pickup is still followed by a full refresh.
  • ArtifactLore.apply and ChargeLore.apply strip their own lore block and rebuild it from the item's data, so one refresh gives the same result as several.
  • One rare difference: a character switch between two pickups in the same tick gets no refresh until the next pickup or join. It only affects lore display.

Checked

  • Tests: 3 new ones in ArtifactListenerTest:
    • 5 pickups plus another player's in one tick give one refresh each, and a later pickup refreshes again;
    • a refresh skipped by a character switch doesn't block the next one;
    • nothing is queued while the plugin isn't running.
  • Coverage: ArtifactListener has 0 missed instructions, branches and lines. The full local suite fails only in Windows file-lock suites that this change doesn't touch.
  • Review: an independent review approved it, including the scheduler ordering.

Dev (TFMCDev01, 11-03)

  • Running as magic-BLOOD-PICKUP-250a7d7-DEV.jar: Blood Magic draft Add the hidden Blood Magic path #71 (2479d18) + the getHolder change + this commit. Same class list as the previous Dev jar; only ArtifactListener differs.
  • Test: a bot held a random artifact ("A Windless Primer On Winter", Seithr 0 / 16.42), and 6 cobblestone stacks were dropped at its feet in one burst.
  • Result: all 6 were picked up, the artifact's lore stayed byte-identical, and there were no errors.

Draft: not merged, not released, nothing on Main or Tutorial.

🤖 Generated with Claude Code

Every item a player picked up queued its own next-tick refresh of the
whole inventory's aura and charge lore, and each refresh re-reads the lore
of every item. Picking up a pile queued one full refresh per item entity.

The listener now queues one refresh per player per tick: further pickups
before it runs ride on it, since it reads the whole inventory then. That is
the same result as several refreshes, because ArtifactLore.apply and
ChargeLore.apply strip their own block and rebuild it from the item's
data. The queued mark is cleared by its own task, also when SessionGuard
skips the refresh (player gone or character switched), so the next pickup
always queues again. Coin pickups never reach this (DenarEconomy cancels
them).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Summary

Summary by CodeRabbit

  • Bug Fixes
    • Artifact lore refreshes are now coordinated when items are picked up, preventing repeated refreshes during the same game tick while allowing later pickups to refresh again.
    • Refreshes are safely skipped when a player’s character changes before the update runs, and pickup events no longer trigger refreshes when the plugin is unavailable.

ArtifactListener now coalesces pickup-triggered inventory lore refreshes per player until a next-tick task clears the pending UUID. It ignores non-player pickups and pickups when Magic.plugin is null. Tests cover coalescing and retry behaviour.

Changes: Artifact pickup refresh

Layer / File(s) Summary
Pickup refresh coalescing
src/main/java/net/tfminecraft/magic/listener/ArtifactListener.java, src/test/java/net/tfminecraft/magic/ArtifactListenerTest.java
onPickup skips non-player pickups and pickups when Magic.plugin is null. It queues one SessionGuard-protected inventory lore refresh per player until the pending UUID is cleared. Tests cover multiple players, later pickups, character changes and a null plugin.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Refactor

Suggested reviewers: ryanbarlow97

Merge Risk: Minimal · up to 42fe0

Pickup refreshes are batched per player. A character switch can defer a refresh until a later pickup or join; no merge-blocking issue was established.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

Share

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 6fa90c51-20fe-44d2-a633-a87bbd0692e8
Commits

Reviewing files that changed from the base of the PR and between d58db3d and 42fe0df.

Files selected for processing: 2
  • src/main/java/net/tfminecraft/magic/listener/ArtifactListener.java
  • src/test/java/net/tfminecraft/magic/ArtifactListenerTest.java

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@github-actions github-actions Bot added the size:S 10-29 effective changed lines (tests excluded in mixed PRs). label Nov 3, 2026
@XxFran10xX
XxFran10xX marked this pull request as ready for review November 3, 2026 20:45
@XxFran10xX

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@XxFran10xX
XxFran10xX merged commit caba970 into main Nov 3, 2026
4 checks passed
@XxFran10xX
XxFran10xX deleted the perf/pickup-lore-once-per-tick branch November 3, 2026 21:00
XxFran10xX added a commit that referenced this pull request Nov 6, 2026
…ly changed slots (#76)

* perf: refresh pickup lore only on items that can carry it, and set only changed slots

Each pickup (once per player per tick since #75) ran both lore writers over
all 41 inventory slots and set every slot back. For an ordinary item that
meant about eight copies of its meta, its lore read twice and run through
regexes (ArtifactLore.readAura), all to change nothing, and then a slot
packet per slot. On Main at 15+ players that was ~3 s of main thread per hour.

VesselLore now reads an item's meta once to tell whether a writer can touch
it: aura or charge-tier data, a charge item match, or lore with a "/" (an aura
line that readAura could read back). Other items come back unchanged, as both
writers left them before. The inventory refresh sets a slot again only when
its item changed; unchanged slots were only resent to the client.

Lore output is the same: artifacts and charges still go through the same
writers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skip items without meta before any lookup, and test an artifact slot

Review: both writers skip an item without meta, so do that first instead of
looking up keys and charge matches on it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Prove skipped items reach neither writer, and cover the no-meta skip

Review: the plain-item test could not tell the skip from the old path, and
MockBukkit's item factory never reports an empty meta.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: XxFran10xX <318299142+XxFran10xX@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 effective changed lines (tests excluded in mixed PRs).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant