@tsukilabs/nil-ffi 0.7.2 → 0.7.3

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