merge: sky/weather/lighting overhaul branch (Opus agent, 7 commits, +27 tests)
Ships full retail-faithful sky-object rendering, 5-kind weather with deterministic per-day roll + storm lightning, dynamic-lighting shader UBO with retail hard-cutoff semantics, per-entity torch LightSource registration via Setup.Lights, ParticleRenderer for rain/snow, and TimeSync handshake wiring. F7 / F10 debug keys for time/weather cycling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
48b5e1f1b1
31 changed files with 3057 additions and 129 deletions
|
|
@ -109,6 +109,21 @@ public sealed class WorldSession : IDisposable
|
|||
/// </summary>
|
||||
public event Action<HearSpeech.Parsed>? SpeechHeard;
|
||||
|
||||
/// <summary>
|
||||
/// Phase G.1: latest server Portal Year tick count. Seeded from the
|
||||
/// ConnectRequest handshake (r12 §1.3 — server sends absolute game
|
||||
/// time as a double) and refreshed on every TimeSync-flagged packet.
|
||||
/// Subscribers feed this into <c>WorldTimeService.SyncFromServer</c>
|
||||
/// so client-local day/night stays in lockstep with the server clock.
|
||||
/// </summary>
|
||||
public event Action<double>? ServerTimeUpdated;
|
||||
|
||||
/// <summary>
|
||||
/// Latest server tick count from <see cref="ServerTimeUpdated"/>
|
||||
/// events. 0 until the handshake completes.
|
||||
/// </summary>
|
||||
public double LastServerTimeTicks { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allow re-sending LoginComplete after a portal teleport. The normal
|
||||
/// _loginCompleteSent latch prevents duplicate sends on the initial spawn
|
||||
|
|
@ -224,6 +239,14 @@ public sealed class WorldSession : IDisposable
|
|||
|
||||
// Step 3: seed ISAAC, send ConnectResponse to port+1, with 200ms race delay
|
||||
var opt = cr.Optional;
|
||||
|
||||
// Phase G.1: server's initial PortalYearTicks (r12 §1.3) lives
|
||||
// in the ConnectRequest optional section. Publish it to
|
||||
// subscribers so WorldTimeService.SyncFromServer can seed the
|
||||
// client clock.
|
||||
LastServerTimeTicks = opt.ConnectRequestServerTime;
|
||||
ServerTimeUpdated?.Invoke(opt.ConnectRequestServerTime);
|
||||
|
||||
byte[] serverSeedBytes = new byte[4];
|
||||
BinaryPrimitives.WriteUInt32LittleEndian(serverSeedBytes, opt.ConnectRequestServerSeed);
|
||||
byte[] clientSeedBytes = new byte[4];
|
||||
|
|
@ -393,6 +416,19 @@ public sealed class WorldSession : IDisposable
|
|||
SendAck(serverHeader.Sequence);
|
||||
}
|
||||
|
||||
// Phase G.1: propagate TimeSync-flagged server time to anyone who
|
||||
// needs it (sky/day-night lerp in particular). Server sends this
|
||||
// periodically — no explicit opcode, just the header flag.
|
||||
if ((serverHeader.Flags & PacketHeaderFlags.TimeSync) != 0)
|
||||
{
|
||||
double t = dec.Packet!.Optional.TimeSync;
|
||||
if (t > 0)
|
||||
{
|
||||
LastServerTimeTicks = t;
|
||||
ServerTimeUpdated?.Invoke(t);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var frag in dec.Packet!.Fragments)
|
||||
{
|
||||
var body = _assembler.Ingest(frag, out _);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue