94 lines
2.2 KiB
TypeScript
94 lines
2.2 KiB
TypeScript
import { NetworkedPredictedEngine } from "./networked-client.js";
|
|
import { NetworkedAuthoritativeEngine } from "./networked-server.js";
|
|
import type { NetworkedGameDefinition } from "./networked-types.js";
|
|
import { createBinaryProtocol, type BinaryProtocol } from "./protocol.js";
|
|
import type { ServerEngineOptions } from "./server.js";
|
|
|
|
export interface DefinedNetworkedGame<
|
|
AuthorityState,
|
|
ClientState,
|
|
Input,
|
|
AuthorityEvent = never,
|
|
PerceptionEvent = never,
|
|
> extends NetworkedGameDefinition<
|
|
AuthorityState,
|
|
ClientState,
|
|
Input,
|
|
AuthorityEvent,
|
|
PerceptionEvent
|
|
> {
|
|
protocol: BinaryProtocol<Input, ClientState, PerceptionEvent>;
|
|
createServer(
|
|
options?: ServerEngineOptions,
|
|
): NetworkedAuthoritativeEngine<
|
|
AuthorityState,
|
|
ClientState,
|
|
Input,
|
|
AuthorityEvent,
|
|
PerceptionEvent
|
|
>;
|
|
createClient(): NetworkedPredictedEngine<
|
|
AuthorityState,
|
|
ClientState,
|
|
Input,
|
|
AuthorityEvent,
|
|
PerceptionEvent
|
|
>;
|
|
}
|
|
|
|
export function defineNetworkedGame<
|
|
AuthorityState,
|
|
ClientState,
|
|
Input,
|
|
AuthorityEvent = never,
|
|
PerceptionEvent = never,
|
|
>(
|
|
definition: NetworkedGameDefinition<
|
|
AuthorityState,
|
|
ClientState,
|
|
Input,
|
|
AuthorityEvent,
|
|
PerceptionEvent
|
|
>,
|
|
): DefinedNetworkedGame<
|
|
AuthorityState,
|
|
ClientState,
|
|
Input,
|
|
AuthorityEvent,
|
|
PerceptionEvent
|
|
> {
|
|
validateRates(definition.tickRateHz, definition.snapshotRateHz);
|
|
|
|
const protocol = createBinaryProtocol<Input, ClientState, PerceptionEvent>(
|
|
definition.codecs,
|
|
);
|
|
|
|
return Object.freeze({
|
|
...definition,
|
|
protocol,
|
|
createServer(options?: ServerEngineOptions) {
|
|
return new NetworkedAuthoritativeEngine(definition, options);
|
|
},
|
|
createClient() {
|
|
return new NetworkedPredictedEngine(definition);
|
|
},
|
|
});
|
|
}
|
|
|
|
function validateRates(tickRateHz: number, snapshotRateHz: number): void {
|
|
if (!Number.isInteger(tickRateHz) || tickRateHz <= 0) {
|
|
throw new RangeError("tickRateHz must be a positive integer");
|
|
}
|
|
|
|
if (
|
|
!Number.isInteger(snapshotRateHz) ||
|
|
snapshotRateHz <= 0 ||
|
|
snapshotRateHz > tickRateHz ||
|
|
tickRateHz % snapshotRateHz !== 0
|
|
) {
|
|
throw new RangeError(
|
|
"snapshotRateHz must be a positive divisor of tickRateHz",
|
|
);
|
|
}
|
|
}
|