fix: 修复 spec 与实现的多处差异
- CombatEvent Hit 消息的 Damage 字段改为传递 configuration.DamagePerShot - SyncSequenceTracker MoveInput streamKey 改为只按 playerId 追踪 - 登录成功后新增 AuthoritativeCombatState bootstrap 逻辑 - 更新 network-gameplay-message-types spec 字段命名以匹配实际 proto 定义
This commit is contained in:
parent
2c46012800
commit
b7c003f227
|
|
@ -41,7 +41,7 @@ namespace Network.NetworkApplication
|
|||
case MessageType.MoveInput:
|
||||
{
|
||||
var input = MoveInput.Parser.ParseFrom(payload);
|
||||
streamKey = $"input:{Normalize(sender)}:{input.PlayerId}";
|
||||
streamKey = $"input:{input.PlayerId}";
|
||||
sequence = input.Tick;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,29 @@ namespace Network.NetworkHost
|
|||
}
|
||||
}
|
||||
|
||||
public void BootstrapState(IPEndPoint remoteEndPoint, string playerId, int hp, bool isDead)
|
||||
{
|
||||
if (remoteEndPoint == null || string.IsNullOrWhiteSpace(playerId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var key = Normalize(remoteEndPoint).ToString();
|
||||
lock (gate)
|
||||
{
|
||||
if (statesByPeer.ContainsKey(key))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
statesByPeer.Add(key, new ServerAuthoritativeCombatState(
|
||||
Normalize(remoteEndPoint),
|
||||
playerId,
|
||||
hp,
|
||||
isDead));
|
||||
}
|
||||
}
|
||||
|
||||
public Task HandleShootInputAsync(byte[] payload, IPEndPoint sender)
|
||||
{
|
||||
if (payload == null || sender == null)
|
||||
|
|
@ -95,7 +118,7 @@ namespace Network.NetworkHost
|
|||
EventType = CombatEventType.Hit,
|
||||
AttackerId = attackerState.PlayerId,
|
||||
TargetId = targetState.PlayerId,
|
||||
Damage = 0,
|
||||
Damage = configuration.DamagePerShot,
|
||||
HitPosition = hitPosition
|
||||
}, MessageType.CombatEvent);
|
||||
|
||||
|
|
|
|||
|
|
@ -284,6 +284,7 @@ namespace Network.NetworkHost
|
|||
RememberPlayerId(remoteEndPoint, playerId);
|
||||
SessionCoordinator.NotifyLoginSucceeded(remoteEndPoint);
|
||||
BootstrapAuthoritativeMovementState(remoteEndPoint, speed);
|
||||
BootstrapAuthoritativeCombatState(remoteEndPoint, playerId);
|
||||
PublishMetricsSessionSnapshot(remoteEndPoint);
|
||||
}
|
||||
|
||||
|
|
@ -382,6 +383,21 @@ namespace Network.NetworkHost
|
|||
authoritativeMovementCoordinator.EnsureState(remoteEndPoint, playerId, speed, out _);
|
||||
}
|
||||
|
||||
private void BootstrapAuthoritativeCombatState(IPEndPoint remoteEndPoint, string playerId)
|
||||
{
|
||||
if (!TryGetKnownPlayerId(remoteEndPoint, out var resolvedPlayerId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!authoritativeMovementCoordinator.TryGetState(remoteEndPoint, out var movementState))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
authoritativeCombatCoordinator.BootstrapState(remoteEndPoint, resolvedPlayerId, movementState.Hp, movementState.IsDead);
|
||||
}
|
||||
|
||||
private void RememberPlayerId(IPEndPoint remoteEndPoint, string playerId)
|
||||
{
|
||||
if (remoteEndPoint == null || string.IsNullOrWhiteSpace(playerId))
|
||||
|
|
|
|||
|
|
@ -17,26 +17,26 @@ The repository SHALL keep the source protobuf schema that defines gameplay netwo
|
|||
- **THEN** the checked-in generated code matches the schema contract used by client and server hosts
|
||||
|
||||
### Requirement: Gameplay messages expose explicit MVP payload fields
|
||||
The shared networking contract SHALL define the MVP payload fields for gameplay messages explicitly in the source protobuf schema and generated C# messages. `MoveInput` MUST expose `playerId`, `tick`, `moveX`, and `moveY`; `ShootInput` MUST expose `playerId`, `tick`, `dirX`, `dirY`, and an optional `targetId`; `PlayerState` MUST expose `playerId`, `tick`, `acknowledgedMoveTick`, `position`, `rotation`, `hp`, and an optional `velocity`; `CombatEvent` MUST expose `tick`, `eventType`, `attackerId`, `targetId`, `damage`, and an optional `hitPosition`. The shared contract MUST also provide `CombatEventType` so combat results use explicit event categories rather than ad hoc integer payload conventions.
|
||||
The shared networking contract SHALL define the MVP payload fields for gameplay messages explicitly in the source protobuf schema and generated C# messages. `MoveInput` MUST expose `player_id`, `tick`, `turn_input`, and `throttle_input`; `ShootInput` MUST expose `player_id`, `tick`, `dir_x`, `dir_y`, and an optional `target_id`; `PlayerState` MUST expose `player_id`, `tick`, `acknowledged_move_tick`, `position`, `rotation`, `hp`, and `velocity`; `CombatEvent` MUST expose `tick`, `event_type`, `attacker_id`, `target_id`, `damage`, and an optional `hit_position`. The shared contract MUST also provide `CombatEventType` so combat results use explicit event categories rather than ad hoc integer payload conventions.
|
||||
|
||||
#### Scenario: Movement input carries explicit movement fields
|
||||
- **WHEN** client or server code constructs or parses `MoveInput`
|
||||
- **THEN** the message exposes `playerId`, `tick`, `moveX`, and `moveY`
|
||||
- **THEN** the message exposes `player_id`, `tick`, `turn_input`, and `throttle_input`
|
||||
- **THEN** movement intent does not rely on an overloaded payload extension
|
||||
|
||||
#### Scenario: Shooting input carries explicit aim fields
|
||||
- **WHEN** client or server code constructs or parses `ShootInput`
|
||||
- **THEN** the message exposes `playerId`, `tick`, `dirX`, `dirY`, and `targetId`
|
||||
- **THEN** the message exposes `player_id`, `tick`, `dir_x`, `dir_y`, and `target_id`
|
||||
- **THEN** shooting direction and optional target selection are represented directly in the message contract
|
||||
|
||||
#### Scenario: Authoritative player state carries explicit gameplay state fields
|
||||
- **WHEN** client or server code constructs or parses `PlayerState`
|
||||
- **THEN** the message exposes `playerId`, `tick`, `acknowledgedMoveTick`, `position`, `rotation`, `hp`, and `velocity`
|
||||
- **THEN** the message exposes `player_id`, `tick`, `acknowledged_move_tick`, `position`, `rotation`, `hp`, and `velocity`
|
||||
- **THEN** snapshot ordering and acknowledged-input reconciliation are both expressed without ad hoc payload extensions or overloaded tick semantics
|
||||
|
||||
#### Scenario: Combat events carry explicit result fields and event categories
|
||||
- **WHEN** client or server code constructs or parses `CombatEvent`
|
||||
- **THEN** the message exposes `tick`, `eventType`, `attackerId`, `targetId`, `damage`, and `hitPosition`
|
||||
- **THEN** the message exposes `tick`, `event_type`, `attacker_id`, `target_id`, `damage`, and `hit_position`
|
||||
- **THEN** `CombatEventType` provides explicit combat-result categories for interpreting that event payload
|
||||
|
||||
### Requirement: Client gameplay actions use split gameplay messages directly
|
||||
|
|
|
|||
Loading…
Reference in New Issue