Skip to content

Nebula invasion receiver: decode get-state lineup into Incident#370

Merged
jfberry merged 10 commits into
mainfrom
nebula-invasion-receiver
Jun 5, 2026
Merged

Nebula invasion receiver: decode get-state lineup into Incident#370
jfberry merged 10 commits into
mainfrom
nebula-invasion-receiver

Conversation

@jfberry

@jfberry jfberry commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Receiver side of Invasion Scanning V2: decode Nebula HTTP battle responses (forwarded by Dragonite) into the existing invasion-lineup storage.

  • Adds a typed NebulaContent message + nebula_contents field to grpc/raw_receiver.proto (byte-identical to the Dragonite copy), with a oneof context { InvasionContext invasion }.
  • Parses nebula_contents from both the gRPC (SubmitRawProto) and HTTP (/raw) inbound paths into a typed NebulaData.
  • New decodeNebula routes on the context oneof case (invasion now; raid/max are logged no-ops until built) and the endpoint; get-state decodes BattleStateOutProto, extracts the opponent actor's roster, and writes the existing Incident fields (slot_1/2/3_pokemon_id + confirmed) via the existing write-behind path. No DB schema changes — reuses the columns/webhook/API already in place.
  • Cross-repo wire round-trip test guards the two proto copies from drifting.

Notes for reviewers

  • Opponent-actor selection is provisional. With no captured get-state payload yet, it matches actors of type NPC/NPC_BOSS and orders slots best-effort. The decoder emits verbose debug logging of every actor (id/type/team/active/roster) precisely so this can be validated/corrected against production data before relying on the lineups.

Test Plan

  • go build ./... clean
  • go test . ./decoder/ ./grpc/ pass (context dispatch, BattleStateOutProto → Incident slot extraction, proto wire round-trip)
  • Production validation: capture a real get-state payload from the debug logs and confirm the opponent/slot mapping is correct

🤖 Generated with Claude Code

jfberry and others added 10 commits June 5, 2026 10:17
Validated against production get-state: the opponent's active pokemon has its
species revealed but the reserves carry PokedexId 0 at the opening state. The
old code wrote those as pokemon id 0; write NULL instead so an unknown reserve
isn't mistaken for "pokemon #0". Slot 1 (the lead) is reliably populated.

Also de-provisionalises the opponent-selection comment now that NPC/NPC_BOSS
is confirmed correct against real payloads. Adds a hidden-reserve test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
BattlePokemonProto carries Display.Form; the legacy OpenInvasion lineup path
set slot_N_form from it but updateFromBattleState only set the pokemon id.
Set the form alongside the species (form 0 = default form is a valid value),
restoring parity with the old flow. Only set when the species is known.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Print the resolved slot pokemon/form after extraction so the decoded lineup
is visible in logs during validation without a DB round-trip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The invasion webhook emitted all three slots whenever slot 1 was set, so
nebula lineups (which know only the lead pokemon) produced
{"slot":2,"pokemon_id":null,"form":null} noise. Build the lineup from only
the slots with a known pokemon. Full lineups (old OpenInvasion flow) are
unchanged; partial ones drop the null reserves.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jfberry jfberry force-pushed the nebula-invasion-receiver branch from 7fe204f to 5a80876 Compare June 5, 2026 09:20
@jfberry jfberry merged commit cafce5d into main Jun 5, 2026
4 checks passed
@jfberry jfberry deleted the nebula-invasion-receiver branch June 5, 2026 09:21
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.

1 participant