61 lines
3.0 KiB
Go
61 lines
3.0 KiB
Go
package routers
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
)
|
|
|
|
var _ = sync.Mutex{}
|
|
var _ = context.Background
|
|
|
|
//
|
|
// Weapon drop / pick-up recovery.
|
|
// Retail drops a weapon by creating a real Destructible in the world and handing its id to the
|
|
// client: SyncDisarmCreateWeaponDestructible (68141963) spawns it and AskPickUpWeapon (67264037)
|
|
// takes a destructibleId, not a weapon id. This server has never sent either, and the client
|
|
// never asks for one — a packet capture of a full drop + long-press-Q cycle contains zero
|
|
// AskDiscardWeapon*/AskPickUpWeapon calls, and every AskInteractCmd carries only CmdType 19/33/34
|
|
// (SyncWeaponFBBIK / Request-SyncGameplayTagMask per NetcodeCommandUtils.NetCodeCmdType), so the
|
|
// whole drop is client-local and the server has no way to learn that it happened.
|
|
// What that leaves behind is a client weapon state machine with nothing to finish against: the
|
|
// long-press-Q absorb never resolves, the unit stays in its root-motion absorb loop and slides
|
|
// backwards until the player switches character (which rebuilds WeaponManager and clears it).
|
|
// ResetWeaponStateAsync is the server-side equivalent of that rebuild, and the admin
|
|
// panel exposes it as 「解除卡死」. See TOPIC notes / 2026-09-19.md §72 for the packet evidence.
|
|
//
|
|
//
|
|
// Client invoke: AskSkillDestructibleCreate — the drop.
|
|
// This is the packet the client sends when a weapon leaves the hand, and it is answered with
|
|
// the new Destructible's id. Everything afterwards (long-press-Q psychokinesis, the pick-up
|
|
// prompt, AskPickUpWeapon) addresses the drop by that id, so answering 0 left the client
|
|
// talking to nothing: absorb animation with no exit (backwards slide), a Q prompt that never
|
|
// clears, and a weapon that returns to the hand only to fall straight back out.
|
|
//
|
|
func GameRouter_WeaponDrop_OnSkillDestructibleCreate(ctx context.Context, conn any, msg any) any {
|
|
// Router implementation for GameRouter_WeaponDrop_OnSkillDestructibleCreate
|
|
var zero any; return zero
|
|
}
|
|
|
|
//
|
|
// Client invoke: AskPickUpWeapon (67264037) — the absorb finished, take it back.
|
|
// Answer with retail's own remove/add pair plus the weapon profile, and nothing else. The
|
|
// client drives the absorb itself; this server has to converge its own state (put the weapon
|
|
// back into the slot it was dropped from, make it current) and hand back a weapon the client
|
|
// can actually use, without rebuilding the weapon manager underneath a running animation.
|
|
//
|
|
func GameRouter_WeaponDrop_OnPickUpWeapon(ctx context.Context, conn any, msg any) any {
|
|
// Router implementation for GameRouter_WeaponDrop_OnPickUpWeapon
|
|
var zero any; return zero
|
|
}
|
|
|
|
//
|
|
// Break whatever action the unit is stuck in and re-publish the authoritative weapon state.
|
|
// Order matters: SyncBreakSkill first, then the snapshot, then the selection packets — the same
|
|
// sequence OnSwitchWeapon uses, minus the slot mutation.
|
|
//
|
|
func GameRouter_WeaponDrop_ResetWeaponStateAsync(ctx context.Context, session *GameSession) any {
|
|
// Router implementation for GameRouter_WeaponDrop_ResetWeaponStateAsync
|
|
var zero any; return zero
|
|
}
|
|
|