@antha/multiplayer-server 0.1.1 → 0.1.2
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/README.md
CHANGED
|
@@ -29,7 +29,7 @@ await startMultiplayerServer({
|
|
|
29
29
|
|
|
30
30
|
## CLI
|
|
31
31
|
|
|
32
|
-
The `start-mp-server` command accepts a required path to a JavaScript, TypeScript, JSON, YAML, or TOML configuration file.
|
|
32
|
+
The `start-mp-server` command accepts a required path to a JavaScript, TypeScript, JSON, YAML, or TOML configuration file.
|
|
33
33
|
|
|
34
34
|
Create a configuration file:
|
|
35
35
|
|
|
@@ -53,3 +53,5 @@ Start the server with the configuration file path:
|
|
|
53
53
|
```sh
|
|
54
54
|
npx start-mp-server ./multiplayer-server.config.mjs
|
|
55
55
|
```
|
|
56
|
+
|
|
57
|
+
[The `ensure-service` package](https://www.npmjs.com/package/ensure-service) is recommended for making sure the server stays up.
|
package/dist/cli/cli.d.ts
CHANGED
|
@@ -1,6 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shape definition for {@link MultiplayerServerCliConfig}.
|
|
3
|
+
*
|
|
4
|
+
* @category Internal
|
|
5
|
+
*/
|
|
6
|
+
declare const multiplayerServerCliConfigShape: import("object-shape-tester").Shape<import("@sinclair/typebox").TUnsafe<{
|
|
7
|
+
logger?: {
|
|
8
|
+
error: (error: Error) => void;
|
|
9
|
+
info: (...args: ReadonlyArray<unknown>) => void;
|
|
10
|
+
} | null | undefined;
|
|
11
|
+
backendOrigin?: string | null | undefined;
|
|
12
|
+
games: {
|
|
13
|
+
default?: string | RegExp | import("@rest-vir/api").OriginCheckCallback | {
|
|
14
|
+
anyOriginWithCredentials?: undefined;
|
|
15
|
+
anyOrigin: true;
|
|
16
|
+
} | {
|
|
17
|
+
anyOrigin?: undefined;
|
|
18
|
+
anyOriginWithCredentials: true;
|
|
19
|
+
} | undefined;
|
|
20
|
+
byId: Record<string, string | RegExp | import("@rest-vir/api").OriginCheckCallback | {
|
|
21
|
+
anyOriginWithCredentials?: undefined;
|
|
22
|
+
anyOrigin: true;
|
|
23
|
+
} | {
|
|
24
|
+
anyOrigin?: undefined;
|
|
25
|
+
anyOriginWithCredentials: true;
|
|
26
|
+
}>;
|
|
27
|
+
} | {
|
|
28
|
+
byId?: Record<string, string | RegExp | import("@rest-vir/api").OriginCheckCallback | {
|
|
29
|
+
anyOriginWithCredentials?: undefined;
|
|
30
|
+
anyOrigin: true;
|
|
31
|
+
} | {
|
|
32
|
+
anyOrigin?: undefined;
|
|
33
|
+
anyOriginWithCredentials: true;
|
|
34
|
+
}> | undefined;
|
|
35
|
+
default: string | RegExp | import("@rest-vir/api").OriginCheckCallback | {
|
|
36
|
+
anyOriginWithCredentials?: undefined;
|
|
37
|
+
anyOrigin: true;
|
|
38
|
+
} | {
|
|
39
|
+
anyOrigin?: undefined;
|
|
40
|
+
anyOriginWithCredentials: true;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
} & {
|
|
44
|
+
host?: string | undefined;
|
|
45
|
+
lockPort?: boolean | undefined;
|
|
46
|
+
debug?: boolean | undefined;
|
|
47
|
+
port: number | undefined;
|
|
48
|
+
} & {
|
|
49
|
+
configReloadInterval?: (Required<Pick<{
|
|
50
|
+
years: number;
|
|
51
|
+
months: number;
|
|
52
|
+
weeks: number;
|
|
53
|
+
days: number;
|
|
54
|
+
hours: number;
|
|
55
|
+
minutes: number;
|
|
56
|
+
seconds: number;
|
|
57
|
+
milliseconds: number;
|
|
58
|
+
}, import("date-vir").DurationUnit.Years>> & Partial<Pick<{
|
|
59
|
+
years: number;
|
|
60
|
+
months: number;
|
|
61
|
+
weeks: number;
|
|
62
|
+
days: number;
|
|
63
|
+
hours: number;
|
|
64
|
+
minutes: number;
|
|
65
|
+
seconds: number;
|
|
66
|
+
milliseconds: number;
|
|
67
|
+
}, import("date-vir").DurationUnit.Months | import("date-vir").DurationUnit.Weeks | import("date-vir").DurationUnit.Days | import("date-vir").DurationUnit.Hours | import("date-vir").DurationUnit.Minutes | import("date-vir").DurationUnit.Seconds | import("date-vir").DurationUnit.Milliseconds>>) | (Required<Pick<{
|
|
68
|
+
years: number;
|
|
69
|
+
months: number;
|
|
70
|
+
weeks: number;
|
|
71
|
+
days: number;
|
|
72
|
+
hours: number;
|
|
73
|
+
minutes: number;
|
|
74
|
+
seconds: number;
|
|
75
|
+
milliseconds: number;
|
|
76
|
+
}, import("date-vir").DurationUnit.Months>> & Partial<Pick<{
|
|
77
|
+
years: number;
|
|
78
|
+
months: number;
|
|
79
|
+
weeks: number;
|
|
80
|
+
days: number;
|
|
81
|
+
hours: number;
|
|
82
|
+
minutes: number;
|
|
83
|
+
seconds: number;
|
|
84
|
+
milliseconds: number;
|
|
85
|
+
}, import("date-vir").DurationUnit.Years | import("date-vir").DurationUnit.Weeks | import("date-vir").DurationUnit.Days | import("date-vir").DurationUnit.Hours | import("date-vir").DurationUnit.Minutes | import("date-vir").DurationUnit.Seconds | import("date-vir").DurationUnit.Milliseconds>>) | (Required<Pick<{
|
|
86
|
+
years: number;
|
|
87
|
+
months: number;
|
|
88
|
+
weeks: number;
|
|
89
|
+
days: number;
|
|
90
|
+
hours: number;
|
|
91
|
+
minutes: number;
|
|
92
|
+
seconds: number;
|
|
93
|
+
milliseconds: number;
|
|
94
|
+
}, import("date-vir").DurationUnit.Weeks>> & Partial<Pick<{
|
|
95
|
+
years: number;
|
|
96
|
+
months: number;
|
|
97
|
+
weeks: number;
|
|
98
|
+
days: number;
|
|
99
|
+
hours: number;
|
|
100
|
+
minutes: number;
|
|
101
|
+
seconds: number;
|
|
102
|
+
milliseconds: number;
|
|
103
|
+
}, import("date-vir").DurationUnit.Years | import("date-vir").DurationUnit.Months | import("date-vir").DurationUnit.Days | import("date-vir").DurationUnit.Hours | import("date-vir").DurationUnit.Minutes | import("date-vir").DurationUnit.Seconds | import("date-vir").DurationUnit.Milliseconds>>) | (Required<Pick<{
|
|
104
|
+
years: number;
|
|
105
|
+
months: number;
|
|
106
|
+
weeks: number;
|
|
107
|
+
days: number;
|
|
108
|
+
hours: number;
|
|
109
|
+
minutes: number;
|
|
110
|
+
seconds: number;
|
|
111
|
+
milliseconds: number;
|
|
112
|
+
}, import("date-vir").DurationUnit.Days>> & Partial<Pick<{
|
|
113
|
+
years: number;
|
|
114
|
+
months: number;
|
|
115
|
+
weeks: number;
|
|
116
|
+
days: number;
|
|
117
|
+
hours: number;
|
|
118
|
+
minutes: number;
|
|
119
|
+
seconds: number;
|
|
120
|
+
milliseconds: number;
|
|
121
|
+
}, import("date-vir").DurationUnit.Years | import("date-vir").DurationUnit.Months | import("date-vir").DurationUnit.Weeks | import("date-vir").DurationUnit.Hours | import("date-vir").DurationUnit.Minutes | import("date-vir").DurationUnit.Seconds | import("date-vir").DurationUnit.Milliseconds>>) | (Required<Pick<{
|
|
122
|
+
years: number;
|
|
123
|
+
months: number;
|
|
124
|
+
weeks: number;
|
|
125
|
+
days: number;
|
|
126
|
+
hours: number;
|
|
127
|
+
minutes: number;
|
|
128
|
+
seconds: number;
|
|
129
|
+
milliseconds: number;
|
|
130
|
+
}, import("date-vir").DurationUnit.Hours>> & Partial<Pick<{
|
|
131
|
+
years: number;
|
|
132
|
+
months: number;
|
|
133
|
+
weeks: number;
|
|
134
|
+
days: number;
|
|
135
|
+
hours: number;
|
|
136
|
+
minutes: number;
|
|
137
|
+
seconds: number;
|
|
138
|
+
milliseconds: number;
|
|
139
|
+
}, import("date-vir").DurationUnit.Years | import("date-vir").DurationUnit.Months | import("date-vir").DurationUnit.Weeks | import("date-vir").DurationUnit.Days | import("date-vir").DurationUnit.Minutes | import("date-vir").DurationUnit.Seconds | import("date-vir").DurationUnit.Milliseconds>>) | (Required<Pick<{
|
|
140
|
+
years: number;
|
|
141
|
+
months: number;
|
|
142
|
+
weeks: number;
|
|
143
|
+
days: number;
|
|
144
|
+
hours: number;
|
|
145
|
+
minutes: number;
|
|
146
|
+
seconds: number;
|
|
147
|
+
milliseconds: number;
|
|
148
|
+
}, import("date-vir").DurationUnit.Minutes>> & Partial<Pick<{
|
|
149
|
+
years: number;
|
|
150
|
+
months: number;
|
|
151
|
+
weeks: number;
|
|
152
|
+
days: number;
|
|
153
|
+
hours: number;
|
|
154
|
+
minutes: number;
|
|
155
|
+
seconds: number;
|
|
156
|
+
milliseconds: number;
|
|
157
|
+
}, import("date-vir").DurationUnit.Years | import("date-vir").DurationUnit.Months | import("date-vir").DurationUnit.Weeks | import("date-vir").DurationUnit.Days | import("date-vir").DurationUnit.Hours | import("date-vir").DurationUnit.Seconds | import("date-vir").DurationUnit.Milliseconds>>) | (Required<Pick<{
|
|
158
|
+
years: number;
|
|
159
|
+
months: number;
|
|
160
|
+
weeks: number;
|
|
161
|
+
days: number;
|
|
162
|
+
hours: number;
|
|
163
|
+
minutes: number;
|
|
164
|
+
seconds: number;
|
|
165
|
+
milliseconds: number;
|
|
166
|
+
}, import("date-vir").DurationUnit.Seconds>> & Partial<Pick<{
|
|
167
|
+
years: number;
|
|
168
|
+
months: number;
|
|
169
|
+
weeks: number;
|
|
170
|
+
days: number;
|
|
171
|
+
hours: number;
|
|
172
|
+
minutes: number;
|
|
173
|
+
seconds: number;
|
|
174
|
+
milliseconds: number;
|
|
175
|
+
}, import("date-vir").DurationUnit.Years | import("date-vir").DurationUnit.Months | import("date-vir").DurationUnit.Weeks | import("date-vir").DurationUnit.Days | import("date-vir").DurationUnit.Hours | import("date-vir").DurationUnit.Minutes | import("date-vir").DurationUnit.Milliseconds>>) | (Required<Pick<{
|
|
176
|
+
years: number;
|
|
177
|
+
months: number;
|
|
178
|
+
weeks: number;
|
|
179
|
+
days: number;
|
|
180
|
+
hours: number;
|
|
181
|
+
minutes: number;
|
|
182
|
+
seconds: number;
|
|
183
|
+
milliseconds: number;
|
|
184
|
+
}, import("date-vir").DurationUnit.Milliseconds>> & Partial<Pick<{
|
|
185
|
+
years: number;
|
|
186
|
+
months: number;
|
|
187
|
+
weeks: number;
|
|
188
|
+
days: number;
|
|
189
|
+
hours: number;
|
|
190
|
+
minutes: number;
|
|
191
|
+
seconds: number;
|
|
192
|
+
milliseconds: number;
|
|
193
|
+
}, import("date-vir").DurationUnit.Years | import("date-vir").DurationUnit.Months | import("date-vir").DurationUnit.Weeks | import("date-vir").DurationUnit.Days | import("date-vir").DurationUnit.Hours | import("date-vir").DurationUnit.Minutes | import("date-vir").DurationUnit.Seconds>>) | null | undefined;
|
|
194
|
+
}>>;
|
|
195
|
+
/**
|
|
196
|
+
* Config for the CLI.
|
|
197
|
+
*
|
|
198
|
+
* @category CLI
|
|
199
|
+
*/
|
|
200
|
+
export type MultiplayerServerCliConfig = typeof multiplayerServerCliConfigShape.runtimeType;
|
|
1
201
|
/**
|
|
2
202
|
* Load a config file and start the multiplayer server from its options.
|
|
3
203
|
*
|
|
4
204
|
* @category Internal
|
|
5
205
|
*/
|
|
6
206
|
export declare function runMultiplayerServerCli(configFilePath: string): Promise<void>;
|
|
207
|
+
export {};
|
package/dist/cli/cli.js
CHANGED
|
@@ -1,14 +1,51 @@
|
|
|
1
|
+
import { assert } from '@augment-vir/assert';
|
|
2
|
+
import { ensureErrorAndPrependMessage, log } from '@augment-vir/common';
|
|
1
3
|
import { loadConfig } from 'config-vir';
|
|
4
|
+
import { atLeastOneDurationShape, convertDuration } from 'date-vir';
|
|
5
|
+
import { intersectShape, nullableShape } from 'object-shape-tester';
|
|
2
6
|
import { startMultiplayerServer, startMultiplayerServerOptionsShape } from '../start-server.js';
|
|
7
|
+
/**
|
|
8
|
+
* Shape definition for {@link MultiplayerServerCliConfig}.
|
|
9
|
+
*
|
|
10
|
+
* @category Internal
|
|
11
|
+
*/
|
|
12
|
+
const multiplayerServerCliConfigShape = intersectShape(startMultiplayerServerOptionsShape, {
|
|
13
|
+
/**
|
|
14
|
+
* How often to reload the config file.
|
|
15
|
+
*
|
|
16
|
+
* @default `{minutes: 5}`
|
|
17
|
+
*/
|
|
18
|
+
configReloadInterval: nullableShape(atLeastOneDurationShape()),
|
|
19
|
+
});
|
|
3
20
|
/**
|
|
4
21
|
* Load a config file and start the multiplayer server from its options.
|
|
5
22
|
*
|
|
6
23
|
* @category Internal
|
|
7
24
|
*/
|
|
8
25
|
export async function runMultiplayerServerCli(configFilePath) {
|
|
9
|
-
const config = await
|
|
10
|
-
|
|
11
|
-
configShape: startMultiplayerServerOptionsShape,
|
|
12
|
-
});
|
|
26
|
+
const config = await loadServerCliConfig(configFilePath, {});
|
|
27
|
+
assert.isDefined(config, 'No config loaded.');
|
|
13
28
|
await startMultiplayerServer(config);
|
|
14
29
|
}
|
|
30
|
+
async function loadServerCliConfig(configFilePath, existingConfig) {
|
|
31
|
+
try {
|
|
32
|
+
Object.assign(existingConfig, await loadConfig({
|
|
33
|
+
configPath: configFilePath,
|
|
34
|
+
configShape: multiplayerServerCliConfigShape,
|
|
35
|
+
}));
|
|
36
|
+
return existingConfig;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
log.error(ensureErrorAndPrependMessage(error, 'Failed to reload multiplayer config.'));
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
globalThis.setTimeout(async () => {
|
|
44
|
+
await loadServerCliConfig(configFilePath, existingConfig);
|
|
45
|
+
}, convertDuration(existingConfig.configReloadInterval || {
|
|
46
|
+
minutes: 5,
|
|
47
|
+
}, {
|
|
48
|
+
milliseconds: true,
|
|
49
|
+
}).milliseconds);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -20,6 +20,7 @@ export declare const multiplayerServerOptionsShape: import("object-shape-tester"
|
|
|
20
20
|
info: import("@sinclair/typebox").TUnsafe<(...args: ReadonlyArray<unknown>) => void>;
|
|
21
21
|
}>)[]>>>;
|
|
22
22
|
backendOrigin: import("object-shape-tester").Shape<import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUndefined | import("@sinclair/typebox").TNull | import("@sinclair/typebox").TString)[]>>>;
|
|
23
|
+
/** The server's supported list of games. */
|
|
23
24
|
games: import("object-shape-tester").Shape<import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TObject<{
|
|
24
25
|
byId: import("@sinclair/typebox").TUnsafe<Record<string, string | RegExp | import("@rest-vir/api").OriginCheckCallback | {
|
|
25
26
|
anyOriginWithCredentials?: undefined;
|
|
@@ -93,7 +94,9 @@ export type ImplementedMultiplayerApi = ReturnType<typeof implementMultiplayerAp
|
|
|
93
94
|
*
|
|
94
95
|
* @category Internal
|
|
95
96
|
*/
|
|
96
|
-
export declare function implementMultiplayerApi(
|
|
97
|
+
export declare function implementMultiplayerApi(
|
|
98
|
+
/** Server options. Any external mutations made to this object will be picked up by the server. */
|
|
99
|
+
options: Readonly<MultiplayerServerOptions>): {
|
|
97
100
|
serverState: MultiplayerServerState;
|
|
98
101
|
api: Readonly<import("@rest-vir/host").ApiImplementation<{
|
|
99
102
|
apiName: string;
|
|
@@ -28,6 +28,7 @@ export const multiplayerServerOptionsShape = defineShape({
|
|
|
28
28
|
info: (...args) => { },
|
|
29
29
|
}),
|
|
30
30
|
backendOrigin: nullableShape(''),
|
|
31
|
+
/** The server's supported list of games. */
|
|
31
32
|
games: unionShape({
|
|
32
33
|
/**
|
|
33
34
|
* Allow specific games by id. If a game id is not matched, the below `default`
|
|
@@ -71,7 +72,9 @@ export const defaultMultiplayerApiLogger = {
|
|
|
71
72
|
*
|
|
72
73
|
* @category Internal
|
|
73
74
|
*/
|
|
74
|
-
export function implementMultiplayerApi(
|
|
75
|
+
export function implementMultiplayerApi(
|
|
76
|
+
/** Server options. Any external mutations made to this object will be picked up by the server. */
|
|
77
|
+
options) {
|
|
75
78
|
const logger = options.logger || defaultMultiplayerApiLogger;
|
|
76
79
|
const roomHandler = createMultiplayerRoomHandler({
|
|
77
80
|
logger,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antha/multiplayer-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "An multiplayer server that can be used with the Antha multiplayer mod.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vir",
|
|
@@ -38,17 +38,17 @@
|
|
|
38
38
|
"test:docs": "virmator docs check"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@antha/multiplayer-core": "^0.1.
|
|
42
|
-
"@antha/multiplayer-p2p-lock-step": "^0.1.
|
|
41
|
+
"@antha/multiplayer-core": "^0.1.2",
|
|
42
|
+
"@antha/multiplayer-p2p-lock-step": "^0.1.2",
|
|
43
43
|
"@augment-vir/assert": "^32.2.2",
|
|
44
44
|
"@augment-vir/common": "^32.2.2",
|
|
45
45
|
"@augment-vir/node": "^32.2.2",
|
|
46
46
|
"@rest-vir/api": "^2.3.1",
|
|
47
47
|
"@rest-vir/host": "^2.3.1",
|
|
48
48
|
"cli-vir": "^1.0.5",
|
|
49
|
-
"config-vir": "^1.0.
|
|
50
|
-
"date-vir": "^9.
|
|
51
|
-
"object-shape-tester": "^6.
|
|
49
|
+
"config-vir": "^1.0.5",
|
|
50
|
+
"date-vir": "^9.1.0",
|
|
51
|
+
"object-shape-tester": "^6.15.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@augment-vir/test": "^32.2.2",
|
|
@@ -58,10 +58,10 @@
|
|
|
58
58
|
"@web/test-runner-playwright": "^1.0.0",
|
|
59
59
|
"c8": "^12.0.0",
|
|
60
60
|
"istanbul-smart-text-reporter": "^1.1.5",
|
|
61
|
-
"tsx": "^4.23.
|
|
61
|
+
"tsx": "^4.23.12"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
-
"@antha/engine": "^0.1.
|
|
64
|
+
"@antha/engine": "^0.1.2"
|
|
65
65
|
},
|
|
66
66
|
"engines": {
|
|
67
67
|
"node": ">=22"
|