@woosh/meep-engine 3.46.0 → 3.47.0
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.
- package/editor/actions/concrete/TransformModifyAction.d.ts.map +1 -1
- package/editor/actions/concrete/TransformModifyAction.js +10 -2
- package/editor/ecs/component/FieldDescriptor.js +15 -0
- package/editor/ecs/component/createObjectEditor.js +41 -12
- package/editor/ecs/component/editors/ecs/Transform64Editor.d.ts.map +1 -1
- package/editor/ecs/component/editors/ecs/Transform64Editor.js +77 -70
- package/editor/tools/TransformToolV2.d.ts.map +1 -1
- package/editor/tools/TransformToolV2.js +4 -0
- package/editor/tools/v2/TransformControls.d.ts.map +1 -1
- package/editor/tools/v2/TransformControls.js +7 -0
- package/editor/view/ecs/EntityEditor.d.ts.map +1 -1
- package/editor/view/ecs/EntityEditor.js +4 -2
- package/package.json +1 -1
- package/src/core/collection/array/array_insert_at.d.ts +16 -0
- package/src/core/collection/array/array_insert_at.d.ts.map +1 -0
- package/src/core/collection/array/array_insert_at.js +32 -0
- package/src/core/collection/array/array_remove_at.d.ts +15 -0
- package/src/core/collection/array/array_remove_at.d.ts.map +1 -0
- package/src/core/collection/array/array_remove_at.js +30 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.d.ts +37 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.js +172 -0
- package/src/core/geom/Quaternion.d.ts +1 -0
- package/src/core/geom/Quaternion.d.ts.map +1 -1
- package/src/core/geom/Quaternion.js +12 -48
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +9 -4
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +10 -0
- package/src/engine/ecs/transform/t64_look_rotation.d.ts +4 -4
- package/src/engine/ecs/transform/t64_look_rotation.d.ts.map +1 -1
- package/src/engine/ecs/transform/t64_look_rotation.js +7 -18
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +30 -1
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +6 -0
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/GPUParticleEmitterSystem.js +72 -29
- package/src/engine/input/devices/KeyboardDevice.d.ts +1 -0
- package/src/engine/input/devices/KeyboardDevice.d.ts.map +1 -1
- package/src/engine/input/devices/KeyboardDevice.js +7 -6
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.d.ts.map +1 -1
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.js +15 -2
- package/src/engine/network/CONGESTION_CONTROL.md +9 -9
- package/src/engine/network/MESSAGE_TRANSPORT.md +364 -0
- package/src/engine/network/NetworkSession.d.ts +31 -11
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +453 -286
- package/src/engine/network/README.md +77 -27
- package/src/engine/network/SMOOTHNESS_DESIGN.md +13 -5
- package/src/engine/network/diagnostics/BandwidthMeter.d.ts +1 -1
- package/src/engine/network/diagnostics/BandwidthMeter.js +1 -1
- package/src/engine/network/orchestrator/HostJoin.d.ts +111 -0
- package/src/engine/network/orchestrator/HostJoin.d.ts.map +1 -0
- package/src/engine/network/orchestrator/HostJoin.js +271 -0
- package/src/engine/network/orchestrator/NetworkPeer.d.ts +151 -112
- package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/NetworkPeer.js +450 -499
- package/src/engine/network/orchestrator/PendingSlices.d.ts +30 -0
- package/src/engine/network/orchestrator/PendingSlices.d.ts.map +1 -0
- package/src/engine/network/orchestrator/PendingSlices.js +83 -0
- package/src/engine/network/orchestrator/ReliableFrames.d.ts +34 -0
- package/src/engine/network/orchestrator/ReliableFrames.d.ts.map +1 -0
- package/src/engine/network/orchestrator/ReliableFrames.js +96 -0
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +77 -10
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +236 -61
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +20 -6
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +33 -8
- package/src/engine/network/replication/Replicator.d.ts.map +1 -1
- package/src/engine/network/replication/Replicator.js +7 -1
- package/src/engine/network/sim/ActionLog.d.ts +32 -5
- package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
- package/src/engine/network/sim/ActionLog.js +47 -5
- package/src/engine/network/sim/SimActionExecutor.d.ts +42 -2
- package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
- package/src/engine/network/sim/SimActionExecutor.js +100 -4
- package/src/engine/network/sim/Snapshotter.d.ts +12 -0
- package/src/engine/network/sim/Snapshotter.d.ts.map +1 -1
- package/src/engine/network/sim/Snapshotter.js +43 -0
- package/src/engine/network/state/Baseline.d.ts +1 -1
- package/src/engine/network/state/Baseline.js +1 -1
- package/src/engine/network/state/FrameBufferRing.d.ts +25 -6
- package/src/engine/network/state/FrameBufferRing.d.ts.map +1 -1
- package/src/engine/network/state/FrameBufferRing.js +51 -6
- package/src/engine/network/state/InputRing.d.ts +4 -0
- package/src/engine/network/state/InputRing.d.ts.map +1 -1
- package/src/engine/network/state/InputRing.js +7 -0
- package/src/engine/network/transport/DeferredTransport.d.ts.map +1 -1
- package/src/engine/network/transport/DeferredTransport.js +1 -0
- package/src/engine/network/transport/LoopbackTransport.d.ts.map +1 -1
- package/src/engine/network/transport/LoopbackTransport.js +4 -2
- package/src/engine/network/transport/Transport.d.ts +7 -0
- package/src/engine/network/transport/Transport.d.ts.map +1 -1
- package/src/engine/network/transport/Transport.js +8 -0
- package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/NodeUDPTransport.js +20 -5
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +8 -0
- package/src/engine/network/transport/adapters/WebTransportTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebTransportTransport.js +6 -0
- package/src/engine/network/transport/connection/Connection.d.ts +191 -0
- package/src/engine/network/transport/connection/Connection.d.ts.map +1 -0
- package/src/engine/network/transport/connection/Connection.js +1262 -0
- package/src/engine/network/transport/connection/RangeSet.d.ts +94 -0
- package/src/engine/network/transport/connection/RangeSet.d.ts.map +1 -0
- package/src/engine/network/transport/connection/RangeSet.js +260 -0
- package/src/engine/network/transport/connection/RxStream.d.ts +48 -0
- package/src/engine/network/transport/connection/RxStream.d.ts.map +1 -0
- package/src/engine/network/transport/connection/RxStream.js +211 -0
- package/src/engine/network/transport/connection/TxStream.d.ts +90 -0
- package/src/engine/network/transport/connection/TxStream.d.ts.map +1 -0
- package/src/engine/network/transport/connection/TxStream.js +243 -0
- package/src/engine/network/transport/connection/bytes_copy.d.ts +17 -0
- package/src/engine/network/transport/connection/bytes_copy.d.ts.map +1 -0
- package/src/engine/network/transport/connection/bytes_copy.js +34 -0
- package/src/engine/network/transport/connection/varint.d.ts +46 -0
- package/src/engine/network/transport/connection/varint.d.ts.map +1 -0
- package/src/engine/network/transport/connection/varint.js +107 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/sound/ecs/audio/AudioEmitter.d.ts +38 -7
- package/src/engine/sound/ecs/audio/AudioEmitter.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitter.js +35 -7
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.js +5 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.d.ts +18 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.js +48 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts +12 -2
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.js +173 -9
- package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts +9 -3
- package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/LiveEmitterSet.js +28 -8
- package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts +8 -0
- package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.js +5 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.d.ts +18 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.js +51 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.js +15 -1
- package/src/engine/sound/sopra/README.md +768 -644
- package/src/engine/sound/sopra/SopraEngine.d.ts +104 -8
- package/src/engine/sound/sopra/SopraEngine.d.ts.map +1 -1
- package/src/engine/sound/sopra/SopraEngine.js +327 -12
- package/src/engine/sound/sopra/definition/EventDescription.d.ts +28 -2
- package/src/engine/sound/sopra/definition/EventDescription.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/EventDescription.js +55 -5
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts +10 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +77 -55
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.d.ts +31 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.js +75 -0
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts +38 -9
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +34 -5
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts +7 -2
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +137 -122
- package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts +3 -1
- package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/EqEffect.js +146 -131
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts +1 -0
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +6 -1
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts +44 -2
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts.map +1 -1
- package/src/engine/sound/sopra/runtime/BusGraph.js +83 -43
- package/src/engine/sound/sopra/runtime/EffectChain.d.ts +96 -0
- package/src/engine/sound/sopra/runtime/EffectChain.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/EffectChain.js +286 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.d.ts +123 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.js +320 -0
- package/src/engine/sound/sopra/runtime/EventInstance.d.ts +55 -5
- package/src/engine/sound/sopra/runtime/EventInstance.d.ts.map +1 -1
- package/src/engine/sound/sopra/runtime/EventInstance.js +201 -26
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts +2 -1
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts.map +1 -1
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +6 -1
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts +15 -0
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts.map +1 -1
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +32 -0
- package/src/engine/sound/sopra/util/MockAudioContext.d.ts.map +1 -1
- package/src/engine/sound/sopra/util/MockAudioContext.js +3 -0
- package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts +13 -3
- package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts.map +1 -1
- package/src/engine/sound/sopra/util/fadeOutAndStop.js +25 -13
- package/src/shade/RENDERER_CONTRACT.md +6 -3
- package/src/shade/device/SHADE_DEVICE_FLOOR.d.ts +24 -0
- package/src/shade/device/SHADE_DEVICE_FLOOR.d.ts.map +1 -0
- package/src/shade/device/SHADE_DEVICE_FLOOR.js +34 -0
- package/src/shade/device/ShadeDeviceFailure.d.ts +12 -5
- package/src/shade/device/ShadeDeviceFailure.d.ts.map +1 -1
- package/src/shade/device/ShadeDeviceFailure.js +17 -8
- package/src/shade/device/ShadeDeviceFailureReason.d.ts +1 -1
- package/src/shade/device/ShadeDeviceFailureReason.js +2 -2
- package/src/shade/device/shade_device_floor_unmet.d.ts +13 -0
- package/src/shade/device/shade_device_floor_unmet.d.ts.map +1 -0
- package/src/shade/device/shade_device_floor_unmet.js +32 -0
- package/src/shade/renderer/Renderer.d.ts +2 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +29 -55
- package/src/shade/renderer/buffer/GPUBufferAllocator.d.ts.map +1 -1
- package/src/shade/renderer/buffer/GPUBufferAllocator.js +9 -0
- package/src/shade/renderer/buffer/buffer_pool_ops.d.ts +21 -12
- package/src/shade/renderer/buffer/buffer_pool_ops.d.ts.map +1 -1
- package/src/shade/renderer/buffer/buffer_pool_ops.js +18 -19
- package/src/shade/renderer/gpu_primitive/test/gpu_test.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/test/gpu_test.js +8 -11
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/pool/TransientResourcePool.d.ts +24 -0
- package/src/shade/renderer/pool/TransientResourcePool.d.ts.map +1 -1
- package/src/shade/renderer/pool/TransientResourcePool.js +41 -10
- package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ComputeShader.js +18 -2
- package/src/shade/renderer/shader/ImageShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ImageShader.js +230 -218
- package/src/view/graphics/GraphicsContextFailureView.d.ts +1 -2
- package/src/view/graphics/GraphicsContextFailureView.d.ts.map +1 -1
- package/src/view/graphics/GraphicsContextFailureView.js +1 -2
- package/src/engine/network/transport/Channel.js +0 -336
- package/src/engine/network/transport/ReliableCommandPipeline.js +0 -335
- package/src/engine/network/transport/fragments/FragmentAssembler.js +0 -350
- package/src/engine/network/transport/fragments/FragmentRetention.js +0 -191
- package/src/engine/network/transport/fragments/fragment_send.js +0 -157
- package/src/engine/network/transport/fragments/packet_size.js +0 -107
|
@@ -5,17 +5,18 @@ import Signal from "../../../core/events/signal/Signal.js";
|
|
|
5
5
|
import { AlwaysRelevantScope } from "../replication/ScopeFilter.js";
|
|
6
6
|
import { ActionRecordCursor } from "../sim/ActionRecordCursor.js";
|
|
7
7
|
import { RewindEngine } from "../sim/RewindEngine.js";
|
|
8
|
+
import { SENDER_CORRECTED } from "../sim/SimActionExecutor.js";
|
|
8
9
|
import { InputRing } from "../state/InputRing.js";
|
|
9
10
|
import { TimeDilation } from "../time/TimeDilation.js";
|
|
10
11
|
import { NetworkPeer } from "./NetworkPeer.js";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Ints per harvested record in {@link ServerAuthoritativeClient}'s replay index:
|
|
14
|
-
* action type id, sender id, and the offset of its payload.
|
|
15
|
+
* action type id, sender id, and the offset and length of its payload.
|
|
15
16
|
*
|
|
16
17
|
* @type {number}
|
|
17
18
|
*/
|
|
18
|
-
const HARVEST_STRIDE =
|
|
19
|
+
const HARVEST_STRIDE = 4;
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Client-side orchestrator for the predict-reconcile model.
|
|
@@ -29,14 +30,37 @@ const HARVEST_STRIDE = 3;
|
|
|
29
30
|
* action_log via the executor (capturing prior-state for later rewind),
|
|
30
31
|
* and goes out over the action stream when `peer.end_tick` flushes it.
|
|
31
32
|
*
|
|
32
|
-
* - On AUTH_STATE arrival: rewind the world to end
|
|
33
|
-
* via the {@link RewindEngine},
|
|
34
|
-
* state bytes via {@link onApplyAuthState}, then replay
|
|
35
|
-
* firing {@link onReplay} for every frame in the InputRing
|
|
36
|
-
* `server_frame + 1` and the client's current frame. The user's
|
|
33
|
+
* - On AUTH_STATE arrival: rewind the world to the end of `server_frame`
|
|
34
|
+
* via the {@link RewindEngine}, overwrite it there with the server's
|
|
35
|
+
* authoritative state bytes via {@link onApplyAuthState}, then replay
|
|
36
|
+
* forward by firing {@link onReplay} for every frame in the InputRing
|
|
37
|
+
* between `server_frame + 1` and the client's current frame. The user's
|
|
37
38
|
* {@link onReplay} handler re-executes the same SimActions the original
|
|
38
39
|
* predict path produced.
|
|
39
40
|
*
|
|
41
|
+
* An AUTH_STATE is the server's state at the END of `server_frame`, and it
|
|
42
|
+
* is put back at exactly that point. It covers one `network_id`; the rest of
|
|
43
|
+
* the world at that point is this client's own prediction of it, which
|
|
44
|
+
* already holds the frame's input — so frame `server_frame` itself is never
|
|
45
|
+
* undone, and nothing in it is lost or applied twice. (Undoing it and then
|
|
46
|
+
* skipping it, which this did, took the frame's input back off every
|
|
47
|
+
* predicted entity the bytes do not describe.)
|
|
48
|
+
*
|
|
49
|
+
* - An applied AUTH_STATE stays on the timeline as a correction: a
|
|
50
|
+
* `SENDER_CORRECTED` record at the end of `server_frame` in the action log,
|
|
51
|
+
* holding the entity's state from before it and the bytes
|
|
52
|
+
* {@link onApplyAuthState} read. A rewind across the frame undoes it like any
|
|
53
|
+
* record, and the replay applies it again, last in its frame. Both halves
|
|
54
|
+
* matter when one entity's AUTH_STATE arrives after another's newer one,
|
|
55
|
+
* which a lossy link does routinely. Without the replay half the older
|
|
56
|
+
* rewind replayed the prediction underneath the newer correction and left
|
|
57
|
+
* that entity on its misprediction until its next AUTH_STATE. Without the
|
|
58
|
+
* undo half the newer correction stayed in the world while the older frames
|
|
59
|
+
* replayed, so an action there that read the entity read the server's value
|
|
60
|
+
* from a later frame. The record is never packed for a peer — this log is
|
|
61
|
+
* also the outbound stream, and the host would take a client-owned entity's
|
|
62
|
+
* old state from it.
|
|
63
|
+
*
|
|
40
64
|
* - A replay also reapplies the records in the rewound window that ARRIVED
|
|
41
65
|
* from a peer, which {@link onReplay} cannot: it re-executes this client's
|
|
42
66
|
* own input, and the AUTH_STATE that precedes it carries one `network_id`.
|
|
@@ -79,10 +103,11 @@ export class ServerAuthoritativeClient {
|
|
|
79
103
|
#measured_scratch;
|
|
80
104
|
|
|
81
105
|
/**
|
|
82
|
-
* Records of one log frame that arrived from a peer,
|
|
83
|
-
* {@link HARVEST_STRIDE} ints apiece into
|
|
84
|
-
* by {@link #
|
|
85
|
-
* {@link #execute_harvested}
|
|
106
|
+
* Records of one log frame that a replay puts back — arrived from a peer,
|
|
107
|
+
* or corrections — indexed {@link HARVEST_STRIDE} ints apiece into
|
|
108
|
+
* {@link #harvest_payloads}. Filled by {@link #harvest} before the frame is
|
|
109
|
+
* reopened and drained by {@link #execute_harvested} and
|
|
110
|
+
* {@link #reapply_corrections} once it is.
|
|
86
111
|
* @type {Int32Array}
|
|
87
112
|
*/
|
|
88
113
|
#harvest_index = new Int32Array(HARVEST_STRIDE * 32);
|
|
@@ -102,6 +127,17 @@ export class ServerAuthoritativeClient {
|
|
|
102
127
|
/** @type {ActionRecordCursor} */
|
|
103
128
|
#harvest_cursor = new ActionRecordCursor();
|
|
104
129
|
|
|
130
|
+
/**
|
|
131
|
+
* A correction record's payload, composed before it is logged: the network
|
|
132
|
+
* id, its slot generation, and the bytes {@link onApplyAuthState} read.
|
|
133
|
+
*
|
|
134
|
+
* Each is about one entity, not one id: a correction whose id has since been
|
|
135
|
+
* freed, or freed and handed to another entity, is dropped by the replay
|
|
136
|
+
* rather than written onto that one.
|
|
137
|
+
* @type {BinaryBuffer}
|
|
138
|
+
*/
|
|
139
|
+
#correction_payload = new BinaryBuffer();
|
|
140
|
+
|
|
105
141
|
// Counters
|
|
106
142
|
/** @type {number} */
|
|
107
143
|
reconcile_count = 0;
|
|
@@ -140,8 +176,16 @@ export class ServerAuthoritativeClient {
|
|
|
140
176
|
* time_dilation?: TimeDilation,
|
|
141
177
|
* max_packets_per_tick?: number,
|
|
142
178
|
* auto_reconcile?: boolean,
|
|
179
|
+
* clock: function(): number,
|
|
180
|
+
* tick_period_ms: number,
|
|
181
|
+
* send_rate_bytes_per_second?: number,
|
|
182
|
+
* max_message_bytes?: number,
|
|
183
|
+
* receive_window_bytes?: number,
|
|
184
|
+
* max_queued_bytes?: number,
|
|
143
185
|
* }} options
|
|
144
186
|
*
|
|
187
|
+
* `clock`, `tick_period_ms` and the connection options: forwarded to {@link NetworkPeer}.
|
|
188
|
+
*
|
|
145
189
|
* `time_dilation`: optional pre-configured {@link TimeDilation}.
|
|
146
190
|
* On TIME_DILATION feedback the client recomputes
|
|
147
191
|
* {@link dilation_factor} for the caller to scale its tick cadence.
|
|
@@ -171,6 +215,12 @@ export class ServerAuthoritativeClient {
|
|
|
171
215
|
time_dilation = new TimeDilation(),
|
|
172
216
|
max_packets_per_tick,
|
|
173
217
|
auto_reconcile = true,
|
|
218
|
+
clock,
|
|
219
|
+
tick_period_ms,
|
|
220
|
+
send_rate_bytes_per_second,
|
|
221
|
+
max_message_bytes,
|
|
222
|
+
receive_window_bytes,
|
|
223
|
+
max_queued_bytes,
|
|
174
224
|
}) {
|
|
175
225
|
/** @type {NetworkPeer} */
|
|
176
226
|
this.peer = new NetworkPeer({
|
|
@@ -182,6 +232,12 @@ export class ServerAuthoritativeClient {
|
|
|
182
232
|
frame_capacity,
|
|
183
233
|
initial_buffer_size,
|
|
184
234
|
max_packets_per_tick,
|
|
235
|
+
clock,
|
|
236
|
+
tick_period_ms,
|
|
237
|
+
send_rate_bytes_per_second,
|
|
238
|
+
max_message_bytes,
|
|
239
|
+
receive_window_bytes,
|
|
240
|
+
max_queued_bytes,
|
|
185
241
|
});
|
|
186
242
|
|
|
187
243
|
/** @type {EntityComponentDataset} */
|
|
@@ -321,6 +377,14 @@ export class ServerAuthoritativeClient {
|
|
|
321
377
|
* payload bytes. The handler should deserialize the bytes into
|
|
322
378
|
* the world (the rewind has already happened; the buffer's bytes
|
|
323
379
|
* ARE the new authoritative state at server_frame).
|
|
380
|
+
*
|
|
381
|
+
* The handler must leave `buffer.position` past what it read: those
|
|
382
|
+
* bytes are what this client keeps as the correction, and a later
|
|
383
|
+
* replay that crosses `server_frame` fires this again, at the end of
|
|
384
|
+
* that frame, with a buffer positioned at them.
|
|
385
|
+
*
|
|
386
|
+
* Write only the entity's replicated components: the correction's
|
|
387
|
+
* prior state, which a rewind puts back, is captured for those.
|
|
324
388
|
* @type {Signal}
|
|
325
389
|
*/
|
|
326
390
|
this.onApplyAuthState = new Signal();
|
|
@@ -381,10 +445,12 @@ export class ServerAuthoritativeClient {
|
|
|
381
445
|
this.peer.disconnect_peer(peer_id);
|
|
382
446
|
}
|
|
383
447
|
|
|
384
|
-
/**
|
|
385
|
-
* @
|
|
386
|
-
|
|
387
|
-
|
|
448
|
+
/**
|
|
449
|
+
* The server's connection, for diagnostics. See {@link NetworkPeer#connection_for}.
|
|
450
|
+
* @param {number} peer_id
|
|
451
|
+
*/
|
|
452
|
+
connection_for(peer_id) {
|
|
453
|
+
return this.peer.connection_for(peer_id);
|
|
388
454
|
}
|
|
389
455
|
|
|
390
456
|
/**
|
|
@@ -422,7 +488,8 @@ export class ServerAuthoritativeClient {
|
|
|
422
488
|
}
|
|
423
489
|
|
|
424
490
|
/**
|
|
425
|
-
* Second half of a tick: close the frame and
|
|
491
|
+
* Second half of a tick: close the frame and send the action stream, with everything else
|
|
492
|
+
* queued, to the server.
|
|
426
493
|
*/
|
|
427
494
|
end_tick() {
|
|
428
495
|
this.peer.end_tick();
|
|
@@ -472,6 +539,30 @@ export class ServerAuthoritativeClient {
|
|
|
472
539
|
this.#handle_auth_state(server_frame, network_id, buffer);
|
|
473
540
|
}
|
|
474
541
|
|
|
542
|
+
/**
|
|
543
|
+
* Forget everything this client holds about the frames it has run: the
|
|
544
|
+
* action log's records — the kept corrections among them — the sampled
|
|
545
|
+
* input, and the newest reconciled frame per network id.
|
|
546
|
+
*
|
|
547
|
+
* For when the frame numbering they were kept under is replaced — a resync
|
|
548
|
+
* that brings a new world and seeks the clock, possibly backwards. Kept, a
|
|
549
|
+
* correction from the old numbering would be written into the new one by
|
|
550
|
+
* the first replay that crosses its frame number, and the old watermark
|
|
551
|
+
* would refuse the new AUTH_STATEs that should overwrite it. The log and the
|
|
552
|
+
* input matter where the seek leaves frames the new world never runs: a
|
|
553
|
+
* sync at host frame F seeks past F by the input lead, and a rewind to F
|
|
554
|
+
* crosses the frames in between — it would put back the old world's prior
|
|
555
|
+
* state from the records there, and the replay would hand the old input
|
|
556
|
+
* to {@link onReplay}.
|
|
557
|
+
*
|
|
558
|
+
* Must be called with no frame open.
|
|
559
|
+
*/
|
|
560
|
+
forget_timeline() {
|
|
561
|
+
this.#last_reconciled_frame.clear();
|
|
562
|
+
this.action_log.empty_frames();
|
|
563
|
+
this.input_ring.clear();
|
|
564
|
+
}
|
|
565
|
+
|
|
475
566
|
/** @private */
|
|
476
567
|
#handle_auth_state(server_frame, network_id, buffer) {
|
|
477
568
|
// Out-of-order safety: never reconcile to an older frame than the
|
|
@@ -512,16 +603,25 @@ export class ServerAuthoritativeClient {
|
|
|
512
603
|
|
|
513
604
|
this.onBeforeReconcile.send2(server_frame, network_id);
|
|
514
605
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
606
|
+
/*
|
|
607
|
+
Real divergence: rewind to the END of `server_frame`, overwrite there,
|
|
608
|
+
replay what came after.
|
|
609
|
+
|
|
610
|
+
The AUTH_STATE describes the end of `server_frame`, so that is where it
|
|
611
|
+
goes. Everything it does not describe stays as this client predicted it
|
|
612
|
+
at that point — the frame's input included, which the server's state
|
|
613
|
+
holds too. Undoing frame `server_frame` instead and skipping it on the
|
|
614
|
+
way back took its input off every predicted entity but `network_id`; a
|
|
615
|
+
client predicting two entities lost a frame of the other one's input on
|
|
616
|
+
every reconciliation, and compounding, since the next entity's rewind
|
|
617
|
+
to the same frame undid the first one's correction again.
|
|
618
|
+
*/
|
|
619
|
+
if (this.#current_frame > server_frame) {
|
|
519
620
|
try {
|
|
520
|
-
this.rewind_engine.rewind_to(this.#current_frame,
|
|
521
|
-
rewound = true;
|
|
621
|
+
this.rewind_engine.rewind_to(this.#current_frame, server_frame);
|
|
522
622
|
} catch (e) {
|
|
523
623
|
/*
|
|
524
|
-
The action_log rolled past server_frame
|
|
624
|
+
The action_log rolled past `server_frame + 1`, so the window this
|
|
525
625
|
reconciliation needs no longer exists and skipping it is the
|
|
526
626
|
only option left. Counted and announced rather than swallowed:
|
|
527
627
|
what the window carried for every entity other than this one is
|
|
@@ -534,41 +634,17 @@ export class ServerAuthoritativeClient {
|
|
|
534
634
|
}
|
|
535
635
|
}
|
|
536
636
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
Its ARRIVED records are the other half of the frame, and the half that
|
|
543
|
-
was being dropped. The bytes below repair one `network_id`; every other
|
|
544
|
-
entity the frame touched has nothing else to restore it. They go back in
|
|
545
|
-
BEFORE those bytes, so the authoritative value still wins wherever the
|
|
546
|
-
two describe the same component.
|
|
547
|
-
|
|
548
|
-
In the ordinary owner-scoped arrangement this is the frame that matters
|
|
549
|
-
most: the owner's records for a frame land in the log at the owner's
|
|
550
|
-
frame number, which is at or below `server_frame`, so they sit at the
|
|
551
|
-
very bottom of the rewound window rather than inside the replay range.
|
|
552
|
-
*/
|
|
553
|
-
if (rewound && this.#harvest_arrived(server_frame) > 0) {
|
|
554
|
-
this.action_log.begin_frame(server_frame);
|
|
555
|
-
try {
|
|
556
|
-
this.#execute_harvested();
|
|
557
|
-
} finally {
|
|
558
|
-
this.action_log.end_frame();
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
// Apply the server's authoritative state bytes. The handler does the
|
|
563
|
-
// adapter-specific deserialize.
|
|
564
|
-
this.onApplyAuthState.send3(server_frame, network_id, buffer);
|
|
637
|
+
// Apply the server's authoritative state bytes, logged as a correction
|
|
638
|
+
// at the end of `server_frame`. The handler does the adapter-specific
|
|
639
|
+
// deserialize, and what it read is the correction.
|
|
640
|
+
this.#apply_correction(server_frame, network_id, local, buffer);
|
|
565
641
|
|
|
566
642
|
// Replay forward from (server_frame + 1) through current_frame.
|
|
567
643
|
let replay_count = 0;
|
|
568
644
|
for (let f = server_frame + 1; f <= this.#current_frame; f++) {
|
|
569
645
|
// Harvested before `begin_frame`, which rewinds the frame's buffer
|
|
570
|
-
// over the bytes being read.
|
|
571
|
-
const
|
|
646
|
+
// over the bytes being read.
|
|
647
|
+
const harvested = this.#harvest(f);
|
|
572
648
|
|
|
573
649
|
this.action_log.begin_frame(f);
|
|
574
650
|
try {
|
|
@@ -586,7 +662,12 @@ export class ServerAuthoritativeClient {
|
|
|
586
662
|
arrived later. It also leaves the owner's value last, which is
|
|
587
663
|
the one that should win where both touch a component.
|
|
588
664
|
*/
|
|
589
|
-
if (
|
|
665
|
+
if (harvested > 0) {
|
|
666
|
+
this.#execute_harvested();
|
|
667
|
+
|
|
668
|
+
// Last of all: a correction is the server's word on the END of its frame.
|
|
669
|
+
this.#reapply_corrections(f);
|
|
670
|
+
}
|
|
590
671
|
} finally {
|
|
591
672
|
this.action_log.end_frame();
|
|
592
673
|
}
|
|
@@ -599,8 +680,97 @@ export class ServerAuthoritativeClient {
|
|
|
599
680
|
}
|
|
600
681
|
|
|
601
682
|
/**
|
|
602
|
-
*
|
|
603
|
-
*
|
|
683
|
+
* Overwrite `local` with the server's state at the end of `frame` through
|
|
684
|
+
* {@link onApplyAuthState}, logged as a `SENDER_CORRECTED` record appended
|
|
685
|
+
* to that frame: the entity's prior state, so a rewind across the frame
|
|
686
|
+
* undoes it, and the bytes the handler read, so a replay applies it again.
|
|
687
|
+
*
|
|
688
|
+
* A frame the log does not hold — not reached yet, the client running behind
|
|
689
|
+
* the server — or a frame open for writing leaves nothing to log into; the
|
|
690
|
+
* correction is then applied as it stands and a rewind will not undo it.
|
|
691
|
+
*
|
|
692
|
+
* @param {number} frame
|
|
693
|
+
* @param {number} network_id
|
|
694
|
+
* @param {number} local
|
|
695
|
+
* @param {BinaryBuffer} buffer positioned at the server's bytes
|
|
696
|
+
* @private
|
|
697
|
+
*/
|
|
698
|
+
#apply_correction(frame, network_id, local, buffer) {
|
|
699
|
+
const log = this.action_log;
|
|
700
|
+
|
|
701
|
+
if (frame > this.#current_frame || log.has_open_frame() || !log.has_frame(frame)) {
|
|
702
|
+
this.onApplyAuthState.send3(frame, network_id, buffer);
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
const payload_start = buffer.position;
|
|
707
|
+
|
|
708
|
+
log.resume_frame(frame);
|
|
709
|
+
try {
|
|
710
|
+
this.executor.begin_correction(local);
|
|
711
|
+
try {
|
|
712
|
+
this.onApplyAuthState.send3(frame, network_id, buffer);
|
|
713
|
+
} finally {
|
|
714
|
+
const length = buffer.position - payload_start;
|
|
715
|
+
assert.greaterThanOrEqual(length, 0, 'onApplyAuthState moved the buffer backwards');
|
|
716
|
+
|
|
717
|
+
const payload = this.#correction_payload;
|
|
718
|
+
payload.position = 0;
|
|
719
|
+
payload.writeUintVar(network_id);
|
|
720
|
+
payload.writeUintVar(this.slot_table.generation_of(network_id));
|
|
721
|
+
payload.writeBytes(buffer.raw_bytes, payload_start, length);
|
|
722
|
+
|
|
723
|
+
this.executor.end_correction(payload.raw_bytes, 0, payload.position);
|
|
724
|
+
}
|
|
725
|
+
} finally {
|
|
726
|
+
log.end_frame();
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Apply again, through {@link onApplyAuthState}, every correction
|
|
732
|
+
* {@link #harvest} took from the frame now open — the replay has just
|
|
733
|
+
* rebuilt it from input and arrived records, and the server's state is what
|
|
734
|
+
* its end actually was. Each is logged again as it was the first time, prior
|
|
735
|
+
* state captured from what the replay rebuilt, so the next rewind across the
|
|
736
|
+
* frame undoes it in turn.
|
|
737
|
+
*
|
|
738
|
+
* A correction whose entity is gone — its id freed, or freed and handed to
|
|
739
|
+
* another entity since — is dropped: it describes nothing here any more.
|
|
740
|
+
*
|
|
741
|
+
* @param {number} frame
|
|
742
|
+
* @private
|
|
743
|
+
*/
|
|
744
|
+
#reapply_corrections(frame) {
|
|
745
|
+
const payloads = this.#harvest_payloads;
|
|
746
|
+
const slot_table = this.slot_table;
|
|
747
|
+
|
|
748
|
+
for (let record = 0; record < this.#harvest_count; record++) {
|
|
749
|
+
const i = record * HARVEST_STRIDE;
|
|
750
|
+
if (this.#harvest_index[i + 1] !== SENDER_CORRECTED) continue;
|
|
751
|
+
|
|
752
|
+
const payload_start = this.#harvest_index[i + 2];
|
|
753
|
+
const payload_length = this.#harvest_index[i + 3];
|
|
754
|
+
|
|
755
|
+
payloads.position = payload_start;
|
|
756
|
+
const network_id = payloads.readUintVar();
|
|
757
|
+
const generation = payloads.readUintVar();
|
|
758
|
+
|
|
759
|
+
const local = slot_table.entity_for(network_id);
|
|
760
|
+
if (local < 0 || slot_table.generation_of(network_id) !== generation) continue;
|
|
761
|
+
|
|
762
|
+
this.executor.begin_correction(local);
|
|
763
|
+
try {
|
|
764
|
+
this.onApplyAuthState.send3(frame, network_id, payloads);
|
|
765
|
+
} finally {
|
|
766
|
+
this.executor.end_correction(payloads.raw_bytes, payload_start, payload_length);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* Copy the records of `frame` that a replay puts back out of the action
|
|
773
|
+
* log, ready for {@link #execute_harvested} and {@link #reapply_corrections}.
|
|
604
774
|
*
|
|
605
775
|
* MUST be called before `action_log.begin_frame(frame)`. Opening a frame
|
|
606
776
|
* rewinds its buffer to zero without clearing it, and the re-execution
|
|
@@ -613,6 +783,8 @@ export class ServerAuthoritativeClient {
|
|
|
613
783
|
* - a CONNECTED peer's id — it arrived from that peer, and nothing else
|
|
614
784
|
* here reproduces it. `onApplyAuthState` covers one `network_id` and
|
|
615
785
|
* {@link onReplay} covers this client's own input. Kept.
|
|
786
|
+
* - `SENDER_CORRECTED` — a server's correction, applied again at the end
|
|
787
|
+
* of the frame. Kept.
|
|
616
788
|
* - `SENDER_DERIVED` — output a replay recomputes. Skipped, same as
|
|
617
789
|
* `ServerAuthoritativeServer.#read_historical` skips it.
|
|
618
790
|
* - `SENDER_LOCAL`, and this client's own peer id — its own input, which
|
|
@@ -628,7 +800,7 @@ export class ServerAuthoritativeClient {
|
|
|
628
800
|
* @returns {number} how many records were harvested
|
|
629
801
|
* @private
|
|
630
802
|
*/
|
|
631
|
-
#
|
|
803
|
+
#harvest(frame) {
|
|
632
804
|
this.#harvest_count = 0;
|
|
633
805
|
this.#harvest_payloads.position = 0;
|
|
634
806
|
|
|
@@ -639,7 +811,8 @@ export class ServerAuthoritativeClient {
|
|
|
639
811
|
const bytes = cursor.buffer.raw_bytes;
|
|
640
812
|
|
|
641
813
|
while (cursor.next()) {
|
|
642
|
-
|
|
814
|
+
const sender_id = cursor.sender_id;
|
|
815
|
+
if (sender_id !== SENDER_CORRECTED && !this.peer.is_connected(sender_id)) continue;
|
|
643
816
|
|
|
644
817
|
if ((this.#harvest_count + 1) * HARVEST_STRIDE > this.#harvest_index.length) {
|
|
645
818
|
this.#grow_harvest_index();
|
|
@@ -647,8 +820,9 @@ export class ServerAuthoritativeClient {
|
|
|
647
820
|
|
|
648
821
|
const i = this.#harvest_count * HARVEST_STRIDE;
|
|
649
822
|
this.#harvest_index[i] = cursor.action_type_id;
|
|
650
|
-
this.#harvest_index[i + 1] =
|
|
823
|
+
this.#harvest_index[i + 1] = sender_id;
|
|
651
824
|
this.#harvest_index[i + 2] = this.#harvest_payloads.position;
|
|
825
|
+
this.#harvest_index[i + 3] = cursor.payload_len;
|
|
652
826
|
this.#harvest_count++;
|
|
653
827
|
|
|
654
828
|
this.#harvest_payloads.writeBytes(bytes, cursor.payload_start, cursor.payload_len);
|
|
@@ -658,8 +832,8 @@ export class ServerAuthoritativeClient {
|
|
|
658
832
|
}
|
|
659
833
|
|
|
660
834
|
/**
|
|
661
|
-
* Re-execute
|
|
662
|
-
* currently-open frame.
|
|
835
|
+
* Re-execute the arrived records {@link #harvest} took, in log order, into
|
|
836
|
+
* the currently-open frame.
|
|
663
837
|
*
|
|
664
838
|
* Going back through the executor is the point rather than an implementation
|
|
665
839
|
* detail: it captures each record's prior bytes again as it applies, so the
|
|
@@ -676,6 +850,7 @@ export class ServerAuthoritativeClient {
|
|
|
676
850
|
const i = record * HARVEST_STRIDE;
|
|
677
851
|
const type_id = this.#harvest_index[i];
|
|
678
852
|
const sender_id = this.#harvest_index[i + 1];
|
|
853
|
+
if (sender_id === SENDER_CORRECTED) continue;
|
|
679
854
|
const payload_start = this.#harvest_index[i + 2];
|
|
680
855
|
|
|
681
856
|
const klass = this.action_registry.klass_for(type_id);
|
|
@@ -102,11 +102,19 @@ export class ServerAuthoritativeServer {
|
|
|
102
102
|
* simulation_delay_ticks?: number,
|
|
103
103
|
* max_packets_per_tick?: number,
|
|
104
104
|
* late_input?: LateInput|string,
|
|
105
|
+
* clock: function(): number,
|
|
106
|
+
* tick_period_ms: number,
|
|
107
|
+
* send_rate_bytes_per_second?: number,
|
|
108
|
+
* max_message_bytes?: number,
|
|
109
|
+
* receive_window_bytes?: number,
|
|
110
|
+
* max_queued_bytes?: number,
|
|
105
111
|
* }} options
|
|
106
112
|
*
|
|
107
113
|
* `max_packets_per_tick`: forwarded to {@link NetworkPeer}; how many
|
|
108
114
|
* action-stream packets a tick may send one peer.
|
|
109
115
|
*
|
|
116
|
+
* `clock`, `tick_period_ms` and the connection options: forwarded to {@link NetworkPeer}.
|
|
117
|
+
*
|
|
110
118
|
* `late_input`: see {@link LateInput}. Default {@link LateInput.Rollback}.
|
|
111
119
|
*
|
|
112
120
|
* `simulation_delay_ticks`: server-side input buffer (Overwatch-style).
|
|
@@ -118,7 +126,7 @@ export class ServerAuthoritativeServer {
|
|
|
118
126
|
* input-to-feedback latency (client prediction hides it). Default 0
|
|
119
127
|
* reproduces pre-feature behavior.
|
|
120
128
|
*/
|
|
121
|
-
constructor({ world, binary_registry, replicated_components, action_classes, scope_filter, frame_capacity, initial_buffer_size, simulation_delay_ticks, max_pending_future_lead, max_pending_total, identity_class, server_peer_id, max_packets_per_tick, late_input, }: {
|
|
129
|
+
constructor({ world, binary_registry, replicated_components, action_classes, scope_filter, frame_capacity, initial_buffer_size, simulation_delay_ticks, max_pending_future_lead, max_pending_total, identity_class, server_peer_id, max_packets_per_tick, late_input, clock, tick_period_ms, send_rate_bytes_per_second, max_message_bytes, receive_window_bytes, max_queued_bytes, }: {
|
|
122
130
|
world: EntityComponentDataset;
|
|
123
131
|
binary_registry: BinarySerializationRegistry;
|
|
124
132
|
replicated_components: Function[];
|
|
@@ -129,6 +137,12 @@ export class ServerAuthoritativeServer {
|
|
|
129
137
|
simulation_delay_ticks?: number;
|
|
130
138
|
max_packets_per_tick?: number;
|
|
131
139
|
late_input?: LateInput | string;
|
|
140
|
+
clock: () => number;
|
|
141
|
+
tick_period_ms: number;
|
|
142
|
+
send_rate_bytes_per_second?: number;
|
|
143
|
+
max_message_bytes?: number;
|
|
144
|
+
receive_window_bytes?: number;
|
|
145
|
+
max_queued_bytes?: number;
|
|
132
146
|
});
|
|
133
147
|
/**
|
|
134
148
|
* Most recently simulated frame. `-1` during warmup
|
|
@@ -304,11 +318,10 @@ export class ServerAuthoritativeServer {
|
|
|
304
318
|
*/
|
|
305
319
|
send_auth_state(peer_id: number, frame_number: number, network_id: number, write_fn: (buf: BinaryBuffer) => void): void;
|
|
306
320
|
/**
|
|
307
|
-
*
|
|
308
|
-
* empty ACK packets in the prototype). Most callers won't need this.
|
|
321
|
+
* A peer's connection, for diagnostics. See {@link NetworkPeer#connection_for}.
|
|
309
322
|
* @param {number} peer_id
|
|
310
323
|
*/
|
|
311
|
-
|
|
324
|
+
connection_for(peer_id: number): import("../transport/connection/Connection.js").Connection;
|
|
312
325
|
/**
|
|
313
326
|
* Send the current buffer-depth observation for one peer to that peer.
|
|
314
327
|
* Convenience wrapper around {@link NetworkPeer#send_time_dilation_feedback}
|
|
@@ -378,8 +391,9 @@ export class ServerAuthoritativeServer {
|
|
|
378
391
|
begin_tick(current_frame: number): void;
|
|
379
392
|
/**
|
|
380
393
|
* Second half of a tick: run {@link onLocalSim} for the open frame, close it, publish the new
|
|
381
|
-
* {@link current_sim_frame},
|
|
382
|
-
*
|
|
394
|
+
* {@link current_sim_frame}, queue the action stream, fire {@link onTickComplete}, and send
|
|
395
|
+
* everything queued — what the handlers queued included, so the tick leaves together. After a
|
|
396
|
+
* warmup {@link begin_tick} it only sends what is queued.
|
|
383
397
|
*/
|
|
384
398
|
end_tick(): void;
|
|
385
399
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerAuthoritativeServer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/orchestrator/ServerAuthoritativeServer.js"],"names":[],"mappings":";;;wBAmBU,MAAM;AAJhB;;;;;GAKG;AACH;IACI;;;;OAIG;;IAEH;;;;OAIG;;GAEJ;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH;IA2DI
|
|
1
|
+
{"version":3,"file":"ServerAuthoritativeServer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/orchestrator/ServerAuthoritativeServer.js"],"names":[],"mappings":";;;wBAmBU,MAAM;AAJhB;;;;;GAKG;AACH;IACI;;;;OAIG;;IAEH;;;;OAIG;;GAEJ;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH;IA2DI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,uXAnCW;QACV,KAAS,yBAAyB;QAClC,eAAmB,8BAA8B;QACjD,qBAAyB,EAAE,UAAU,CAAC;QACtC,cAAkB,EAAE,UAAU,CAAC;QAC/B,YAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,cAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,mBAAuB,CAAC,EAAE,MAAM,CAAC;QACjC,sBAA0B,CAAC,EAAE,MAAM,CAAC;QACpC,oBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,UAAc,CAAC,EAAE,SAAS,GAAC,MAAM,CAAC;QAClC,KAAS,QAAc,MAAM,CAAC;QAC9B,cAAkB,EAAE,MAAM,CAAC;QAC3B,0BAA8B,CAAC,EAAE,MAAM,CAAC;QACxC,iBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,oBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,gBAAoB,CAAC,EAAE,MAAM,CAAC;KAC3B,EAgRH;IA1SD;;;;;OAKG;IACH,mBAFU,MAAM,CAEO;IAmEnB;;;;OAIG;IACH,qBAFU,SAAS,GAAC,MAAM,CAEE;IAC5B,0BAA0B;IAC1B,MADW,WAAW,CAgBpB;IAEF,qCAAqC;IACrC,8BAAkB;IAClB,gCAAgC;IAChC,4BAAkC;IAclC,mCAAmC;IACnC,iCAAsC;IACtC,wBAAwB;IACxB,sBAAsC;IACtC,gCAAgC;IAChC,mCAAgD;IAChD,0CAA0C;IAC1C,gDAAsD;IAEtD,2BAA2B;IAC3B,eADW,YAAY,CAKrB;IAEF;;;;;;OAMG;IACH,6BAFU,MAAM,CAEqB;IAErC;;;;OAIG;IACH,wBAFU,MAAM,CAEoC;IAEpD;;;;;;;OAOG;IACH,gBAFU,MAAM,CAEoB;IAEpC;;;;;;;;;OASG;IACH,yBAFU,MAAM,CAEsC;IAEtD;;;;;;;;;OASG;IACH,mBAFU,MAAM,CAE0B;IAyC1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,YAFU,MAAM,CAEc;IAE9B;;;;;;;OAOG;IACH,gBAFU,MAAM,CAEkB;IAElC;;;;;;;OAOG;IACH,mBAFU,MAAM,CAEqB;IAErC;;;;;;;;;;;OAWG;IACH,UAFU,MAAM,CAEY;IAE5B;;;;;;;OAOG;IACH,wBAFU,MAAM,CAE0B;IAG9C;;;;;;;OAOG;IACH,sBAHW,MAAM,aACN,MAAM,QAIhB;IAED;;;OAGG;IACH,yBAFW,MAAM,QAIhB;IAED;;;;;;;;OAQG;IACH,yBALW,MAAM,gBACN,MAAM,cACN,MAAM,YACN,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,QAIrC;IAED;;;OAGG;IACH,wBAFW,MAAM,8DAIhB;IAED;;;;;;;;OAQG;IACH,qCAFW,MAAM,QAIhB;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,wCA8BC;IAED;;;OAGG;IACH,6BAFa,MAAM,CAIlB;IAED;;;;;;;;;;;;;OAaG;IACH,oBAFW,MAAM,QAKhB;IAED;;;;;;;;;OASG;IACH,0BAFW,MAAM,QAqEhB;IAED;;;;;OAKG;IACH,iBAsBC;IAED;;;OAGG;IACH,yBAEC;IAED;;;;;;;;OAQG;IACH,+BAHW,MAAM,GACJ,MAAM,CAOlB;IAoQD;;;;OAIG;IACH,yBAFa,MAAM,CAIlB;;CA6MJ;4BA9pC2B,kBAAkB;6BAFjB,wBAAwB;mBAPlC,uCAAuC;6BAH7B,sCAAsC"}
|
|
@@ -172,11 +172,19 @@ export class ServerAuthoritativeServer {
|
|
|
172
172
|
* simulation_delay_ticks?: number,
|
|
173
173
|
* max_packets_per_tick?: number,
|
|
174
174
|
* late_input?: LateInput|string,
|
|
175
|
+
* clock: function(): number,
|
|
176
|
+
* tick_period_ms: number,
|
|
177
|
+
* send_rate_bytes_per_second?: number,
|
|
178
|
+
* max_message_bytes?: number,
|
|
179
|
+
* receive_window_bytes?: number,
|
|
180
|
+
* max_queued_bytes?: number,
|
|
175
181
|
* }} options
|
|
176
182
|
*
|
|
177
183
|
* `max_packets_per_tick`: forwarded to {@link NetworkPeer}; how many
|
|
178
184
|
* action-stream packets a tick may send one peer.
|
|
179
185
|
*
|
|
186
|
+
* `clock`, `tick_period_ms` and the connection options: forwarded to {@link NetworkPeer}.
|
|
187
|
+
*
|
|
180
188
|
* `late_input`: see {@link LateInput}. Default {@link LateInput.Rollback}.
|
|
181
189
|
*
|
|
182
190
|
* `simulation_delay_ticks`: server-side input buffer (Overwatch-style).
|
|
@@ -203,6 +211,12 @@ export class ServerAuthoritativeServer {
|
|
|
203
211
|
server_peer_id = -1,
|
|
204
212
|
max_packets_per_tick,
|
|
205
213
|
late_input = LateInput.Rollback,
|
|
214
|
+
clock,
|
|
215
|
+
tick_period_ms,
|
|
216
|
+
send_rate_bytes_per_second,
|
|
217
|
+
max_message_bytes,
|
|
218
|
+
receive_window_bytes,
|
|
219
|
+
max_queued_bytes,
|
|
206
220
|
}) {
|
|
207
221
|
assert.isNonNegativeInteger(simulation_delay_ticks, 'simulation_delay_ticks');
|
|
208
222
|
assert.isPositiveInteger(max_pending_future_lead, 'max_pending_future_lead');
|
|
@@ -227,6 +241,12 @@ export class ServerAuthoritativeServer {
|
|
|
227
241
|
frame_capacity,
|
|
228
242
|
initial_buffer_size,
|
|
229
243
|
max_packets_per_tick,
|
|
244
|
+
clock,
|
|
245
|
+
tick_period_ms,
|
|
246
|
+
send_rate_bytes_per_second,
|
|
247
|
+
max_message_bytes,
|
|
248
|
+
receive_window_bytes,
|
|
249
|
+
max_queued_bytes,
|
|
230
250
|
});
|
|
231
251
|
|
|
232
252
|
/** @type {EntityComponentDataset} */
|
|
@@ -466,12 +486,11 @@ export class ServerAuthoritativeServer {
|
|
|
466
486
|
}
|
|
467
487
|
|
|
468
488
|
/**
|
|
469
|
-
*
|
|
470
|
-
* empty ACK packets in the prototype). Most callers won't need this.
|
|
489
|
+
* A peer's connection, for diagnostics. See {@link NetworkPeer#connection_for}.
|
|
471
490
|
* @param {number} peer_id
|
|
472
491
|
*/
|
|
473
|
-
|
|
474
|
-
return this.peer.
|
|
492
|
+
connection_for(peer_id) {
|
|
493
|
+
return this.peer.connection_for(peer_id);
|
|
475
494
|
}
|
|
476
495
|
|
|
477
496
|
/**
|
|
@@ -484,7 +503,7 @@ export class ServerAuthoritativeServer {
|
|
|
484
503
|
* @param {number} peer_id
|
|
485
504
|
*/
|
|
486
505
|
send_time_dilation_feedback(peer_id) {
|
|
487
|
-
this.peer.send_time_dilation_feedback(peer_id, this.buffer_depth_for_peer(peer_id));
|
|
506
|
+
this.peer.send_time_dilation_feedback(peer_id, this.buffer_depth_for_peer(peer_id), Math.max(0, this.current_sim_frame));
|
|
488
507
|
}
|
|
489
508
|
|
|
490
509
|
/**
|
|
@@ -652,13 +671,18 @@ export class ServerAuthoritativeServer {
|
|
|
652
671
|
|
|
653
672
|
/**
|
|
654
673
|
* Second half of a tick: run {@link onLocalSim} for the open frame, close it, publish the new
|
|
655
|
-
* {@link current_sim_frame},
|
|
656
|
-
*
|
|
674
|
+
* {@link current_sim_frame}, queue the action stream, fire {@link onTickComplete}, and send
|
|
675
|
+
* everything queued — what the handlers queued included, so the tick leaves together. After a
|
|
676
|
+
* warmup {@link begin_tick} it only sends what is queued.
|
|
657
677
|
*/
|
|
658
678
|
end_tick() {
|
|
659
679
|
const sim_frame = this.#open_sim_frame;
|
|
660
680
|
|
|
661
|
-
if (sim_frame === -1)
|
|
681
|
+
if (sim_frame === -1) {
|
|
682
|
+
// warmup, or no begin_tick: nothing simulated, but answers and acknowledgements go
|
|
683
|
+
this.peer.send_queued();
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
662
686
|
|
|
663
687
|
this.#open_sim_frame = -1;
|
|
664
688
|
|
|
@@ -672,6 +696,7 @@ export class ServerAuthoritativeServer {
|
|
|
672
696
|
this.current_sim_frame = sim_frame;
|
|
673
697
|
this.peer.flush_outbound(sim_frame);
|
|
674
698
|
this.onTickComplete.send1(sim_frame);
|
|
699
|
+
this.peer.send_queued();
|
|
675
700
|
}
|
|
676
701
|
|
|
677
702
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Replicator.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/replication/Replicator.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Replicator.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/replication/Replicator.js"],"names":[],"mappings":"AAsBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH;IAiLI;;;;;;;;OAQG;IACH,iFARW;QACV,UAAc,YAAY;QAC1B,eAAmB,oBAAoB;QACvC,QAAY,oBAAoB;QAChC,UAAc,uBAAuB;QACrC,YAAgB,EAAE;YAAE,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC;KACpF,EA6BH;IA5ID;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,wBAHW,MAAM,GACJ;QAAC,iBAAiB,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAC,CAc1F;IA2BD;;;;;;;;;;;;;OAaG;IACH,gBAFU,MAAM,CAEc;IAE9B;;;;;;;;;;;;;;;;;OAiBG;IACH,mBAFU,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAEvI;IAmBrB;;OAEG;IACH,sBAA4B;IAE5B;;OAEG;IACH,mCAAsC;IAEtC;;OAEG;IACH,4BAAwB;IAExB;;OAEG;IACH,iCAA4B;IAE5B;;;;OAIG;IACH,cAFU;QAAE,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAE9C;IAGpC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,uBAVW,MAAM,eACN,MAAM,aACN,MAAM,cACN,YAAY,cACZ,MAAM,GACJ,MAAM,CAoFlB;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,0BALW,MAAM,aACN,YAAY,iBACZ,MAAM,UACN;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAC,GAAC,IAAI,QAoEtE;IAqRD;;;;;;;OAOG;IACH,qBAFW,MAAM,QAKhB;;CA8CJ;mBA7xBkB,uCAAuC;6BAD7B,sCAAsC"}
|