12f86c86de
The netcode core of the 4-socket kit (Phase1_Combat_Gym_Build_Spec §1,§2,§5; review NP-1/ RS-1/DB-1/DB-3): - PlayerInput: +4 Socket0..3 InputEvents + Burst-safe GetSocket(i); legacy Fire kept vestigial. - PlayerInputGatherSystem: gather sockets from keyboard 1..4 (+gamepad RT/LB/RB); socket 0 also fires on the legacy primary (right-click / pad LT) as a bridge. - AbilityFireSystem: query dropped to 4 type args (PlayerInput/PlayerFacing/LocalTransform/ GhostOwner) + BufferLookup<AbilitySocket>/ComponentLookup<SocketCooldown>/BufferLookup< EffectiveSocketStats> (the 7-arg-cap fix); loops 4 sockets; per-socket cooldown + per-socket effective stats; Cone + Projectile dispatch per socket (predict-spawn Projectile-only). - ProjectileSpawnId.Pack: pure Burst-safe key owner14|socket2|fireCount12|fork4 so same-tick multi-socket projectiles never collide; AbilityFireSystem uses it. L1 clean; L2 494/494 (+5 ProjectileSpawnId tests: distinct-per-socket, fork, owner, bit-ranges, count-wrap). L3 two-player + rollback is the group-A gate (after step 2.5). Note: the client feel layer (muzzle/anim) still reads the legacy cooldown until step 2.5; sockets bake empty until content (step 4), so nothing fires in-game yet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
67 lines
3.4 KiB
C#
67 lines
3.4 KiB
C#
using Unity.Collections;
|
|
using Unity.Mathematics;
|
|
using Unity.NetCode;
|
|
|
|
namespace ProjectM.Simulation
|
|
{
|
|
/// <summary>
|
|
/// Twin-stick player input (server-authoritative, input-only clients). Gathered once per frame
|
|
/// on the owning client in <see cref="GhostInputSystemGroup"/> and streamed to the server via
|
|
/// AutoCommandTarget. Netcode source-gen produces InputBufferData<PlayerInput> plus the
|
|
/// copy/apply systems from this type. The [GhostField]s let remote owners be predicted; the
|
|
/// data replays deterministically under rollback.
|
|
/// </summary>
|
|
public struct PlayerInput : IInputComponentData
|
|
{
|
|
/// <summary>WASD / left-stick movement, normalized to roughly -1..1 per axis.</summary>
|
|
[GhostField(Quantization = 1000)] public float2 Move;
|
|
|
|
/// <summary>Right-stick / cursor aim direction (normalized). Zero => face movement direction.</summary>
|
|
[GhostField(Quantization = 1000)] public float2 Aim;
|
|
|
|
/// <summary>Primary ability fire. InputEvent survives the frame→tick→rollback boundary so a press fires exactly once.</summary>
|
|
[GhostField] public InputEvent Fire;
|
|
/// <summary>Dodge dash. InputEvent twin of <see cref="Fire"/>: survives the frame-tick-rollback boundary
|
|
/// so one press dashes exactly once; read by the predicted DashSystem (MC-1).</summary>
|
|
[GhostField] public InputEvent Dash;
|
|
|
|
/// <summary>Melee combo attack (MC-4) - the player's PRIMARY verb. InputEvent twin of Fire/Dash: one press =
|
|
/// one swing attempt across the frame->tick->rollback boundary; read by the predicted MeleeComboSystem.</summary>
|
|
[GhostField] public InputEvent Attack;
|
|
|
|
/// <summary>LANTERN 4-socket kit: one fire event per ability socket (0..3). A press sets that socket's
|
|
/// event for the tick; AbilityFireSystem fires the Spark in that socket. InputEvent survives the
|
|
/// frame->tick->rollback boundary so one press fires once. Read per-socket via <see cref="GetSocket"/>.</summary>
|
|
[GhostField] public InputEvent Socket0;
|
|
[GhostField] public InputEvent Socket1;
|
|
[GhostField] public InputEvent Socket2;
|
|
[GhostField] public InputEvent Socket3;
|
|
|
|
/// <summary>Active input scheme this tick (<see cref="InputSchemeId"/>: 0 = mouse/keyboard, 1 = gamepad).
|
|
/// The server reads it so the auto-target assist applies only to gamepad shots; precise mouse aim is left
|
|
/// exact. A byte (not an enum): it is compared inside the Burst-compiled <c>AbilityFireSystem</c>.</summary>
|
|
[GhostField] public byte Scheme;
|
|
|
|
/// <summary>The fire event for ability socket <paramref name="i"/> (0..3). Burst-safe (switch, not a field index).</summary>
|
|
public InputEvent GetSocket(int i)
|
|
{
|
|
switch (i)
|
|
{
|
|
case 0: return Socket0;
|
|
case 1: return Socket1;
|
|
case 2: return Socket2;
|
|
default: return Socket3;
|
|
}
|
|
}
|
|
|
|
public FixedString512Bytes ToFixedString()
|
|
{
|
|
var s = new FixedString512Bytes();
|
|
s.Append(Move.x); s.Append(','); s.Append(Move.y); s.Append(';');
|
|
s.Append(Aim.x); s.Append(','); s.Append(Aim.y); s.Append(';');
|
|
s.Append(Fire.Count); s.Append(';'); s.Append(Scheme); s.Append(';'); s.Append(Dash.Count); s.Append(';'); s.Append(Attack.Count);
|
|
return s;
|
|
}
|
|
}
|
|
}
|