Add player lookup and admin head management features#57
Open
Add player lookup and admin head management features#57
Conversation
Bugs fixed: - foundHeadsAlreadyCount always returned 0 (looked for non-existent top-level "heads" key), causing every player to see "You are the first to find this egg" — now iterates all player records correctly - Double head recording: HeadWorldController.playerCollectedHead manually wrote to the YAML list and then also called insertCollectedHead, recording each collection twice; removed the duplicate write - Integer == comparison in hasAlreadyCollectedHead and HeadWorldController used reference equality, which fails for coordinates outside JVM cache range (-128..127) — switched to Objects.equals() - debugheadhunt permission check used || instead of &&, requiring players to have BOTH the permission node and OP simultaneously; fixed to && - SKINSMAX was 9 but config contained 10 skins (indices 0-9), leaving skin 9 unreachable; corrected to 10 - Leading space in maven-shade-plugin shadedPattern removed - Version mismatch between pom.xml (1.1.1) and plugin.yml (1.2.0) — aligned pom.xml to 1.2.0 New features: - On startup, logs loaded player profile count and total heads collected - /heads [player] now accepts an optional player name so any sender (including console) can look up a specific player's egg count - /debugheadhunt clearheads [player] now accepts an optional player name, allowing console and admins to clear another player's heads; also updates their helmet and scoreboard if they are online - /leaderboard console output now shows "1. PlayerName - N heads" instead of the raw record toString() - Players who have already collected all available eggs are now blocked from continuing to collect more (LANG.HEAD.ALLHEADSCOLLECTED config key added) Dependency updates: - maven-compiler-plugin 3.8.1 → 3.13.0 - maven-shade-plugin 3.4.1 → 3.5.3 - lombok 1.18.30 → 1.18.36 - snakeyaml 2.0 → 2.3 - httpclient5 5.2 → 5.4.1 https://claude.ai/code/session_01JyfubfoVpre8dsRWa3K6Vx
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Inserts copper helmet into the progression between leather (25) and chainmail (100). Requires Minecraft 1.21.2+ (Material.COPPER_HELMET). https://claude.ai/code/session_01JyfubfoVpre8dsRWa3K6Vx
Copper armor was added in Minecraft 1.21.2; Material.COPPER_HELMET does not exist in the 1.20.4 API, causing a compilation error. Updated the Paper API dependency to 1.21.4-R0.1-SNAPSHOT and raised api-version in plugin.yml to 1.21 accordingly. https://claude.ai/code/session_01JyfubfoVpre8dsRWa3K6Vx
Previously, helmets were mapped via separate keys (LEATHERHELMET: 25,
CHAINMAILHELMET: 100, etc.) which required keeping two separate lists in
sync. Each milestone entry can now carry an optional 'helmet' field, so
adding or moving a milestone is a single edit in one place.
Config format change:
MINOR / MAJOR entries are either a plain number (no helmet) or a map:
- count: 50
helmet: LEATHER_HELMET
The parser in PluginConfig.parseMilestoneEntry() handles both forms and
logs a warning for any unrecognised Material name rather than crashing.
https://claude.ai/code/session_01JyfubfoVpre8dsRWa3K6Vx
Milestone counts used to be hardcoded values that had to be updated
manually whenever eggs were added or removed. They are now stored as
percentages of the total egg count and recomputed automatically every
time countHeadsInRegion() updates the total (i.e. on startup and via
/debugheadhunt countheads).
Config format change — each MILESTONES entry is now a percentage:
Plain number: - 8.0 (8% of total, no helmet)
With helmet: - percentage: 25.0
helmet: IRON_HELMET
PluginConfig.recomputeMilestones(int) clears and repopulates the
headMilestones map in-place, so HeadFindEvent's reference to the map
automatically reflects the updated counts without re-registration.
The computed milestone counts are logged to console after each scan.
https://claude.ai/code/session_01JyfubfoVpre8dsRWa3K6Vx
When FEATURE.DISABLEFLIGHT is TRUE the plugin:
- Strips allowFlight and isFlying from every non-exempt player on join,
overriding any grant made by another plugin or the server before the
join event fires (EventPriority.HIGHEST)
- Cancels PlayerToggleFlightEvent mid-session for the same player set,
as a secondary guard against plugins granting flight after join
- Sends LANG.FLIGHT.DISABLED message when flight is blocked
Exempt from restriction:
- Ops
- Players with playerheadhunt.flight.exempt permission
- Creative and Spectator mode players
New files / changes:
events/HeadHunterFlightControl.java — new listener + enforceFlight()
events/HeadHunterOnJoin.java — calls enforceFlight() on join
PluginConfig.java — flightDisabledFeatureEnabled,
langFlightDisabled fields
config.yml — FEATURE.DISABLEFLIGHT, LANG.FLIGHT
plugin.yml — playerheadhunt.flight.exempt perm
https://claude.ai/code/session_01JyfubfoVpre8dsRWa3K6Vx
saveDefaultConfig() only writes the file when it doesn't exist, so servers upgrading from an older version never received new config keys (e.g. LANG.FLIGHT.DISABLED). Objects.requireNonNull() then threw NPE before console was even assigned, causing a second NPE in onDisable. Fix: call getConfig().options().copyDefaults(true) + saveConfig() after saveDefaultConfig() so any missing keys are merged from the bundled default before PluginConfig reads them. Also guard onDisable against a null console so startup failures don't produce a second confusing stack trace. https://claude.ai/code/session_01JyfubfoVpre8dsRWa3K6Vx
Root cause: calling saveConfig() with copyDefaults(true) on startup tried to merge new structured MILESTONES defaults (percentage maps) into the server's existing config (plain integer lists), producing invalid YAML. On the next restart Bukkit could not parse the corrupt file, causing getString() to return null for keys that had always existed (e.g. LANG.HEAD.HEADCOLLECTIONMILESTONEREACHED), which then hit requireNonNull. Fixes: - Remove saveConfig() from onEnable entirely. copyDefaults(true) alone is sufficient: Bukkit's getConfig() already sets the bundled config.yml as the defaults source, so any key absent from the server file is served from the in-memory defaults without touching disk. - Replace every Objects.requireNonNull(config.getString(...)) in PluginConfig with a lang() helper that calls config.getString() directly (which falls back to bundled defaults automatically) and logs a warning + returns "" if somehow still null, rather than crashing the server. Note: if your config.yml was already corrupted by the previous build, delete plugins/PlayerHeadHunt/config.yml and restart to regenerate it. https://claude.ai/code/session_01JyfubfoVpre8dsRWa3K6Vx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR enhances the PlayerHeadHunt plugin with player lookup capabilities and improved admin commands for managing player head collections. It refactors data access patterns to use a single source of truth and adds new utility methods for querying player statistics.
Key Changes
New Player Lookup Features
foundHeadsCountByName()method to query head counts by player nameclearHeadsByName()method to clear heads for a named player (works from console)/headscommand to support optional player argument:/heads [player]/debugheadhunt clearheadsto support clearing heads for named players:/debugheadhunt clearheads [player]Data Access Refactoring
foundHeadsAlreadyCount()to iterate through all players instead of assuming a flat "heads" list, making it consistent with actual data structureHeadWorldController.playerCollectedHead()- now delegates toHeadQuery.insertCollectedHead()as single source of truthhasAlreadyCollectedHead()to useObjects.equals()for safer integer comparisonsNew Utility Methods
getLoadedPlayerCount()to retrieve total number of loaded player profilesgetTotalHeadsCollectedAcrossAllPlayers()to get aggregate head collection statisticsUI/UX Improvements
targetPlayerHeadCountResponse()for displaying other players' head countsBug Fixes
debugheadhuntcommand (changed OR to AND for proper permission validation)Dependencies
Notable Implementation Details
foundHeadsAlreadyCount()now properly iterates through the player data structure, checking each player's collected heads against the specified coordinateshttps://claude.ai/code/session_01JyfubfoVpre8dsRWa3K6Vx