Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 6, 2025

  • Analyze the issue: User changes chassis color/pattern/booster/emblem, then changes heraldry separately, but heraldry settings overwrite chassis settings
  • Explore codebase to understand cosmetic loadout handling
  • Identify the problem in LoadoutEquipItem function
  • Understand how to differentiate chassis vs heraldry equipment (via PanelID)
  • Fix LoadoutEquipItem to respect separate chassis and heraldry settings
  • Add tests for the fix
  • Build and test the changes
  • Run EVR tests
  • Format code with gofmt

Root Cause Identified:
In server/evr_profile_cache.go, the LoadoutEquipItem function unconditionally updates BOTH chassis and heraldry/body slots when equipping tint, pattern, or decal items:

  • Lines 390-391: Decal updates both Decal (chassis) and DecalBody (heraldry)
  • Lines 402-404: Tint updates both Tint (chassis) and TintBody (heraldry)
  • Lines 407-408: Pattern updates both Pattern (chassis) and PatternBody (heraldry)

The ApplyHeraldryTint field exists in the data model but is never used. The system needs to track which panel (chassis vs heraldry) the user is equipping from to apply changes correctly.

Original prompt

This section details on the original issue you should resolve

<issue_title>chassis and heraldry</issue_title>
<issue_description>i changed my entire loadout

i changed my chassis color, my booster, my pattern, and emblem.

i then made my heraldry something different than my chassis

i expected it to stick like normal

instead everything on my heraldry stuck rather than my chassis</issue_description>

Comments on the Issue (you are @copilot in this section)

@thesprockee @copilot

analyze this ticket, then review the codebase, and create a PR to resolve the issue.</comment_new>


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

thesprockee and others added 20 commits October 15, 2025 12:40
- Implement BeforeWriteStorageObjectsHook and BeforeDeleteStorageObjectsHook to enforce StorageObjects intent (or IsGlobalOperator) and block unauthorized write/delete requests by returning nil.
- Clarify AfterReadStorageObjectsHook comment to specify retry when zero objects were returned.
- Small TODO placement fix in BeforeListMatchesHook.
- Comment out registration of the BeforeWriteStorageObjects guard in registerAPIGuards.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Andrew Bates <a@sprock.io>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Andrew Bates <a@sprock.io>
* Initial plan

* Add nakama-debug to .gitignore

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Co-authored-by: Andrew Bates <a@sprock.io>
…tion (#124)

* Initial plan

* Extract common storage authorization logic into helper function

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Co-authored-by: Andrew Bates <a@sprock.io>
…ing (#127)

* Initial plan

* Add novalidation tag support for game server registration

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Add documentation for novalidation tag

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Use constant for novalidation tag to avoid magic string

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Make audit message sending async and clarify documentation

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Co-authored-by: Andrew Bates <a@sprock.io>
…ions (#128)

* Initial plan

* Extract common authorization logic into helper function

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

---------

Signed-off-by: Andrew Bates <a@sprock.io>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Co-authored-by: Andrew Bates <a@sprock.io>
…130)

* Initial plan

* Add nakama-debug to .gitignore

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Conditionally show moderator Discord ID in suspension embeds

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Add tests for conditional enforcer ID display in suspension embeds

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Co-authored-by: Andrew Bates <a@sprock.io>
* Initial plan

* Initial analysis - Identify error message improvement needed

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Update error messages to include internal IP, external IP, and port

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Co-authored-by: Andrew Bates <a@sprock.io>
Use the loop variable (gID) instead of the outer groupID when calling
createSuspensionDetailsEmbedField so each embed field references the
correct guild instead of always using the current group.
* Initial plan

* Initial plan for fixing Past Display Names embed bug

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Fix Past Display Names embed bug and add missing ServerEventsPublish method

- Fixed timestamp assignment bug in createPastDisplayNameEmbed where variable 'e' was being assigned instead of 'ts'
- Added comprehensive test coverage for createPastDisplayNameEmbed function
- Fixed Satori build issue by implementing missing ServerEventsPublish method

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Co-authored-by: Andrew Bates <a@sprock.io>
* Added IGN Override lock toggle and interaction for user metadata

* Update server/evr_discord_appbot_handlers.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Andrew Bates <a@sprock.io>

* Update server/evr_discord_appbot_igp.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Andrew Bates <a@sprock.io>

* Update server/evr_discord_appbot.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Andrew Bates <a@sprock.io>

---------

Signed-off-by: Andrew Bates <a@sprock.io>
Co-authored-by: Andrew Bates <a@sprock.io>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Andrew Bates <a@sprock.io>
…gs (#131)

* Initial plan

* Add daily average player loudness leaderboard stat

- Add PlayerLoudnessStatisticID constant
- Process VOIP_LOUDNESS remote logs to accumulate loudness data
- Track total loudness, min, max, and count per player
- Store metadata (min_loudness, max_loudness, count) in leaderboard records
- Queue leaderboard updates with daily reset schedule
- Add unit tests for loudness accumulation and average calculation
- Fix satori interface compilation issue with stub method

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Add documentation for PlayerLoudness leaderboard stat

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Fix metadata type handling and documentation format

- Fix metadata parsing to handle string values correctly (was trying to parse as float64)
- Remove incorrect comment syntax from markdown documentation
- Add test verification for metadata parsing

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Add error handling for metadata parsing and fix documentation

- Add error handling for fmt.Sscanf calls with warning logs
- Update documentation example to show correct string-based metadata parsing
- Ensures parsing failures are logged instead of silently failing

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Refactor to use strconv instead of fmt.Sscanf for parsing

- Replace fmt.Sscanf with strconv.ParseFloat/ParseInt for better performance
- Update all code and documentation to use strconv functions
- More appropriate and efficient for string-to-number conversion
- All tests still pass with the new approach

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Improve error messages and clarify comments

- Add more context to error messages for debugging
- Include match ID in player not found error
- Include team info in non-playing team error
- Clarify that average calculation happens when reading data, not storing

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Fix error message format and improve function documentation

- Fix format string in team validation error (removed missing %d placeholders)
- Update ServerEventsPublish comment to follow Go documentation conventions

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

* Remove satori modifications - not needed for this feature

Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Co-authored-by: Andrew Bates <a@sprock.io>
Copilot AI requested a review from thesprockee November 6, 2025 13:44
Base automatically changed from evr.202 to main November 11, 2025 04:12
Signed-off-by: Andrew Bates <a@sprock.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants