Skip to content

[Bug] STS2RitsuLib...NHandCardHolderFlashHandOutlinePatch.Postfix 调用了Disposed对象。 #84

Description

@MagicalAstrogy

模块范围

Public API(公开 API)

严重程度

Major / regression(主要问题 / 回归)

发生了什么?

ritsulib_state_divergence_20260709_001210_checksum_695_96728696.zip

复现步骤

原始 divergence 发生在 checksum #695:host 侧刚执行完 PlayCardAction card: CARD.SHADOWVERSEBYDMOD_CARD_FAIRY ... targetid: 2 后,host 和 remote 的状态校验不一致。

关键状态差异是同一张带 Exhaust, EternalTezcatara's Ember 的 Fairy 在两端进入了不同 pile:

  • host/local:Fairy 仍停在 players[0].piles.Play
  • remote:Fairy 已进入 players[0].piles.Exhaust

本地日志在同一动作窗口记录了 ObjectDisposedException

System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'MegaCrit.Sts2.Core.Nodes.Cards.Holders.NHandCardHolder'.
at STS2RitsuLib...NHandCardHolderFlashHandOutlinePatch.Postfix(...)
at MegaCrit.Sts2.Core.Nodes.Cards.Holders.NHandCardHolder.Flash_Patch2(...)
at shadowversebydmod.Scripts.Components.Common.PulseComponent.RefreshCost()
at shadowversebydmod.Scripts.Components.Common.PulseComponent.AfterCardPlayedLatePostfix(...)

PulseComponent.AfterCardPlayedLatePostfix 会在己方出牌后刷新手牌中 Pulse 卡的费用显示,并调用 Card.InvokeEnergyCostChanged()。当前源码中 NHandCardHolderPatch 原先在 SubscribeToEvents 的 prefix 里为“不在树上”的 hand holder 订阅 EnergyCostChanged -> NHandCardHolder.Flash。这会让离树/已释放的 hand holder 仍可能收到卡牌事件;一旦 Pulse 刷新费用,RitsuLib 的 hand-outline postfix 访问已释放的 holder,就会抛出 ObjectDisposedException

STS2 本体 CardModel.OnPlayWrapper 中,Hook.AfterCardPlayed(...) 在移动出牌结果 pile 之前执行;该异常会中断后续 CardCmd.Exhaust(...),因此 host 侧 Fairy 停在 Play pile,而 remote 正常进入 Exhaust。

复现方式

原始复现条件来自附件:

  • RitsuLib 0.4.54
  • MinionLib 0.6.0
  • Shadowverse Beyond Mod 1.0.3
  • 双人联机,Forestcraft/Castelle 玩家打出带 Tezcatara's Ember 的 Fairy
  • 出牌后 Pulse 组件刷新手牌费用显示时触发 disposed NHandCardHolder 事件处理器

容器内不能完整模拟 Steam 双端联机,但已用 headless 测试覆盖同一关键路径:通过网络动作打出带 Exhaust 的 Fairy,并在另一个 Pulse 卡留在手牌时触发出牌后费用刷新,断言 Fairy 正确进入 Exhaust 且不留在 Play。

关键证据

  • /output/evidence/state-divergence-report.txt

期望行为

No response

日志 / 堆栈

RitsuLib 版本

No response

运行环境

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/apiPublic API, contracts, or compatibility surface.priority/p1High priority regression or high-impact work.severity/majorSignificant bug with workaround or limited scope.status/needs-reviewReady for maintainer review.type/bugDefect or incorrect behavior in RitsuLib.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions