762 Commits

Author SHA1 Message Date
gamer147
8c9fe7a1b9 port(m1): wave 6e — Unity ctors + Unity/ZXing/SFB type stubs (444->362)
CS1729 Unity ctors: Plane(3pt), Texture2D(w,h,fmt,mip), Keyframe(4),
  AnimationCurve(params Keyframe[]), WebCamTexture(name,w,h,fps), UnityWebRequest(url,method).
CS0246 Unity: AnimationState, GUIContent, TextEditor, WebCamDevice, Display,
  WaitForSecondsRealtime, AnimationBlendMode + WebCamTexture.devices.
CS0246 SDK: SFB ExtensionFilter/StandaloneFileBrowser; ZXing BarcodeFormat/Result/
  BarcodeWriter/BarcodeReader/QrCodeEncodingOptions/ErrorCorrectionLevel.
NullBattleCardView parameterless ctor (CS7036).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 00:06:03 -04:00
gamer147
629ae6bf98 port(m1): wave 6d — Unity method/ctor overloads (572->444)
CS1501 overload gaps (Unity):
- Transform.TransformPoint/InverseTransformPoint(float,float,float); LookAt(.,worldUp) x2.
- Object.FindObjectsOfType(Type)/(bool); Instantiate<T>(.,pos,rot,parent).
- Component/GameObject.BroadcastMessage(string,object[,opts]).
- Animator.Play(string/int, layer[, normalizedTime]).
- Mathf.Min/Max(params float[]/int[]).
- MonoBehaviour.CancelInvoke(string).
CS1729: NullBattleCardView(BuildInfo) ctor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 00:00:11 -04:00
gamer147
9376b35db2 port(m1): wave 6c — Unity + Steam/FB/Adjust static-class shims (696->572)
Off-battle-path static surfaces (CS0103 cluster):
- UnityStatics: Gizmos, Physics2D, Caching, GUIUtility, Cursor, ColorUtility,
  ScreenCapture, RenderSettings, JsonUtility, Social + CursorLockMode enum.
- RaycastHit2D implicit-bool operator; ILocalUser in SocialPlatforms.
- Steamworks: Callback<T>.Create, AppId_t/CSteamID/HAuthTicket/SteamNetworkingIdentity,
  MicroTxn/GetAuthSessionTicket response structs, SteamAPI/User/Utils/Client statics.
  Removed empty dup GetAuthSessionTicketResponse_t from ThirdParty.cs.
- Facebook.Unity: FB + ILoginResult + FacebookDelegate<T>; com.adjust.sdk.Adjust;
  global TimeNativePlugin/Packsize native-plugin stubs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 23:56:52 -04:00
gamer147
755f7fd148 port(m1): wave 6b — View base members + app-type stubs (772->696)
- BattleCardView shim: GameObject, HandFrameEffect, GetCurrentIconLayout (fixes Player/EnemyClassBattleCardView.GameObject inheritance).
- BattlePlayerViewBase.AlwaysShowStatusPanel; NullBattleCardView.ReleaseSharedDummy.
- EvolutionTouchProcessor: 4 events (OnFocus/Unfocus/Select/NotSelect Target) hand-added — m1_stub_gen drops `event` decls.
- Generated full-surface stubs: StoryWorldDataManager, GenerateDeckCode, GameSetup, CommonPrefabContainer, ApplicationFinishManager, EvolutionConfirmation, ReplayDataHandler (hand stubs -> partial).
- Closure pulled by StoryWorldDataManager full-surface: 4 verbatim copies (StoryChapter/Summary/LeaderSelect dialogs, ClassIconName) + empty stubs StoryWorldData/BattleRecovery/ResourceDownloader/TemporaryAssetDeleter (non-battle, signature-only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 23:50:10 -04:00
gamer147
67f91e230e port(m1): wave 6a — GameMgr setters, Tab MonoBehaviour, OpeningVfx members, Vfx stubs (838->772)
- GameMgr.Is{Network,AINetwork,Watch,Replay,Puzzle,AdminWatch}Battle: read-only => settable (CS0200, Matching/NetworkBattleManagerBase assign them).
- Tab : MonoBehaviour (inherits Object.name; CS1061 x8).
- OpeningVfx: static OpenningLogStep, ShowBattleUIImmediatelyVfx (NullVfx, F1 contract), nested WaitVoiceEndVfx (CS0117/0426 x14).
- Generated no-op stubs EffectBattleVfxBase/SkillEffectBattleVfx/FallToGroundVfx/ThinkIconShowVfx (: SequentialVfxPlayer chain), baseclauses reattached.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 23:43:47 -04:00
gamer147
db76808e64 feat(battle-engine): re-attach interfaces dropped by base-clause recovery (958->838)
base-clause recovery strips interfaces (to dodge CS0535), but copied code converts
the stubs to those interfaces -> ~120 CS0266/CS1503. Two mechanisms:
- _IfaceImpl.g.cs: explicit no-op impls of the FULL (copied) interfaces, layered
  onto each hierarchy base (BattleCardView/CardVfxCreatorBase/BattlePlayerView/
  BattleEnemyView/ClassInfomationUIBase + NullCardVfxCreator). Explicit form never
  collides with existing members; leaves inherit. Walks base-interface chains
  (IPlayerView : IBattlePlayerView) and emits events.
- _InterfaceReattach.g.cs: plain ': IFoo' for the empty stub interfaces
  (IProcessing, IReplayRecordManager).
- ClassBattleCardViewBase/NullBattleCardView: restore dropped BattleCardView base
  so they inherit its IBattleCardView impl.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 23:33:14 -04:00
gamer147
be10425819 feat(battle-engine): VfxWith ctor arg order + Unity conversions + ITouchProcessor reattach (1102->958)
- VfxWith<T> ctor params were swapped ((T,VfxBase) vs decomp (VfxBase,T)) -> ~38
  CS1503 across SkillCollectionBase/BattleCardBase skill-processing (ProcessInfo
  <-> VfxBase). These are on the resolution path. Fixed to match decomp.
- UnityEngine primitives: implicit Vector3/Vector2<->Vector4 + Color->Color32
  conversions; Transform.Translate/Rotate(Vector3,Space) overloads (iTween).
- ITouchProcessor was dropped from touch-processor stubs by base-clause recovery;
  re-attach via Shim/View/TouchProcessorIfaces.cs (interface-only for generated
  full-surface stubs, interface+no-op members for the empty hand stubs).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 23:18:35 -04:00
gamer147
795f7a6bc8 feat(battle-engine): preserve ctor base-initializers + Event/Reward shims (1386->1226)
- Regenerate 31 VFX/View/UI/Touch stubs to keep their decomp ': base(...)' /
  ': this(...)' ctor initializers (m1_stub_gen was dropping them -> CS7036/CS1729
  when the copied base has no parameterless ctor). Whole base-ctor cluster cleared.
- UnityEngine.Event: add rawType/keyCode/modifiers/Use() + EventType enum (NGUI
  UIInput/UIInputOnGUI legacy IMGUI path).
- Reward: copy the real Wizard.Scripts.Network.Data.TaskData.Arena.Reward verbatim
  (was an empty ambiguous-name shim in LooseEnds); deps (UserGoods/JsonData) present.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 23:10:52 -04:00
gamer147
7e5ff0a58f feat(battle-engine): ParticleSystem/Collider2D/Quaternion + SocketOptions members (1462->1386)
ParticleSystem.MainModule (playOnAwake/simulationSpeed/startColor + MinMaxGradient),
ParticleSystemRenderer (maskInteraction/trailMaterial + SpriteMaskInteraction), BoxCollider2D
(isTrigger/offset/size), Quaternion.FromToRotation/Inverse. SocketOptions (AutoConnect/
ConnectWith/AdditionalQueryParams) + PlatformSupport ObservableDictionary.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 22:43:39 -04:00
gamer147
7ac13f73f2 feat(battle-engine): BestHTTP SocketIO + Spine SDK member shims (1556->1462)
BestHTTP.SocketIO: Socket.On/Off/Emit + SocketIOCallback delegate, SocketManager ctors/
State/Socket/indexer/Open/Close/SettingRealtimeNetworkAgent, SocketOptions. Spine: Skeleton
(Data/Skin/Scale/FindBone/SetSkin/Update), Bone (WorldX/Y/RotationX), SkeletonMecanim
(MonoBehaviour + skeleton). All minimal hand shims (no full-surface -> no SDK closure pull);
node-socket path is Phase-2, off the battle path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 22:41:06 -04:00
gamer147
a1c0c2d312 feat(battle-engine): CRI/Unity overload + generated base-ctor fixes (1586->1556)
CRI: CriAtomExPlayer.AttachFader, CriAtomCueSheet.acb, CriAtomExCategory static.
Unity overload gaps (CS7036): Transform.Translate/Rotate(float,float), Vector4(3/2-arg)
ctors, Vector3 instance Scale. Parameterless ctors for generated Vfx bases (ForecastIcon
VfxBase/ShowChantCountVfx/EvolveVfx) whose derived stubs' implicit base() failed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 22:38:02 -04:00
gamer147
4be630bd09 feat(battle-engine): full-surface app-type god-object/manager stubs (1692->1586 true)
Make the minimal hand shims partial + generate full member surface for the manager/
task/controller god-objects (LoadingViewManager/DeckUpdateTask/MyPageTask/ReplayController/
PlayerControllerForWatching/WatchDataHandler/EvolutionTouchProcessor/StoryChapterSelection
Utility/NonDialogPopup). NonDialogPopup given MonoBehaviour base + hand Close() removed
(superseded by full surface). LoadTask dup deleted (already copied verbatim). RoomMatch
watch/replay closure types stubbed. Copied 8 more closure files.

CS0246-in-generated-signature masking note: 4 such errors were hiding ~1582 — generated
CS0246 masks as hard as header CS0246; the real frontier is 1586 (CS7036 base-ctor +
member-level), 0 structural.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 22:33:37 -04:00
gamer147
fce02a6250 feat(battle-engine): VFX container Create overloads (2202->1692)
The hand-shim VFX containers only had no-arg Create(); the engine calls them with
collection/params/loading-main args (510 CS1501). Add the real decomp Create overloads
to SequentialVfxPlayer/ParallelVfxPlayer/VfxWithLoading/VfxWithLoadingSequential.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 22:27:51 -04:00
gamer147
2ddc86943e feat(battle-engine): re-establish dropped base clauses for net-new stubs (2704->2202 true)
The stub generator emits net-new types as base-LESS partials, so generated Vfx/View
types weren't actually VfxBase/etc. -> hundreds of CS1503/CS0029 'cannot convert to
VfxBase' at every polymorphic call site. m1_baseclauses.py recovers each generated
type's decomp base CLASS (interfaces dropped to avoid CS0535) into _BaseClauses.g.cs,
cross-namespace bases fully qualified. Generated the intermediate Vfx/processing base
types (SpreadOutVfx/OpenCardVfx/ProcessingBase/DamageVfxBase/ForecastIconVfxBase/...).
DefaultOpeningVfx regenerated WITH override (its base OpeningVfx is copied+abstract).

Clearing the polymorphism cascade + the masking base-type CS0246s unmasked the true
member-level frontier: 2202 (CS1501/CS1061/CS1503), 0 structural errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 22:24:22 -04:00
gamer147
d01e3da869 feat(battle-engine): UnityEngine member + static-class shims (3526->2706)
Extend the UnityEngine value/component shims with no-op members surfaced by the compile
loop (UnityWebRequest/Font/Mesh/LODGroup/AudioSource/Rigidbody/Camera/Sprite/Animation/
Transform/Material/Texture2D/Light/Input/Resources + CharacterInfo/Vector4), via partial
declarations + UnityShimExt.cs. Add the missing UnityEngine static classes (PlayerPrefs/
Physics/GUI/SystemInfo/Graphics/QualitySettings/StackTraceUtility) + enums (TextureFormat/
ColorSpace/EventModifiers/RenderTextureReadWrite) + Experimental.Rendering.GraphicsFormat*
in UnityStatics.cs. All cosmetic, off the battle path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 22:14:23 -04:00
gamer147
9cd3f40a2f feat(battle-engine): CRI Atom/Mana audio+movie shim (3916->3526)
Hand-model the CRI ADX2 (audio) + CRI Mana (movie) SDK surface exercised by the copied
audio/movie engine files (AudioManager/Voice/Se/Effect/MoviePlayer). No decomp source
exists; signatures mirror the real CRI API as called at the sites (arg counts/types from
the call sites). All no-op, cosmetic, off the battle path. Reconciled with the empty CRI
stubs already in SdkStubs (CriAtomExAcb/CriAtomExPlayback/CriManaMovieMaterial).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 22:08:36 -04:00
gamer147
4b9a603cd4 feat(battle-engine): full View/VFX/UI/Touch/Story type closure (4254->3916, unmasked)
Generate no-op shells for the entire stop-listed View/Vfx/UI/Touch/Story missing-
type closure (~180 types) + 5 copyable engine files. Net-new shells emitted base-less,
so override members are stripped via the new --no-override generator flag. SDK/BCL
over-reach (Adjust/GZipStream/Socket*) and non-battle Story-world clusters reduced to
minimal/empty stubs instead of full-surface. Nested-type closure (BuildInfo/BattleDialog/
ROOM_URI/FuncGetCantAttackText) placed top-level in their decomp namespaces.

Clearing the last View CS0115 unmasked the true member-level frontier: 3916 errors,
0 generated/structural errors, now dominated by Unity-type + god-object members.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 22:01:37 -04:00
gamer147
a28e3ba334 feat(battle-engine): Unity shim members — BoxCollider/RenderTexture/AnimationCurve/Animator (4572->4254)
Add no-op members + supporting types (FilterMode/TextureWrapMode/WrapMode/Keyframe/
AnimatorStateInfo/AnimatorClipInfo) to the UnityEngine shim. Standard Unity API surface,
inferred from frontier member names — Unity types aren't in the decomp so they're
hand-extended, not generated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 21:40:37 -04:00
gamer147
f32492b6c9 feat(battle-engine): app-type wave (RoomBase/Avatar/BossRush/tasks) 4850->4572
Full-surface stubs for RoomBase, Avatar/BossRush/MyRotation battle-log items (MonoBehaviour),
GetDeckDataFromCode, MailTopTask, AccountTransferHelper, CanNotTouchCardVfx. EXCLUDE
inherited overrides (CanNotTouchCardVfx.IsEnd, MailTopTask.Parse). ClosureStubs for the
RoomMatch subsystem bleed (~11 Room* types) + AppleLogin(+Error). Reward/Event deferred
(ambiguous common names resolve to wrong SDK files).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 21:37:23 -04:00
gamer147
70a2c3e8ed feat(battle-engine): View/Room/Vfx type wave (5600->4850)
Full-surface stubs for ICardVfxCreator(iface), SelectedStoryInfo, ImageSelection,
IReadOnlyVoiceInfo, RoomConnectController(+InitializeParameter/enums), RoomRuleSetting,
VideoHostingHUD(+HUDMode), TabList, BattleCardView.AttackTargetSelectInfo, ProtectionColorType.
Wired hand shims partial + MonoBehaviour bases; let generated supersede hand-written
nested enums (decomp-authoritative values). SocketManager kept as minimal SDK hand shim.
ClosureStubs for ~14 referenced empties.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 21:33:00 -04:00
gamer147
b47741d2a5 feat(battle-engine): full-surface god-object stubs (UIManager/GameObjMgr/BattleLog) 7532->5600
Generate the COMPLETE decomp member surface (not frontier-subset, which silently drops
already-provided members) for UIManager(+ViewScene/ChangeViewSceneParam), GameObjMgr,
BattleLogManager/Item, InPlayCardFrameEffectControl. UIManager/Footer base fixes:
UIManager is MonoBehaviour (singleton kept by hand via --exclude); Footer is the copied
Engine type (removed the conflicting global shim). Add HUDMode enum, Wizard manager
return-type stubs, and a closure-stubs file for 7 referenced empties.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 21:23:52 -04:00
gamer147
de1b7362c9 feat(battle-engine): BattleLog cluster via generated no-op stubs (7852->7532)
Stub-generate BattleLogManager(45)/BattleLogItem(17)/InPlayCardFrameEffectControl(4)
member surfaces from decomp signatures; declare BattleLogWindow+nested enum; make
BattleLogItem a MonoBehaviour so inherited gameObject/transform resolve.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 21:05:57 -04:00
gamer147
f9982f5249 feat(battle-engine): copy-loop closure to 3282 files (member-surface frontier) 2026-06-05 20:41:25 -04:00
gamer147
3dcd53933a feat(battle-engine): AOT/SFB/Steam/DisallowMultiple + FriendDataBase.SetPlayerData
Clears the last type+header frontier (RoomInviteFriendColum override). Per F3 this
unmasks the remaining View/UI/god-object member bodies (~8k) -- the next grind is
pure member-surface growth, closure (~3242 files) now essentially complete.
2026-06-05 20:40:33 -04:00
gamer147
0455ff649e feat(battle-engine): EffectType full enum + collection/card/vfx extension copies
Replaces partial EffectMgr.EffectType with all 226 decomp values; copies the
IsNotNullOrEmpty/EquelsID/FindFromCardId/GetAllFuncVfxResults extension files +
UI extensions; adds Renderer/MeshFilter shared-material/mesh/sortingOrder. Compile
loop then closed the revealed deps (3242 files). 9.1k -> 18 errors.
2026-06-05 20:38:56 -04:00
gamer147
c3bd39f2cb feat(battle-engine): final type-frontier residual (Story/Title/Friend stubs, SDK anchors, Unity AndroidJavaObject/WebCamTexture)
Clears the last CS0246/CS0234 type frontier; per F3 this unmasks the AI-subsystem
member bodies (~9k member-level errors) -- next grind is extension copies + god-object
member growth.
2026-06-05 20:34:49 -04:00
gamer147
824309ec44 feat(battle-engine): close the AI-simulation subsystem (verbatim)
Copied the 89 uncopied AI*SimulationUtility/extension files defining the
AIVirtualCard/AIVirtualField extension methods; the compile loop then auto-closed
the revealed type deps (~3049 files total, drift-clean). 10.0k -> 62 errors.
2026-06-05 20:30:59 -04:00
gamer147
78f310c2b3 feat(battle-engine): grow god-object + VFX-container shim surface
GameMgr (managers/setting/flags), UIManager (GetInstance + scene/dialog/loading
surface), EffectMgr (Start/effect lifecycle), VfxMgr + VfxWithLoading(Sequential)
register methods -- signatures mirrored from decomp. 15.9k -> 10.0k errors.
2026-06-05 20:27:00 -04:00
gamer147
4491c6c7f3 feat(battle-engine): full Unity primitive/runtime surface + game extension copies
Grows Vector2/3, Mathf, Color, Quaternion, GameObject, Transform, Camera, Material,
ParticleSystem, Rect, Bounds, Time to the surface the engine references; adds Input/
Random/Resources statics + full KeyCode enum. Copies the verbatim extension files that
collapse thousands of CS1061s at once (ContentKeywordExt, JsonData/LitJson extensions,
EventExtension.Call, GameObjectExtension(s)). 26.5k -> 15.9k errors; residual now
dominated by god-object member surface (GameMgr/UIManager/EffectMgr/Vfx*).
2026-06-05 20:22:43 -04:00
gamer147
a00e90c74a feat(battle-engine): clear header frontier (Item/ErrorDialog/SDK shims + infra copies)
Resolves the 268-error header frontier: settings Item base, ErrorDialog.Data,
RoomConnectController nested types, Unity asset/light/collider types, CriWare/
CodeStage/Spine SDK surface, and copies INetworkLogger + SingletonMonoBehaviour
verbatim. Per F3 this unmasks the type bodies (~26.5k member-level errors now
visible) -- the real M1 bulk, attacked in following waves.
2026-06-05 20:11:08 -04:00
gamer147
957af3d1ec feat(battle-engine): full Unity/VFX/god-object shims + expanded copy closure (2570 files)
Authored Unity primitive/object-model shim, VFX layer (control-flow-preserving, InstantVfx never invokes its action -- headless suppression), god-object stubs (GameMgr/EffectMgr/UIManager with faithfully-extracted nested enums), View/UI/Touch tree, LitJson+BetterList+Tuple copied, third-party stubs. Discovered Roslyn header-error masking: fixing class-header type errors unmasks body references, so the true copy closure is ~2570 files (was 782 under masking). Errors: masked-25720 -> 268; our shim files compile clean. Remaining: ~50 residual shim/external types, 24 NGUI UI-base overrides, static-type fixes, plus likely 1-2 more unmask waves.
2026-06-05 17:22:20 -04:00
gamer147
0d9d8acae0 feat(battle-engine): M1 auto-copy closure (782 battle-logic files)
Compile-driven bulk-copy loop (tools/engine-port/m1_copy_loop.py) pulled the precise reference closure of the battle-core roots, stopping at the classify god-object/View-VFX-UI boundary. 782 files; no re-explosion (M0 had estimated ~order 1000). Residual frontier = 52 shim-classified + 80 external (Unity/BCL) types to author next.
2026-06-05 16:57:20 -04:00
gamer147
23a6596558 fix(battle-engine): Quaternion.identity w=1 to match Unity semantics 2026-06-05 16:49:02 -04:00
gamer147
550cedbf1e feat(battle-engine): seed copy roots + UnityEngine primitive shim
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 16:45:12 -04:00
gamer147
bb80815b01 feat(battle-engine): scaffold empty SVSim.BattleEngine library 2026-06-05 16:34:46 -04:00
gamer147
13f902ce58 fix(battlenode): emit real spellboost count in played-card knownList
The node hardcoded knownList.spellboost=0 on every played card. Prod sends
the true accumulated count, which the client reads straight into the card's
cost model; with 0 the opponent computes the card at full price and silently
rejects the play in OperateReceiveChecker.IsPlayCard (PP-over -> ConductError
-> NullOperationCollection -> no render/echo), desyncing the board.

Mine spellboost-count changes from the sender''s orderList alter ops
(MineAlterSpellboosts: a/s/h ops), accumulate per-side idx->count in
BattleSessionState (RecordSpellboostFrom), and surface the current count on
the played card via BuildPlayedCard. Recorded from the authoritative
PlayActions only (never the Echo) and folded in AFTER the played card is
built, since a card''s cost is fixed as it leaves hand and a play that grants
spellboost targets the rest of the hand.

Also adds a [sio-in-body] full-body inbound log to RealParticipant to capture
both clients'' re-simulated responses for PvP RNG verification.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 13:51:40 -04:00
gamer147
2d32051cc0 refactor(battlenode): key dispatch on OpponentIsAckOnly, drop per-frame BattleType switch
Behavior-identical; 231 BattleNode tests green with ZERO test changes.

The 10 handler arms no longer switch on BattleType:
- 4 Bot arms gate on the new FrameDispatchContext.OpponentIsAckOnly
  (Other is not IHasHandshakePhase) — the participant property the audit asked for.
- 6 relay arms drop the Type == Pvp guard; it was redundant with BothSidesAfterReady()
  (only a two-real-player session has both handshake phases). Its doc now records that.
- FrameDispatchContext.Type removed (+ the Type = Type in BuildContext). BattleSession.Type
  stays for the session-level drop cascade.

Zero test churn because the stubs already encode the split: FakeRealParticipant/ProbeParticipant
implement IHasHandshakePhase, the bot stub FakeParticipant doesn't, and NewBotSession uses it as
the opponent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 08:20:56 -04:00
gamer147
9ff8948903 docs(battlenode): document four latent low-tier hygiene hazards
Comment-only; behavior-preserving; 231 BattleNode tests green.

- OutboundSequencer._archive: name the unbounded-per-match growth + ack-prune point.
- NodeCrypto.BuildAes: SECURITY remarks on key-derived IV reuse + base64 entropy loss;
  warn against caching the session key.
- MatchContext/BattlePlayer: FOOTGUN notes on reference-based record equality over the deck list.
- RecordTokensFrom: TRUST note on isSelf/idx overwrite; name the idx>deckCount guard for
  untrusted peers (not added — trusted-LAN today).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 08:11:13 -04:00
gamer147
1007cf24d2 refactor(battlenode): type MatchContext.ClassId as CardClass enum (§C)
Behavior-preserving; full solution builds, 1013 tests green.

ClassId is the one genuinely-closed set of the three flagged stringly fields, so it
becomes a CardClass enum (1..8). Wire stays "1".."8": producer casts
(CardClass)run.ClassId, ServerBattleFrames renders via CardClassWire.ToWireValue().
RankBattleController's AI-start path drops a fragile int.TryParse(...)?:-1 for (int)cast.

CharaId (free-form leader/skin id, e.g. "5000123") and CountryCode (open-ended account
data) stay string with proper XML docs; CountryCodes.Korea/Japan name the captured values.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 08:04:49 -04:00
gamer147
9b8a7f1e37 refactor(battlenode): name sender-only vs both-sides handshake checks (§D)
Behavior-preserving; 231 BattleNode tests green.

FrameDispatchContext.BothAfterReady() -> BothSidesAfterReady() (7 call sites). The
4 inline `SenderPhase == AfterReady` checks in TurnEndHandler/TurnEndFinalHandler now
read a new SenderIsAfterReady property. Both carry cross-referencing docs so the
Bot-arm (sender-only) vs PvP-arm (both-sides) distinction is explicit at the type.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 07:49:27 -04:00
gamer147
578d0a75ef refactor(battlenode): rename mode-id field off BattleType, add BattleModes (§D)
Behavior-preserving; 271 BattleNode/Matching/Services tests green, full solution builds.

"BattleType" meant two things: the Sessions.BattleType enum (Pvp/Bot) and an int
"mode id" field. Renamed the int field on MatchContext AND the BattleStartBody wire
DTO to BattleModeId (wire key stays "battleType" via JsonPropertyName), so BattleType
now means only the enum project-wide.

New Bridge/BattleModes.cs (TakeTwo = 11) replaces every 11 literal — both prod
MatchContextBuilder sites and the test fixtures/assertions. The arbitrary-passthrough
42 and bot 0 stay literal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 07:44:02 -04:00
gamer147
d119d2c277 refactor(battlenode): single-source MsgEnvelope envelope keys (§E)
Behavior-preserving; 231 BattleNode tests green.

The envelope key set was encoded three times (ReservedEnvelopeKeys, the ToJson
writes, the FromJson reads). Added a private nested MsgEnvelope.Keys with a const
per key; the reserved set, writes, and reads now all draw from it, so a key added
in one place but not another (letting a body key shadow an envelope field) can no
longer happen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 07:33:54 -04:00
gamer147
7e167b1cef refactor(battlenode): centralize inbound wire-key literals in WireKeys (§C)
Behavior-preserving; 231 BattleNode tests green (capture-conformance suite drives
real prod frames, so a wrong constant would fail).

New Sessions/Dispatch/WireKeys.cs holds the 28 inbound-body read keys (orderList /
keyAction / targetList / uList field names). KnownListBuilder, PlayActionsHandler,
EchoHandler, and BattleFrames.ExtractIdxList now read through it instead of repeated
inline strings, so a parse-side typo ("isSelf" vs "IsSelf") can no longer silently
degrade token resolution. Outbound [JsonPropertyName] attributes left as-is (already
single-source per DTO).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 07:30:02 -04:00
gamer147
3e8901eec3 refactor(battlenode): split BattleSessionPhase into HandshakePhase + SessionLifecycle
Behavior-preserving; 231 BattleNode tests green.

One enum conflated two axes. Split:
- HandshakePhase (per participant): AwaitingInitNetwork..AfterReady. On
  IHasHandshakePhase.Phase, FrameDispatchContext.SenderPhase, the handler gates.
- SessionLifecycle (per battle): Active | Terminal. On the renamed
  BattleSessionState.Lifecycle (was SessionPhase, defaulting to a handshake value)
  and BattleSession.Lifecycle (was Phase). Reads are only != Terminal, so the
  Active default is behavior-identical.

OpponentTurn was dead (never assigned) -> dropped. BattleSessionPhase deleted; the
two axes can no longer be cross-assigned.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 07:21:59 -04:00
gamer147
7d4da69f22 refactor(battlenode): low-churn §B/§D/§E/§F quality cleanups
Behavior-preserving; 231 BattleNode tests green.

- §D: MsgEnvelope.Try -> RetryAttempt (drops keyword-escape; wire key stays "try");
  SocketIoFrame.AckResponse arg -> pubSeqEcho.
- §B: Gungnir.EmitInterval -> BattleNodeOptions.AliveEmitInterval (unused literal
  moved to its config home); deck-idx 4L -> InitialHand.Length + 1.
- §E: shared Wire.WireJsonOptions.CamelCase replaces the duplicated camelCase
  JsonSerializerOptions in EngineIoHandshake and MsgEnvelope.
- §F: do-NOT-consistency-fix polarity notes on TurnEndFinalHandler (From wins)
  and RetireKillHandler (From loses).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 23:06:44 -04:00
gamer147
e70f32db79 refactor(battlenode): close §A boolean-blindness items (MinedToken, Stock, KeyActionType)
Behavior-preserving; 231 BattleNode tests green.

- MinedToken record struct replaces the transpose-prone (int Idx, long CardId,
  CardOwner IsSelf) tuple returned by KnownListBuilder.Mine*. Positional deconstruct
  keeps the Record*From call sites unchanged.
- enum Stock { Normal, Bypass } replaces the negative `bool noStock` on
  IBattleParticipant.PushAsync and DispatchRoute, threaded through both participants,
  BattleSession, and all handler construction sites.
- enum KeyActionType mirrors the client's SendKeyActionDataManager.KeyActionType;
  the StripKeyActionForOpponent guard compares named values, KeyActionEntry.Type is
  the enum (wire-identical via JsonNumberEnumConverter).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 22:53:32 -04:00
gamer147
a3e445cf2f refactor(battle-node): replace int IsSelf with CardOwner enum on mined-token tuples
MineAddOps/MineChoicePicks/MineCopyTokens return types and all
extraction casts changed from int to CardOwner. The 4 routing
comparisons in BattleSessionState now read isSelf == CardOwner.Self
instead of isSelf == 1.

No wire or behavioral change — CardOwner was already in use on the
wire-facing side (OppoTargetEntry, UnapprovedCardEntry); this extends
it to the internal mining path so the bare-int transpose risk is gone.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-04 22:25:01 -04:00
gamer147
564b1d678f fix(battle-node): collision-safe battle-id registration + viewer eviction
RegisterPending → TryRegisterPending (TryAdd instead of indexer) so
battle-id collisions return false instead of silently evicting a live
battle. MatchingBridge retries with fresh IDs on collision (max 5).

Before registering, EvictStaleForViewer removes any stale pending
battle the viewer left behind, enforcing the one-pending-per-viewer
invariant that was previously comment-asserted.

Store tests switched to per-test local stores to fix a race under
the assembly-wide ParallelScope.All.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-04 22:13:20 -04:00
gamer147
c6fb411861 fix(battle-node): dispose participants, unsubscribe events, filter catch
#5: BattleSession.RunAsync now unsubscribes FrameEmitted handlers
(-= OnFrameFromA/B) before termination and calls DisposeAsync on
both participants + the dispatch gate SemaphoreSlim afterward. This
unpins the session state from live delegates and releases the WS.

#6: Bare catch {} blocks replaced with filtered exception handlers
that silently swallow OperationCanceledException and WebSocketException
(expected at battle end) but log anything else at Warning. NREs and
other real bugs in handler threads are now visible instead of silently
eaten.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-04 22:00:28 -04:00
gamer147
99129c786c fix(battle-node): harden SIO parse + narrow Matched OppoId/Seed to int
#3: SocketIoFrame.Parse now range-checks the packet type char (was
unchecked cast — any char outside 0-6 produced an undefined enum
value) and uses int.TryParse for ack-id (was int.Parse — a >10-digit
ack-id threw OverflowException, tearing down the WS mid-game). Both
now throw ArgumentException consistently. The read loop in
RealParticipant wraps both EIO and SIO parse calls with try-catch so
a malformed frame is logged and skipped instead of killing the battle.

#4: MatchedSelfInfo/MatchedOppoInfo OppoId and Seed narrowed from
long to int. The client reads both with Convert.ToInt32 inside a
swallowing try/catch — any value > int.MaxValue silently dropped the
Matched event, preventing the battle from starting. Seed was already
int-range (BattleSeeds.Stable returns int); OppoId (viewer ID) is
~847M in captures, well under int.MaxValue. The narrowing cast now
happens explicitly in ServerBattleFrames.BuildMatched at the wire
boundary.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-04 21:57:29 -04:00