@woosh/meep-engine 3.60.9 → 3.61.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/package.json +1 -1
  3. package/src/engine/ecs/EntityManager.d.ts +3 -3
  4. package/src/engine/ecs/EntityManager.js +3 -3
  5. package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
  6. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +4 -0
  7. package/src/engine/graphics/ecs/decal/v2/Decal.d.ts +46 -2
  8. package/src/engine/graphics/ecs/decal/v2/Decal.d.ts.map +1 -1
  9. package/src/engine/graphics/ecs/decal/v2/Decal.js +74 -5
  10. package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.d.ts.map +1 -1
  11. package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js +13 -1
  12. package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.d.ts +9 -0
  13. package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.d.ts.map +1 -0
  14. package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.js +37 -0
  15. package/src/engine/graphics3/DecalSystem.d.ts.map +1 -1
  16. package/src/engine/graphics3/DecalSystem.js +462 -447
  17. package/src/engine/graphics3/decal/DECAL_GPU_RECORD.d.ts +14 -0
  18. package/src/engine/graphics3/decal/DECAL_GPU_RECORD.d.ts.map +1 -1
  19. package/src/engine/graphics3/decal/DECAL_GPU_RECORD.js +53 -13
  20. package/src/engine/graphics3/decal/chunk_decal_record.d.ts +6 -1
  21. package/src/engine/graphics3/decal/chunk_decal_record.d.ts.map +1 -1
  22. package/src/engine/graphics3/decal/chunk_decal_record.js +28 -9
  23. package/src/engine/graphics3/decal/decal_gpu_records.d.ts +2 -1
  24. package/src/engine/graphics3/decal/decal_gpu_records.d.ts.map +1 -1
  25. package/src/engine/graphics3/decal/decal_gpu_records.js +26 -5
  26. package/src/engine/graphics3/decal/decal_material_samplers.d.ts +6 -0
  27. package/src/engine/graphics3/decal/decal_material_samplers.d.ts.map +1 -1
  28. package/src/engine/graphics3/decal/decal_material_samplers.js +13 -0
  29. package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +1 -1
  30. package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +1 -1
  31. package/src/engine/graphics3/decal/shader_decal_composite.d.ts +5 -0
  32. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  33. package/src/engine/graphics3/decal/shader_decal_composite.js +69 -28
  34. package/src/engine/network/NetworkSession.d.ts +3 -0
  35. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  36. package/src/engine/network/NetworkSession.js +68 -10
  37. package/src/engine/network/README.md +6 -3
  38. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +51 -5
  39. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
  40. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +308 -34
  41. package/src/engine/network/replication/Replicator.d.ts +8 -2
  42. package/src/engine/network/replication/Replicator.d.ts.map +1 -1
  43. package/src/engine/network/replication/Replicator.js +13 -4
  44. package/src/engine/network/sim/ActionLog.d.ts +16 -2
  45. package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
  46. package/src/engine/network/sim/ActionLog.js +33 -2
  47. package/src/engine/network/sim/RewindEngine.d.ts +9 -0
  48. package/src/engine/network/sim/RewindEngine.d.ts.map +1 -1
  49. package/src/engine/network/sim/RewindEngine.js +15 -1
  50. package/src/engine/network/state/FrameBufferRing.d.ts +12 -5
  51. package/src/engine/network/state/FrameBufferRing.d.ts.map +1 -1
  52. package/src/engine/network/state/FrameBufferRing.js +32 -6
  53. package/src/engine/network/time/TimeDilation.d.ts +30 -14
  54. package/src/engine/network/time/TimeDilation.d.ts.map +1 -1
  55. package/src/engine/network/time/TimeDilation.js +47 -17
  56. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  57. package/src/generation/foliage/skeleton/ShootWoodHash.d.ts +3 -2
  58. package/src/generation/foliage/skeleton/ShootWoodHash.d.ts.map +1 -1
  59. package/src/generation/foliage/skeleton/ShootWoodHash.js +25 -2
  60. package/src/shade/renderer/buffer/graph_read_buffer.d.ts +3 -1
  61. package/src/shade/renderer/buffer/graph_read_buffer.d.ts.map +1 -1
  62. package/src/shade/renderer/buffer/graph_read_buffer.js +9 -6
  63. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts +5 -0
  64. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts.map +1 -1
  65. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.js +48 -43
  66. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  67. package/src/shade/renderer/material/GPUMaterialManager.js +117 -35
  68. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts +2 -2
  69. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
  70. package/src/shade/renderer/material/standard/fragment_gbuffer.js +10 -3
  71. package/src/shade/renderer/material/standard/material_gbuffer_vertex.d.ts +15 -3
  72. package/src/shade/renderer/material/standard/material_gbuffer_vertex.d.ts.map +1 -1
  73. package/src/shade/renderer/material/standard/material_gbuffer_vertex.js +25 -4
  74. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +23 -5
  75. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  76. package/src/shade/renderer/particles/GPUParticleSystem.js +294 -20
  77. package/src/shade/renderer/particles/resize/shader_particle_shrink_alive_list.d.ts +21 -0
  78. package/src/shade/renderer/particles/resize/shader_particle_shrink_alive_list.d.ts.map +1 -0
  79. package/src/shade/renderer/particles/resize/shader_particle_shrink_alive_list.js +83 -0
  80. package/src/shade/renderer/particles/resize/shader_particle_shrink_free_list.d.ts +21 -0
  81. package/src/shade/renderer/particles/resize/shader_particle_shrink_free_list.d.ts.map +1 -0
  82. package/src/shade/renderer/particles/resize/shader_particle_shrink_free_list.js +64 -0
  83. package/src/shade/renderer/restir/di/chunk_restir_resolve.d.ts.map +1 -1
  84. package/src/shade/renderer/restir/di/chunk_restir_resolve.js +91 -94
  85. package/src/shade/renderer/restir/reservoir/chunk_rtxdi_stream_sample.js +1 -1
  86. package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.d.ts +14 -0
  87. package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.d.ts.map +1 -1
  88. package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.js +36 -21
  89. package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_sample_gather.d.ts +22 -0
  90. package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_sample_gather.d.ts.map +1 -0
  91. package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_sample_gather.js +64 -0
  92. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_vertex_normal.d.ts.map +1 -1
  93. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_vertex_normal.js +13 -18
  94. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_vertex_normal.d.ts.map +1 -1
  95. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_vertex_normal.js +28 -30
  96. package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_u32_to_vec2.d.ts.map +1 -1
  97. package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_u32_to_vec2.js +15 -16
  98. package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_vec2_to_u32.d.ts +0 -1
  99. package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_vec2_to_u32.d.ts.map +1 -1
  100. package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_vec2_to_u32.js +15 -18
  101. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_bitset_or.d.ts +32 -0
  102. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_bitset_or.d.ts.map +1 -0
  103. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_bitset_or.js +73 -0
  104. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +8 -1
  105. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  106. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +7 -3
  107. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_sh3_color_encode.d.ts +0 -2
  108. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_sh3_color_encode.d.ts.map +0 -1
  109. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_sh3_color_encode.js +0 -6
@@ -1,6 +1,7 @@
1
1
  import { assert } from "../../core/assert.js";
2
2
  import { BinaryBuffer } from "../../core/binary/BinaryBuffer.js";
3
3
  import Signal from "../../core/events/signal/Signal.js";
4
+ import { clamp } from "../../core/math/clamp.js";
4
5
  import { EntityObserver } from "../ecs/EntityObserver.js";
5
6
  import { UUID } from "../ecs/guid/UUID.js";
6
7
  import { BinarySerializationRegistry, } from "../ecs/storage/binary/BinarySerializationRegistry.js";
@@ -677,6 +678,14 @@ export class NetworkSession {
677
678
  */
678
679
  #host_frame_seen = -1;
679
680
 
681
+ /**
682
+ * Client: the newest host frame this client's world holds — the frame the last join's snapshot
683
+ * was taken at, or a frame applied from the host's action stream since, whichever is newer — or
684
+ * -1 before the first join. It is what a RESUME_HELLO claims, and a resumed stream starts after it.
685
+ * @private @type {number}
686
+ */
687
+ #host_frame_applied = -1;
688
+
680
689
  /**
681
690
  * Client: the host's newest depth feedback — its latest sight of this client's frame minus its
682
691
  * own sim frame, measured where this client's input lands — and that latest sight itself (the
@@ -841,6 +850,9 @@ export class NetworkSession {
841
850
  * - `frame_capacity` sizes the action-log ring (rollback depth + back-fill
842
851
  * range + retransmit window — see {@link DEFAULT_ACTION_LOG_FRAME_CAPACITY}).
843
852
  * Default 32. Raise it for high-RTT / lossy links.
853
+ * - `time_dilation` (client role): defaults to one built for round trips up to
854
+ * `frame_capacity` frames. One of your own should be too: its
855
+ * `max_round_trip_frames` is what keeps it from overshooting.
844
856
  * - `scope_filter` defaults to {@link OwnerAwareScope} on the host.
845
857
  * - `server_resume_grace_ms` (host role): how long peer state is
846
858
  * retained after a transport drop before being freed. Default 30s.
@@ -956,8 +968,7 @@ export class NetworkSession {
956
968
 
957
969
  this.#time_dilation = time_dilation || new TimeDilation({
958
970
  target_buffer_depth: this.simulation_delay_ticks > 0 ? this.simulation_delay_ticks : 2,
959
- max_dilation: 0.05,
960
- gain: 0.05,
971
+ max_round_trip_frames: this.frame_capacity,
961
972
  });
962
973
  this.#adaptive_render_delay = adaptive_render_delay || new AdaptiveRenderDelay({
963
974
  tick_period_ms: this.tick_period_ms,
@@ -1263,10 +1274,12 @@ export class NetworkSession {
1263
1274
  // and "spectator" (no sampler — sampler-driven onPredict
1264
1275
  // returns no actions, so the predict-reconcile machinery
1265
1276
  // exists but stays idle).
1277
+ // Only Replay rewinds, so only Replay needs a late host record put back in its frame.
1266
1278
  this.#client = new ServerAuthoritativeClient({
1267
1279
  ...orchestrator_opts,
1268
1280
  time_dilation: this.#time_dilation,
1269
1281
  auto_reconcile: this.#reconcile === NetworkSessionReconcile.Replay,
1282
+ rebase_on_arrival: this.#reconcile === NetworkSessionReconcile.Replay,
1270
1283
  });
1271
1284
  if (this.#reconcile === NetworkSessionReconcile.Correct) {
1272
1285
  this.#client.peer.onAuthState.add((_peer_id, server_frame, network_id, buffer) => {
@@ -1496,7 +1509,14 @@ export class NetworkSession {
1496
1509
  // Resume candidate. Wait for RESUME_HELLO; restore
1497
1510
  // baseline + add to connected_peers on validation.
1498
1511
  // Don't queue INITIAL_SYNC — it'll only fire if we
1499
- // RESUME_REJECT.
1512
+ // RESUME_REJECT. Its action stream waits for the claim too:
1513
+ // until the host has read it, neither the peer's token nor
1514
+ // the frame its world is held through is known. A stream
1515
+ // packed meanwhile starts at the ring floor, under frames
1516
+ // the client has already applied, and the client's apply
1517
+ // watermark starts afresh with the connection: it would
1518
+ // apply them again.
1519
+ this.#peer.hold_outbound(remote_peer_id);
1500
1520
  } else {
1501
1521
  // Fresh peer. Queue initial-sync for the next host tick.
1502
1522
  this.#queue_initial_sync(remote_peer_id);
@@ -1554,7 +1574,7 @@ export class NetworkSession {
1554
1574
  // we don't speak is one the host has to time out.
1555
1575
  const token = this.session_token;
1556
1576
  if (token !== null || this.#has_ever_connected) {
1557
- const last_acked = Math.max(0, this.#playout.latest_frame);
1577
+ const last_acked = Math.max(0, this.#host_frame_applied);
1558
1578
  this.#peer.send_resume_hello(
1559
1579
  remote_peer_id, this.local_peer_id, last_acked,
1560
1580
  token !== null, token !== null ? token.data : NO_SESSION_TOKEN,
@@ -1893,10 +1913,11 @@ export class NetworkSession {
1893
1913
  // Client: drive the reconnect timer.
1894
1914
  this.#tick_reconnect(dt_ms);
1895
1915
 
1896
- // Time dilation: run the whole local simulation a few percent fast or slow, as the
1897
- // host asks, by stretching the wall time each step consumes. The step itself — and so
1898
- // every system's dt — is unchanged, and the render alpha stays a true fraction of it.
1899
- this.entity_manager.fixedStepTimeScale = 1 / this.#client.dilation_factor;
1916
+ // Time dilation: run the whole local simulation fast or slow, as the host asks, by
1917
+ // stretching the wall time each step consumes — a few percent to steer, slower in
1918
+ // proportion to a lead it has to repay. The step itself — and so every system's dt — is
1919
+ // unchanged, and the render alpha stays a true fraction of it.
1920
+ this.entity_manager.fixedStepTimeScale = 1 / this.#dilation_in_force();
1900
1921
  }
1901
1922
 
1902
1923
  // Idle reaping: a connected peer that has gone silent past the timeout
@@ -2427,6 +2448,9 @@ export class NetworkSession {
2427
2448
  this.#align_to_host(frame_number);
2428
2449
  this.#forget_predicted_world();
2429
2450
  this.#binding_answer = BindingAnswer.Synced;
2451
+ // The world is the host's as of this frame, whatever the one it replaced held: a resume
2452
+ // claiming less would be sent frames the snapshot already holds.
2453
+ this.#host_frame_applied = frame_number;
2430
2454
 
2431
2455
  // Input from here on is predicted on the host's world. What was predicted before —
2432
2456
  // held since this binding was made, or still in the log from before it — was
@@ -2489,6 +2513,34 @@ export class NetworkSession {
2489
2513
  this.#client.forget_timeline();
2490
2514
  }
2491
2515
 
2516
+ /**
2517
+ * Client: the dilation factor to run at — the host's, as far as the report it came from still
2518
+ * holds. A report names the newest frame of this client's the host has seen, which the host keeps
2519
+ * as a running maximum and never lowers.
2520
+ *
2521
+ * - About a frame the clock has since gone back past, the report is about frames the client has
2522
+ * left: nominal rate.
2523
+ * - With no report on this binding, or none for longer than the longest round trip the dilation is
2524
+ * built for, the last one is stale: it may steer, within `max_dilation`, but repays nothing — the
2525
+ * lead it described may be gone, and repaying it again would put the client behind.
2526
+ *
2527
+ * @returns {number}
2528
+ */
2529
+ #dilation_in_force() {
2530
+ const time_dilation = this.#time_dilation;
2531
+ const factor = this.#client.dilation_factor;
2532
+ const seen = this.#host_marker_seen;
2533
+ const age = this.#local_frame - seen;
2534
+
2535
+ if (seen >= 0 && age <= 0) return 1;
2536
+
2537
+ if (seen < 0 || age > time_dilation.max_round_trip_frames) {
2538
+ return clamp(factor, 1 - time_dilation.max_dilation, 1 + time_dilation.max_dilation);
2539
+ }
2540
+
2541
+ return factor;
2542
+ }
2543
+
2492
2544
  /**
2493
2545
  * Client, as a step opens: more than the host's input window behind, the client re-takes the
2494
2546
  * host's time.
@@ -2942,8 +2994,11 @@ export class NetworkSession {
2942
2994
  }
2943
2995
 
2944
2996
  // Valid resume. Restore the action-stream baseline so the
2945
- // replicator packs from `last_acked + 1`, then accept.
2997
+ // replicator packs from `last_acked + 1`, release the stream
2998
+ // `connect()` held from that frame on — nothing the client
2999
+ // already holds is sent on this connection — then accept.
2946
3000
  this.#peer.baseline.set_acked(claimed_peer_id, last_acked_frame);
3001
+ this.#peer.release_outbound(transport_peer_id, last_acked_frame + 1);
2947
3002
  this.#peer_grace_state.delete(claimed_peer_id);
2948
3003
  this.#connected_peers.add(transport_peer_id);
2949
3004
  this.#peer.send_resume_accept(transport_peer_id);
@@ -3680,12 +3735,15 @@ export class NetworkSession {
3680
3735
  /**
3681
3736
  * Record post-apply state for every remote-owned entity into the
3682
3737
  * network timeline. Locally-owned entities are predicted, not
3683
- * interpolated from the network, so they're skipped.
3738
+ * interpolated from the network, so they're skipped. The frame is
3739
+ * one the world now holds, which a resume claims.
3684
3740
  *
3685
3741
  * Doesn't fire on the host — the replicator's deferral path doesn't
3686
3742
  * emit `onFrameApplied`, so the host gets no recording naturally.
3687
3743
  */
3688
3744
  #on_frame_applied(_peer_id, frame_number) {
3745
+ if (frame_number > this.#host_frame_applied) this.#host_frame_applied = frame_number;
3746
+
3689
3747
  const log = this.#interp_log;
3690
3748
  const interpolands = this.#interpolands;
3691
3749
 
@@ -59,8 +59,8 @@ nothing else to set up. What that takes, and where it lives:
59
59
  the step closes (`closeFixedStep`), so physics, controllers and game code all simulate inside the
60
60
  frame. There is no `session.tick()` to call (it is deprecated and inert);
61
61
  `entity_manager.update(dt)` — the engine loop — drives everything. Client time dilation is the
62
- engine's `fixedStepTimeScale`: the step cadence stretches by a few percent, no step is dropped or
63
- doubled. The session's timers — render playout, idle reaping, grace window — run on the same
62
+ engine's `fixedStepTimeScale`: the step cadence stretches — by a few percent to steer, by more to
63
+ repay a lead the host's lost time left — and no step is dropped or doubled. The session's timers — render playout, idle reaping, grace window — run on the same
64
64
  frame time.
65
65
  - **The network writes where the simulation writes.** Every transport the session is given is held
66
66
  (`DeferredTransport`): what arrives is applied as the next step opens, after the interpolation
@@ -128,7 +128,10 @@ connection:
128
128
 
129
129
  - **`RESUME_ACCEPT`**: the host kept the client's session, so the world the client has been
130
130
  predicting on goes on. Everything predicted meanwhile is sent, input predicted while cut off
131
- included, and the host applies it late.
131
+ included, and the host applies it late. The host sends the new connection none of its own action
132
+ stream until it has read the client's `RESUME_HELLO`, and then the frames after the one the client
133
+ claims to hold the world through: the frame its last join's snapshot was taken at, or the newest
134
+ frame it has applied since.
132
135
  - **`INITIAL_SYNC`**: the host's snapshot replaces the client's world. Nothing predicted before it
133
136
  is ever sent, on this connection or a later one that resumes it: that input was predicted on a
134
137
  world that is gone. The client's input starts at the frame the snapshot sets its counter to.
@@ -54,6 +54,27 @@
54
54
  * third. Here the authored half is `onReplay`'s job and the arrived half is
55
55
  * this one's.
56
56
  *
57
+ * - Records that arrive from a peer for a frame this client has already
58
+ * predicted past belong in that frame, under the prediction since, and
59
+ * before the frame's corrections, which already hold what they did. The
60
+ * frames after it were predicted without them and hold the prior state they
61
+ * captured then, so a rewind across those frames would put back what the
62
+ * records changed — a rewind about any other entity included. Where the
63
+ * records write something a frame after theirs, or a correction of their
64
+ * own frame, holds prior state of, the client takes them back off the
65
+ * world, rewinds to the end of their frame and back past its corrections,
66
+ * applies them there, the corrections after them, and replays what came
67
+ * after, as a reconciliation replays. Records about nothing written since
68
+ * stay where they landed: for everything they write, the present still holds
69
+ * what the end of their frame held. The test is on what records write, not
70
+ * what they read: one that only reads state written since — copying a
71
+ * predicted value into an entity nothing else writes — keeps what it read at
72
+ * the present until a replay crosses its frame. The replay is a
73
+ * reconciliation's, so a local record {@link onReplay} does not produce is
74
+ * lost from the frames it rebuilds. Records for a frame the action log has
75
+ * moved past have no frame to go in: they are applied where they land, and
76
+ * not logged.
77
+ *
57
78
  * - A no-op short-circuit is built in: before doing the rewind+replay, the
58
79
  * orchestrator gives the user a chance to compute what the replay WOULD
59
80
  * produce via {@link onComputeExpected}; if that matches the current
@@ -83,6 +104,7 @@ export class ServerAuthoritativeClient {
83
104
  * time_dilation?: TimeDilation,
84
105
  * max_packets_per_tick?: number,
85
106
  * auto_reconcile?: boolean,
107
+ * rebase_on_arrival?: boolean,
86
108
  * clock: function(): number,
87
109
  * tick_period_ms: number,
88
110
  * send_rate_bytes_per_second?: number,
@@ -96,8 +118,8 @@ export class ServerAuthoritativeClient {
96
118
  * `time_dilation`: optional pre-configured {@link TimeDilation}.
97
119
  * On TIME_DILATION feedback the client recomputes
98
120
  * {@link dilation_factor} for the caller to scale its tick cadence.
99
- * Defaults to a stock instance; `dilation_factor` is 1.0 until the
100
- * first feedback arrives.
121
+ * Defaults to one built for round trips up to `frame_capacity` frames;
122
+ * `dilation_factor` is 1.0 until the first feedback arrives.
101
123
  *
102
124
  * `max_packets_per_tick`: forwarded to {@link NetworkPeer}; how many
103
125
  * action-stream packets a tick may send the server.
@@ -107,8 +129,15 @@ export class ServerAuthoritativeClient {
107
129
  * own reconciliation — `NetworkSession` corrects by comparison instead —
108
130
  * turns it off and listens to `peer.onAuthState` itself; {@link reconcile}
109
131
  * remains available to it.
132
+ *
133
+ * `rebase_on_arrival` (default true): put the records a peer sends for a
134
+ * frame this client has already predicted past in that frame, under what it
135
+ * predicted since, by rewind and replay — see the class notes. It keeps the
136
+ * log true for the rewinds this client reconciles by. A caller that never
137
+ * rewinds — `NetworkSession` correcting by comparison — turns it off, and
138
+ * the records are applied to the world as it is when they arrive.
110
139
  */
111
- constructor({ world, binary_registry, replicated_components, action_classes, scope_filter, frame_capacity, initial_buffer_size, input_ring_capacity, input_byte_size, reconcile_epsilon, time_dilation, max_packets_per_tick, auto_reconcile, clock, tick_period_ms, send_rate_bytes_per_second, max_message_bytes, receive_window_bytes, max_queued_bytes, }: {
140
+ constructor({ world, binary_registry, replicated_components, action_classes, scope_filter, frame_capacity, initial_buffer_size, input_ring_capacity, input_byte_size, reconcile_epsilon, time_dilation, max_packets_per_tick, auto_reconcile, rebase_on_arrival, clock, tick_period_ms, send_rate_bytes_per_second, max_message_bytes, receive_window_bytes, max_queued_bytes, }: {
112
141
  world: EntityComponentDataset;
113
142
  binary_registry: BinarySerializationRegistry;
114
143
  replicated_components: Function[];
@@ -122,6 +151,7 @@ export class ServerAuthoritativeClient {
122
151
  time_dilation?: TimeDilation;
123
152
  max_packets_per_tick?: number;
124
153
  auto_reconcile?: boolean;
154
+ rebase_on_arrival?: boolean;
125
155
  clock: () => number;
126
156
  tick_period_ms: number;
127
157
  send_rate_bytes_per_second?: number;
@@ -131,7 +161,10 @@ export class ServerAuthoritativeClient {
131
161
  });
132
162
  /** @type {number} */
133
163
  reconcile_count: number;
134
- /** @type {number} */
164
+ /**
165
+ * Frames replayed, by reconciliations and by records put back in their frame.
166
+ * @type {number}
167
+ */
135
168
  replay_frame_count: number;
136
169
  /**
137
170
  * Records that arrived from a peer and were reapplied by a replay, over the
@@ -147,6 +180,13 @@ export class ServerAuthoritativeClient {
147
180
  * @type {number}
148
181
  */
149
182
  reconcile_abandoned_count: number;
183
+ /**
184
+ * Frames of records from a peer that arrived after this client had predicted past them, wrote
185
+ * something written later — in a frame after theirs, or by a correction of their own — and so
186
+ * were put back in their frame by a rewind and a replay. See {@link #land_arrived}.
187
+ * @type {number}
188
+ */
189
+ rebase_count: number;
150
190
  /** @type {NetworkPeer} */
151
191
  peer: NetworkPeer;
152
192
  /** @type {EntityComponentDataset} */
@@ -190,7 +230,10 @@ export class ServerAuthoritativeClient {
190
230
  /**
191
231
  * Tick-period multiplier from the latest TIME_DILATION feedback.
192
232
  * `< 1.0` ⇒ caller should run faster, `> 1.0` ⇒ slower. 1.0 until
193
- * the first feedback arrives.
233
+ * the first feedback arrives. It follows every report, and holds while
234
+ * none come: a caller that seeks its frames back, or loses the host,
235
+ * judges whether the latest report still holds before running at it, as
236
+ * `NetworkSession` does.
194
237
  *
195
238
  * scheduled_tick_period_ms = TICK_PERIOD_MS * client.dilation_factor;
196
239
  *
@@ -284,6 +327,9 @@ export class ServerAuthoritativeClient {
284
327
  * longer holds the frames its rewind needed. Args:
285
328
  * `(server_frame, network_id)`.
286
329
  *
330
+ * Nothing of it is done: the world stays at the present, and the
331
+ * server's state is not applied.
332
+ *
287
333
  * This is a real loss of replicated state and not a hiccup: state a peer
288
334
  * does not own reaches it on the action stream, and an owner that
289
335
  * publishes on change never sends it again — so whatever that window
@@ -1 +1 @@
1
- {"version":3,"file":"ServerAuthoritativeClient.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/orchestrator/ServerAuthoritativeClient.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ServerAuthoritativeClient.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/orchestrator/ServerAuthoritativeClient.js"],"names":[],"mappings":"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"}