@tsukilabs/nil-ffi 0.7.2 → 0.7.4

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/dist/def.d.ts CHANGED
@@ -16,6 +16,22 @@ export declare const definitions: {
16
16
  readonly arguments: readonly [ffi.types.UINT_32];
17
17
  readonly return: ffi.types.VOID;
18
18
  };
19
+ readonly nil_is_host: {
20
+ readonly arguments: readonly [ffi.types.UINT_32];
21
+ readonly return: ffi.types.VOID;
22
+ };
23
+ readonly nil_start_server: {
24
+ readonly arguments: readonly [ffi.types.UINT_32, ffi.types.POINTER];
25
+ readonly return: ffi.types.VOID;
26
+ };
27
+ readonly nil_start_server_with_savedata: {
28
+ readonly arguments: readonly [ffi.types.UINT_32, ffi.types.POINTER];
29
+ readonly return: ffi.types.VOID;
30
+ };
31
+ readonly nil_stop_server: {
32
+ readonly arguments: readonly [ffi.types.UINT_32];
33
+ readonly return: ffi.types.VOID;
34
+ };
19
35
  readonly nil_client_version: {
20
36
  readonly arguments: readonly [ffi.types.UINT_32];
21
37
  readonly return: ffi.types.VOID;
@@ -56,6 +72,14 @@ export declare const definitions: {
56
72
  readonly arguments: readonly [ffi.types.UINT_32];
57
73
  readonly return: ffi.types.VOID;
58
74
  };
75
+ readonly nil_runtime_num_alive_tasks: {
76
+ readonly arguments: readonly [ffi.types.UINT_32];
77
+ readonly return: ffi.types.VOID;
78
+ };
79
+ readonly nil_runtime_num_workers: {
80
+ readonly arguments: readonly [ffi.types.UINT_32];
81
+ readonly return: ffi.types.VOID;
82
+ };
59
83
  readonly nil_add_academy_recruit_order: {
60
84
  readonly arguments: readonly [ffi.types.UINT_32, ffi.types.POINTER];
61
85
  readonly return: ffi.types.VOID;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { definitions } from './def';
2
2
  import { Option } from '@tb-dev/utils';
3
- import { GetRemoteWorldsResponse } from '@tsukilabs/nil-bindings';
3
+ import { QueueOptions } from './queue';
4
+ import { AuthorizeRequest, ffi_UpdateClient, GetPlayerIdsRequest, GetPlayerIdsResponse, GetPlayerRequest, GetPlayerStatusRequest, GetRemoteWorldsResponse, LocalServer, PlayerExistsRequest, ServerAddr, SetPlayerStatusRequest, SpawnPlayerRequest, ValidateTokenRequest, ValidateTokenResponse, WorldOptions } from '@tsukilabs/nil-bindings';
4
5
  import * as ffi from "node:ffi";
5
6
  export * from './def';
6
7
  export * from './error';
@@ -8,21 +9,48 @@ export type Handle = ffi.DynamicLibraryResult<typeof definitions>;
8
9
  export declare const VERSION: string;
9
10
  export declare const USER_AGENT: string;
10
11
  export declare class Nil implements Disposable {
12
+ readonly path: string;
11
13
  private readonly handle;
12
14
  readonly functions: Handle["functions"];
13
15
  private readonly queue;
14
16
  private disposed;
15
17
  private constructor();
16
- static init(dll: string): Promise<Nil>;
18
+ static init(dll: string, options?: NilOptions): Promise<Nil>;
19
+ static initLatest(outDir?: Option<string>, options?: NilOptions): Promise<Nil>;
20
+ static downloadLatest(outDir?: Option<string>): Promise<string>;
17
21
  [Symbol.dispose](): void;
18
22
  close(): void;
23
+ isClosed(): boolean;
24
+ authorize(req: AuthorizeRequest): Promise<string>;
19
25
  getClientVersion(): Promise<string>;
20
26
  getFfiVersion(): Promise<string>;
27
+ getPlayer(req: GetPlayerRequest): Promise<import('@tsukilabs/nil-bindings').Player>;
28
+ getPlayerIds(req: GetPlayerIdsRequest): Promise<GetPlayerIdsResponse>;
29
+ getPlayerStatus(req: GetPlayerStatusRequest): Promise<import('@tsukilabs/nil-bindings').PlayerStatus>;
21
30
  getRemoteWorldLimit(): Promise<number>;
22
31
  getRemoteWorldLimitPerUser(): Promise<number>;
23
32
  getRemoteWorlds(): Promise<GetRemoteWorldsResponse>;
33
+ getRuntimeNumAliveTasks(): Promise<number>;
34
+ getRuntimeNumWorkers(): Promise<number>;
35
+ getServerAddr(): Promise<ServerAddr>;
36
+ getServerKind(): Promise<import('@tsukilabs/nil-bindings').ServerKind>;
24
37
  getUserAgent(): Promise<string>;
25
- getWorld(): Promise<Option<string>>;
26
- setUserAgent(userAgent: string): Promise<void>;
27
- private throwIfClosed;
38
+ getWorldId(): Promise<Option<string>>;
39
+ isHost(): Promise<boolean>;
40
+ isLocal(): Promise<boolean>;
41
+ isReady(): Promise<boolean>;
42
+ isRemote(): Promise<boolean>;
43
+ playerExists(req: PlayerExistsRequest): Promise<boolean>;
44
+ setPlayerStatus(req: SetPlayerStatusRequest): Promise<import('@tb-dev/utils').nil>;
45
+ setUserAgent(userAgent: string): Promise<import('@tb-dev/utils').nil>;
46
+ spawnPlayer(req: SpawnPlayerRequest): Promise<import('@tb-dev/utils').nil>;
47
+ startServer(options: WorldOptions): Promise<LocalServer>;
48
+ startServerWithSavedata(path: string): Promise<LocalServer>;
49
+ stopClient(): Promise<import('@tb-dev/utils').nil>;
50
+ stopServer(): Promise<import('@tb-dev/utils').nil>;
51
+ updateClient(options: ffi_UpdateClient): Promise<import('@tb-dev/utils').nil>;
52
+ validateToken(req: ValidateTokenRequest): Promise<ValidateTokenResponse>;
53
+ }
54
+ export interface NilOptions {
55
+ onError?: QueueOptions["onError"];
28
56
  }
package/dist/index.js CHANGED
@@ -1,179 +1,11 @@
1
1
  import * as ffi from "node:ffi";
2
- import { EventEmitter } from "node:events";
3
- import { isNil } from "es-toolkit/predicate";
4
2
  import * as process from "node:process";
3
+ import { cwd } from "node:process";
5
4
  import { ffi_Status } from "@tsukilabs/nil-bindings";
6
- //#region src/request.ts
7
- //! Copyright (C) Call of Nil contributors
8
- //! SPDX-License-Identifier: AGPL-3.0-only
9
- var RequestId = class {
10
- #current = 0;
11
- next() {
12
- if (this.#current >= 4294967295) this.#current = 0;
13
- return ++this.#current;
14
- }
15
- };
16
- //#endregion
17
- //#region src/ptr.ts
18
- //! Copyright (C) Call of Nil contributors
19
- //! SPDX-License-Identifier: AGPL-3.0-only
20
- function allocBuffer(size) {
21
- return Buffer.alloc(size ?? pointerSize());
22
- }
23
- function readBufferPtr(buffer) {
24
- if (pointerSize() === 8) return buffer.readBigUInt64LE();
25
- else return BigInt(buffer.readUInt32LE());
26
- }
27
- function pointerSize() {
28
- if (process.arch === "x64" || process.arch === "arm64") return 8;
29
- else return 4;
30
- }
31
- //#endregion
32
- //#region src/error.ts
33
- //! Copyright (C) Call of Nil contributors
34
- //! SPDX-License-Identifier: AGPL-3.0-only
35
- var NilError = class NilError extends Error {
36
- constructor(message, options) {
37
- const status = options?.status ?? ffi_Status.ERR_UNKNOWN;
38
- if (!message && status !== ffi_Status.OK) {
39
- for (const [key, value] of Object.entries(ffi_Status)) if (value === status) {
40
- message = key;
41
- break;
42
- }
43
- }
44
- message ??= "ERR_UNKNOWN";
45
- super(message, options);
46
- this.name = "NilError";
47
- this.status = status;
48
- }
49
- static fromStatus(status) {
50
- return new NilError(null, { status });
51
- }
52
- };
53
- var HandleClosedError = class extends Error {
54
- constructor(options) {
55
- super("handle is closed", options);
56
- this.name = "HandleClosedError";
57
- }
58
- };
59
- var UnknownResponseError = class extends Error {
60
- constructor(response, options) {
61
- super(`got unknown response with id ${response.id}`, options);
62
- this.name = "UnknownResponseError";
63
- this.response = response;
64
- }
65
- };
66
- //#endregion
67
- //#region src/queue.ts
68
- //! Copyright (C) Call of Nil contributors
69
- //! SPDX-License-Identifier: AGPL-3.0-only
70
- var QueueEmitter = class extends EventEmitter {
71
- emit(event, ...args) {
72
- return super.emit(event, ...args);
73
- }
74
- on(event, listener) {
75
- return super.on(event, listener);
76
- }
77
- };
78
- var Queue = class Queue {
79
- static {
80
- this.POLL_INTERVAL = 16;
81
- }
82
- static {
83
- this.LIMIT_PER_TICK = 200;
84
- }
85
- constructor(handle, options) {
86
- this.disposed = false;
87
- this.emitter = new QueueEmitter();
88
- this.requestId = new RequestId();
89
- this.pendingRequests = /* @__PURE__ */ new Map();
90
- this.functions = handle.functions;
91
- this.errorHandler = options?.onError ?? console.error;
92
- this.emitter.on("error", this.errorHandler);
93
- this.emitter.on("response", this.onResponse.bind(this));
94
- this.timer = setTimeout(() => this.drain(), 0);
95
- }
96
- [Symbol.dispose]() {
97
- if (this.disposed) return;
98
- this.disposed = true;
99
- this.rejectAll(new HandleClosedError());
100
- this.emitter.removeAllListeners();
101
- }
102
- request(start) {
103
- if (this.disposed) return Promise.reject(new HandleClosedError());
104
- const requestId = this.requestId.next();
105
- return new Promise((resolve, reject) => {
106
- this.pendingRequests.set(requestId, {
107
- resolve,
108
- reject
109
- });
110
- try {
111
- start(requestId);
112
- } catch (err) {
113
- this.pendingRequests.delete(requestId);
114
- reject(err);
115
- }
116
- });
117
- }
118
- drain() {
119
- if (this.disposed) return;
120
- this.clearTimeout();
121
- try {
122
- for (let i = 0; i < Queue.LIMIT_PER_TICK; i++) if (!this.poll()) break;
123
- } catch (err) {
124
- this.emitter.emit("error", err);
125
- }
126
- this.timer = setTimeout(() => this.drain(), Queue.POLL_INTERVAL);
127
- }
128
- poll() {
129
- const out = allocBuffer();
130
- const status = this.functions.nil_ffi_poll(out);
131
- if (status === ffi_Status.ERR_NOTHING_TO_POLL) return false;
132
- if (status !== ffi_Status.OK) throw NilError.fromStatus(status);
133
- const ptr = readBufferPtr(out);
134
- if (ptr === 0n) throw new Error("failed to poll: unexpected null pointer");
135
- try {
136
- const json = ffi.toString(ptr) ?? "";
137
- const entry = JSON.parse(json);
138
- this.dispatch(entry);
139
- } finally {
140
- this.functions.nil_ffi_free_str(ptr);
141
- }
142
- return true;
143
- }
144
- dispatch(entry) {
145
- switch (entry.kind) {
146
- case "response": {
147
- const response = JSON.parse(entry.json_str);
148
- this.emitter.emit("response", response);
149
- break;
150
- }
151
- }
152
- }
153
- rejectAll(error) {
154
- this.clearTimeout();
155
- this.pendingRequests.values().forEach(({ reject }) => reject(error));
156
- this.pendingRequests.clear();
157
- }
158
- clearTimeout() {
159
- if (!isNil(this.timer)) {
160
- clearTimeout(this.timer);
161
- this.timer = null;
162
- }
163
- }
164
- onResponse(response) {
165
- const pending = this.pendingRequests.get(response.id);
166
- if (pending) {
167
- this.pendingRequests.delete(response.id);
168
- if (response.kind === "ok") pending.resolve(response.data);
169
- else {
170
- const { status, error } = response;
171
- pending.reject(new NilError(error, { status }));
172
- }
173
- } else this.emitter.emit("error", new UnknownResponseError(response));
174
- }
175
- };
176
- //#endregion
5
+ import { writeFile } from "node:fs/promises";
6
+ import { EventEmitter } from "node:events";
7
+ import { isNil } from "es-toolkit/predicate";
8
+ import { join, resolve } from "node:path";
177
9
  //#region src/def.ts
178
10
  //! Copyright (C) Call of Nil contributors
179
11
  //! SPDX-License-Identifier: AGPL-3.0-only
@@ -194,6 +26,22 @@ var definitions = {
194
26
  arguments: [ffi.types.UINT_32],
195
27
  return: ffi.types.VOID
196
28
  },
29
+ nil_is_host: {
30
+ arguments: [ffi.types.UINT_32],
31
+ return: ffi.types.VOID
32
+ },
33
+ nil_start_server: {
34
+ arguments: [ffi.types.UINT_32, ffi.types.POINTER],
35
+ return: ffi.types.VOID
36
+ },
37
+ nil_start_server_with_savedata: {
38
+ arguments: [ffi.types.UINT_32, ffi.types.POINTER],
39
+ return: ffi.types.VOID
40
+ },
41
+ nil_stop_server: {
42
+ arguments: [ffi.types.UINT_32],
43
+ return: ffi.types.VOID
44
+ },
197
45
  nil_client_version: {
198
46
  arguments: [ffi.types.UINT_32],
199
47
  return: ffi.types.VOID
@@ -234,6 +82,14 @@ var definitions = {
234
82
  arguments: [ffi.types.UINT_32],
235
83
  return: ffi.types.VOID
236
84
  },
85
+ nil_runtime_num_alive_tasks: {
86
+ arguments: [ffi.types.UINT_32],
87
+ return: ffi.types.VOID
88
+ },
89
+ nil_runtime_num_workers: {
90
+ arguments: [ffi.types.UINT_32],
91
+ return: ffi.types.VOID
92
+ },
237
93
  nil_add_academy_recruit_order: {
238
94
  arguments: [ffi.types.UINT_32, ffi.types.POINTER],
239
95
  return: ffi.types.VOID
@@ -724,24 +580,220 @@ var definitions = {
724
580
  }
725
581
  };
726
582
  //#endregion
583
+ //#region src/error.ts
584
+ //! Copyright (C) Call of Nil contributors
585
+ //! SPDX-License-Identifier: AGPL-3.0-only
586
+ var NilError = class NilError extends Error {
587
+ constructor(message, options) {
588
+ const status = options?.status ?? ffi_Status.ERR_UNKNOWN;
589
+ if (!message && status !== ffi_Status.OK) {
590
+ for (const [key, value] of Object.entries(ffi_Status)) if (value === status) {
591
+ message = key;
592
+ break;
593
+ }
594
+ }
595
+ message ??= "ERR_UNKNOWN";
596
+ super(message, options);
597
+ this.name = "NilError";
598
+ this.status = status;
599
+ }
600
+ static fromStatus(status) {
601
+ return new NilError(null, { status });
602
+ }
603
+ };
604
+ var HandleClosedError = class extends Error {
605
+ constructor(options) {
606
+ super("handle is closed", options);
607
+ this.name = "HandleClosedError";
608
+ }
609
+ };
610
+ var UnknownResponseError = class extends Error {
611
+ constructor(response, options) {
612
+ super(`got unknown response with id ${response.id}`, options);
613
+ this.name = "UnknownResponseError";
614
+ this.response = response;
615
+ }
616
+ };
617
+ //#endregion
618
+ //#region src/request.ts
619
+ //! Copyright (C) Call of Nil contributors
620
+ //! SPDX-License-Identifier: AGPL-3.0-only
621
+ var RequestId = class {
622
+ #current = 0;
623
+ next() {
624
+ if (this.#current >= 4294967295) this.#current = 0;
625
+ return ++this.#current;
626
+ }
627
+ };
628
+ //#endregion
629
+ //#region src/ptr.ts
630
+ //! Copyright (C) Call of Nil contributors
631
+ //! SPDX-License-Identifier: AGPL-3.0-only
632
+ function allocBuffer(size) {
633
+ return Buffer.alloc(size ?? pointerSize());
634
+ }
635
+ function readBufferPtr(buffer) {
636
+ if (pointerSize() === 8) return buffer.readBigUInt64LE();
637
+ else return BigInt(buffer.readUInt32LE());
638
+ }
639
+ function pointerSize() {
640
+ if (process.arch === "x64" || process.arch === "arm64") return 8;
641
+ else return 4;
642
+ }
643
+ //#endregion
644
+ //#region src/queue.ts
645
+ //! Copyright (C) Call of Nil contributors
646
+ //! SPDX-License-Identifier: AGPL-3.0-only
647
+ var QueueEmitter = class extends EventEmitter {
648
+ emit(event, ...args) {
649
+ return super.emit(event, ...args);
650
+ }
651
+ on(event, listener) {
652
+ return super.on(event, listener);
653
+ }
654
+ };
655
+ var Queue = class Queue {
656
+ static {
657
+ this.POLL_INTERVAL = 16;
658
+ }
659
+ static {
660
+ this.LIMIT_PER_TICK = 200;
661
+ }
662
+ constructor(handle, options) {
663
+ this.disposed = false;
664
+ this.emitter = new QueueEmitter();
665
+ this.requestId = new RequestId();
666
+ this.pendingRequests = /* @__PURE__ */ new Map();
667
+ this.functions = handle.functions;
668
+ this.errorHandler = options?.onError ?? console.error;
669
+ this.emitter.on("error", this.errorHandler);
670
+ this.emitter.on("response", this.onResponse.bind(this));
671
+ this.timer = setTimeout(() => this.drain(), 0);
672
+ }
673
+ [Symbol.dispose]() {
674
+ if (this.disposed) return;
675
+ this.disposed = true;
676
+ this.rejectAll(new HandleClosedError());
677
+ this.emitter.removeAllListeners();
678
+ }
679
+ request(start) {
680
+ if (this.disposed) return Promise.reject(new HandleClosedError());
681
+ const requestId = this.requestId.next();
682
+ return new Promise((resolve, reject) => {
683
+ this.pendingRequests.set(requestId, {
684
+ resolve,
685
+ reject
686
+ });
687
+ try {
688
+ start(requestId);
689
+ } catch (err) {
690
+ this.pendingRequests.delete(requestId);
691
+ reject(err);
692
+ }
693
+ });
694
+ }
695
+ drain() {
696
+ if (this.disposed) return;
697
+ this.clearTimeout();
698
+ try {
699
+ for (let i = 0; i < Queue.LIMIT_PER_TICK; i++) if (!this.poll()) break;
700
+ } catch (err) {
701
+ this.emitter.emit("error", err);
702
+ }
703
+ this.timer = setTimeout(() => this.drain(), Queue.POLL_INTERVAL);
704
+ }
705
+ poll() {
706
+ const out = allocBuffer();
707
+ const status = this.functions.nil_ffi_poll(out);
708
+ if (status === ffi_Status.ERR_NOTHING_TO_POLL) return false;
709
+ if (status !== ffi_Status.OK) throw NilError.fromStatus(status);
710
+ const ptr = readBufferPtr(out);
711
+ if (ptr === 0n) throw new Error("failed to poll: unexpected null pointer");
712
+ try {
713
+ const json = ffi.toString(ptr) ?? "";
714
+ const entry = JSON.parse(json);
715
+ this.dispatch(entry);
716
+ } finally {
717
+ this.functions.nil_ffi_free_str(ptr);
718
+ }
719
+ return true;
720
+ }
721
+ dispatch(entry) {
722
+ switch (entry.kind) {
723
+ case "response": {
724
+ const response = JSON.parse(entry.json_str);
725
+ this.emitter.emit("response", response);
726
+ break;
727
+ }
728
+ }
729
+ }
730
+ rejectAll(error) {
731
+ this.clearTimeout();
732
+ this.pendingRequests.values().forEach(({ reject }) => reject(error));
733
+ this.pendingRequests.clear();
734
+ }
735
+ clearTimeout() {
736
+ if (!isNil(this.timer)) {
737
+ clearTimeout(this.timer);
738
+ this.timer = null;
739
+ }
740
+ }
741
+ onResponse(response) {
742
+ const pending = this.pendingRequests.get(response.id);
743
+ if (pending) {
744
+ this.pendingRequests.delete(response.id);
745
+ if (response.kind === "ok") pending.resolve(response.data);
746
+ else {
747
+ const { status, error } = response;
748
+ pending.reject(new NilError(error, { status }));
749
+ }
750
+ } else this.emitter.emit("error", new UnknownResponseError(response));
751
+ }
752
+ };
753
+ //#endregion
754
+ //#region package.json
755
+ var version = "0.7.4";
756
+ //#endregion
757
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/decorate.js
758
+ function __decorate(decorators, target, key, desc) {
759
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
760
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
761
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
762
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
763
+ }
764
+ //#endregion
727
765
  //#region src/index.ts
728
766
  //! Copyright (C) Call of Nil contributors
729
767
  //! SPDX-License-Identifier: AGPL-3.0-only
730
- var VERSION = "0.7.2";
768
+ var VERSION = version;
731
769
  var USER_AGENT = `nil-ffi-node/${VERSION}`;
732
770
  var Nil = class Nil {
733
- constructor(dll) {
771
+ constructor(dll, options) {
734
772
  this.disposed = false;
735
773
  if (!dll.endsWith(ffi.suffix)) dll = `${dll}.${ffi.suffix}`;
774
+ this.path = resolve(dll);
736
775
  this.handle = ffi.dlopen(dll, definitions);
737
776
  this.functions = this.handle.functions;
738
- this.queue = new Queue(this.handle);
777
+ this.queue = new Queue(this.handle, options);
739
778
  }
740
- static async init(dll) {
741
- const nil = new Nil(dll);
779
+ static async init(dll, options) {
780
+ const nil = new Nil(dll, options);
742
781
  await nil.setUserAgent(USER_AGENT);
743
782
  return nil;
744
783
  }
784
+ static async initLatest(outDir, options) {
785
+ const dll = await this.downloadLatest(outDir);
786
+ return this.init(dll, options);
787
+ }
788
+ static async downloadLatest(outDir) {
789
+ const file = `libnil.${ffi.suffix}`;
790
+ const response = await fetch(`https://tsukilabs.dev.br/${file}`);
791
+ if (!response.ok) throw new Error(`failed to download ${file}: ${response.status} ${response.statusText}`);
792
+ const bytes = await response.bytes();
793
+ const path = join(outDir ?? cwd(), file);
794
+ await writeFile(path, bytes);
795
+ return resolve(path);
796
+ }
745
797
  [Symbol.dispose]() {
746
798
  this.close();
747
799
  }
@@ -752,58 +804,190 @@ var Nil = class Nil {
752
804
  this.functions.nil_ffi_shutdown();
753
805
  this.handle[Symbol.dispose]();
754
806
  }
807
+ isClosed() {
808
+ return this.disposed;
809
+ }
810
+ async authorize(req) {
811
+ return this.queue.request((requestId) => {
812
+ this.functions.nil_authorize(requestId, JSON.stringify(req));
813
+ });
814
+ }
755
815
  async getClientVersion() {
756
- this.throwIfClosed();
757
816
  return this.queue.request((requestId) => {
758
817
  this.functions.nil_client_version(requestId);
759
818
  });
760
819
  }
761
820
  async getFfiVersion() {
762
- this.throwIfClosed();
763
821
  return this.queue.request((requestId) => {
764
822
  this.functions.nil_ffi_version(requestId);
765
823
  });
766
824
  }
825
+ async getPlayer(req) {
826
+ return this.queue.request((requestId) => {
827
+ this.functions.nil_get_player(requestId, JSON.stringify(req));
828
+ });
829
+ }
830
+ async getPlayerIds(req) {
831
+ return this.queue.request((requestId) => {
832
+ this.functions.nil_get_player_ids(requestId, JSON.stringify(req));
833
+ });
834
+ }
835
+ async getPlayerStatus(req) {
836
+ return this.queue.request((requestId) => {
837
+ this.functions.nil_get_player_status(requestId, JSON.stringify(req));
838
+ });
839
+ }
767
840
  async getRemoteWorldLimit() {
768
- this.throwIfClosed();
769
841
  return this.queue.request((requestId) => {
770
842
  this.functions.nil_get_remote_world_limit(requestId);
771
843
  });
772
844
  }
773
845
  async getRemoteWorldLimitPerUser() {
774
- this.throwIfClosed();
775
846
  return this.queue.request((requestId) => {
776
847
  this.functions.nil_get_remote_world_limit_per_user(requestId);
777
848
  });
778
849
  }
779
850
  async getRemoteWorlds() {
780
- this.throwIfClosed();
781
851
  return this.queue.request((requestId) => {
782
852
  this.functions.nil_get_remote_worlds(requestId);
783
853
  });
784
854
  }
855
+ async getRuntimeNumAliveTasks() {
856
+ return this.queue.request((requestId) => {
857
+ this.functions.nil_runtime_num_alive_tasks(requestId);
858
+ });
859
+ }
860
+ async getRuntimeNumWorkers() {
861
+ return this.queue.request((requestId) => {
862
+ this.functions.nil_runtime_num_workers(requestId);
863
+ });
864
+ }
865
+ async getServerAddr() {
866
+ return this.queue.request((requestId) => {
867
+ this.functions.nil_server_addr(requestId);
868
+ });
869
+ }
870
+ async getServerKind() {
871
+ return this.queue.request((requestId) => {
872
+ this.functions.nil_get_server_kind(requestId);
873
+ });
874
+ }
785
875
  async getUserAgent() {
786
- this.throwIfClosed();
787
876
  return this.queue.request((requestId) => {
788
877
  this.functions.nil_user_agent(requestId);
789
878
  });
790
879
  }
791
- async getWorld() {
792
- this.throwIfClosed();
880
+ async getWorldId() {
793
881
  return this.queue.request((requestId) => {
794
882
  this.functions.nil_world(requestId);
795
883
  });
796
884
  }
885
+ async isHost() {
886
+ return this.queue.request((requestId) => {
887
+ this.functions.nil_is_host(requestId);
888
+ });
889
+ }
890
+ async isLocal() {
891
+ return this.queue.request((requestId) => {
892
+ this.functions.nil_is_local(requestId);
893
+ });
894
+ }
895
+ async isReady() {
896
+ return this.queue.request((requestId) => {
897
+ this.functions.nil_is_ready(requestId);
898
+ });
899
+ }
900
+ async isRemote() {
901
+ return this.queue.request((requestId) => {
902
+ this.functions.nil_is_remote(requestId);
903
+ });
904
+ }
905
+ async playerExists(req) {
906
+ return this.queue.request((requestId) => {
907
+ this.functions.nil_player_exists(requestId, JSON.stringify(req));
908
+ });
909
+ }
910
+ async setPlayerStatus(req) {
911
+ return this.queue.request((requestId) => {
912
+ this.functions.nil_set_player_status(requestId, JSON.stringify(req));
913
+ });
914
+ }
797
915
  async setUserAgent(userAgent) {
798
- this.throwIfClosed();
799
- await this.queue.request((requestId) => {
800
- const arg1 = JSON.stringify(userAgent);
801
- this.functions.nil_set_user_agent(requestId, arg1);
916
+ return this.queue.request((requestId) => {
917
+ this.functions.nil_set_user_agent(requestId, JSON.stringify(userAgent));
918
+ });
919
+ }
920
+ async spawnPlayer(req) {
921
+ return this.queue.request((requestId) => {
922
+ this.functions.nil_spawn_player(requestId, JSON.stringify(req));
802
923
  });
803
924
  }
804
- throwIfClosed() {
805
- if (this.disposed) throw new HandleClosedError();
925
+ async startServer(options) {
926
+ return this.queue.request((requestId) => {
927
+ this.functions.nil_start_server(requestId, JSON.stringify(options));
928
+ });
929
+ }
930
+ async startServerWithSavedata(path) {
931
+ return this.queue.request((requestId) => {
932
+ this.functions.nil_start_server_with_savedata(requestId, JSON.stringify(path));
933
+ });
934
+ }
935
+ async stopClient() {
936
+ return this.queue.request((requestId) => {
937
+ this.functions.nil_stop_client(requestId);
938
+ });
939
+ }
940
+ async stopServer() {
941
+ return this.queue.request((requestId) => {
942
+ this.functions.nil_stop_server(requestId);
943
+ });
944
+ }
945
+ async updateClient(options) {
946
+ return this.queue.request((requestId) => {
947
+ this.functions.nil_update_client(requestId, JSON.stringify(options));
948
+ });
949
+ }
950
+ async validateToken(req) {
951
+ return this.queue.request((requestId) => {
952
+ this.functions.nil_validate_token(requestId, JSON.stringify(req));
953
+ });
806
954
  }
807
955
  };
956
+ __decorate([ThrowIfClosed], Nil.prototype, "authorize", null);
957
+ __decorate([ThrowIfClosed], Nil.prototype, "getClientVersion", null);
958
+ __decorate([ThrowIfClosed], Nil.prototype, "getFfiVersion", null);
959
+ __decorate([ThrowIfClosed], Nil.prototype, "getPlayer", null);
960
+ __decorate([ThrowIfClosed], Nil.prototype, "getPlayerIds", null);
961
+ __decorate([ThrowIfClosed], Nil.prototype, "getPlayerStatus", null);
962
+ __decorate([ThrowIfClosed], Nil.prototype, "getRemoteWorldLimit", null);
963
+ __decorate([ThrowIfClosed], Nil.prototype, "getRemoteWorldLimitPerUser", null);
964
+ __decorate([ThrowIfClosed], Nil.prototype, "getRemoteWorlds", null);
965
+ __decorate([ThrowIfClosed], Nil.prototype, "getRuntimeNumAliveTasks", null);
966
+ __decorate([ThrowIfClosed], Nil.prototype, "getRuntimeNumWorkers", null);
967
+ __decorate([ThrowIfClosed], Nil.prototype, "getServerAddr", null);
968
+ __decorate([ThrowIfClosed], Nil.prototype, "getServerKind", null);
969
+ __decorate([ThrowIfClosed], Nil.prototype, "getUserAgent", null);
970
+ __decorate([ThrowIfClosed], Nil.prototype, "getWorldId", null);
971
+ __decorate([ThrowIfClosed], Nil.prototype, "isHost", null);
972
+ __decorate([ThrowIfClosed], Nil.prototype, "isLocal", null);
973
+ __decorate([ThrowIfClosed], Nil.prototype, "isReady", null);
974
+ __decorate([ThrowIfClosed], Nil.prototype, "isRemote", null);
975
+ __decorate([ThrowIfClosed], Nil.prototype, "playerExists", null);
976
+ __decorate([ThrowIfClosed], Nil.prototype, "setPlayerStatus", null);
977
+ __decorate([ThrowIfClosed], Nil.prototype, "setUserAgent", null);
978
+ __decorate([ThrowIfClosed], Nil.prototype, "spawnPlayer", null);
979
+ __decorate([ThrowIfClosed], Nil.prototype, "startServer", null);
980
+ __decorate([ThrowIfClosed], Nil.prototype, "startServerWithSavedata", null);
981
+ __decorate([ThrowIfClosed], Nil.prototype, "stopClient", null);
982
+ __decorate([ThrowIfClosed], Nil.prototype, "stopServer", null);
983
+ __decorate([ThrowIfClosed], Nil.prototype, "updateClient", null);
984
+ __decorate([ThrowIfClosed], Nil.prototype, "validateToken", null);
985
+ function ThrowIfClosed(_target, _key, descriptor) {
986
+ const method = descriptor.value;
987
+ descriptor.value = function(...args) {
988
+ if (this.isClosed()) throw new HandleClosedError();
989
+ return Reflect.apply(method, this, args);
990
+ };
991
+ }
808
992
  //#endregion
809
993
  export { HandleClosedError, Nil, NilError, USER_AGENT, UnknownResponseError, VERSION, definitions };
package/dist/queue.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Handle } from '.';
2
- import { Option } from '@tb-dev/utils';
2
+ import { nil, Option } from '@tb-dev/utils';
3
3
  import { ffi_RequestId } from '@tsukilabs/nil-bindings';
4
4
  export declare class Queue implements Disposable {
5
5
  private static readonly POLL_INTERVAL;
@@ -13,7 +13,7 @@ export declare class Queue implements Disposable {
13
13
  private readonly errorHandler;
14
14
  constructor(handle: Handle, options?: QueueOptions);
15
15
  [Symbol.dispose](): void;
16
- request<T = unknown>(start: RequestFn): Promise<T>;
16
+ request<T = nil>(start: RequestFn): Promise<T>;
17
17
  private drain;
18
18
  private poll;
19
19
  private dispatch;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsukilabs/nil-ffi",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@11.17.0",
6
6
  "license": "AGPL-3.0-only",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@tb-dev/utils": "^8.1.1",
32
- "@tsukilabs/nil-bindings": "workspace:*",
32
+ "@tsukilabs/nil-bindings": "^0.7.3",
33
33
  "es-toolkit": "^1.50.0"
34
34
  },
35
35
  "files": ["dist"],