@s2script/sdk 0.31.0 → 0.32.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/entity.d.ts CHANGED
@@ -88,6 +88,25 @@ export declare class EntityRef {
88
88
  * at `finalOff` into a number[]. All in-core (raw pointers never cross); null if the root is stale or any hop
89
89
  * is null. */
90
90
  readFloatsChain(ptrOffs: number[], finalOff: number, count: number): number[] | null;
91
+ /**
92
+ * Zero-allocation bulk read for per-tick hot paths: one liveness check, then every field `plan`
93
+ * names, written as numbers into your preallocated `out` starting at `outIndex` (default 0).
94
+ *
95
+ * `plan` is a flat run of entries `[hops, hop0..hopN-1, finalOff, kind, count]`: follow `hops`
96
+ * (0..8) pointer offsets, then read `count` (1..16) contiguous {@link GatherKind} elements at
97
+ * `finalOff`. An entry whose chain hits a null pointer writes `NaN` into its slots; the rest of
98
+ * the plan still runs. Build the plan once and reuse both arrays every tick.
99
+ *
100
+ * Returns the slot count written, `-1` when the ref is stale, or `-2` for a malformed plan or an
101
+ * `out` too short for the whole plan (nothing is written in either failure case).
102
+ * @example
103
+ * import { GatherKind } from "@s2script/sdk/entity";
104
+ * // two floats at +0x10, then one u8 behind the pointer at +0x30
105
+ * const plan = new Int32Array([0, 0x10, GatherKind.Float32, 2, 1, 0x30, 0x8, GatherKind.UInt8, 1]);
106
+ * const out = new Float64Array(3);
107
+ * if (ref.gather(plan, out) === 3) console.log(out[0], out[1], out[2]);
108
+ */
109
+ gather(plan: Int32Array, out: Float64Array, outIndex?: number): number;
91
110
  /** The `Vector` at `offset`, or null if the ref is stale. */
92
111
  readVector(offset: number): Vector | null;
93
112
  /** The `QAngle` at `offset`, or null if the ref is stale. */
@@ -212,6 +231,19 @@ export declare class EntityRef {
212
231
  acceptInput(input: string, value?: string, activator?: EntityRef, caller?: EntityRef, delay?: number): boolean;
213
232
  }
214
233
 
234
+ /** Element kinds for {@link EntityRef.gather} plans — the scalar kinds a `Float64Array` holds exactly. */
235
+ export declare const GatherKind: {
236
+ readonly Int32: number;
237
+ readonly Float32: number;
238
+ readonly Bool: number;
239
+ readonly Int8: number;
240
+ readonly Int16: number;
241
+ readonly UInt8: number;
242
+ readonly UInt16: number;
243
+ readonly UInt32: number;
244
+ readonly Float64: number;
245
+ };
246
+
215
247
  /** Keyvalues for a CEntityKeyValues-configured spawn. Inference: string -> SetString,
216
248
  * boolean -> SetBool, integer (int32) -> SetInt, other finite number -> SetFloat.
217
249
  * Keys are case-insensitive (hashed via MurmurHash2LowerCase, the engine's own keying). */
package/files.d.ts ADDED
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @s2script/files — sandboxed, off-thread file IO. Reads, writes (optionally gzip-compressed),
3
+ * lists and removes run on the shared async runtime's worker threads; the game thread only copies
4
+ * the payload and later receives the result on a frame drain. NO runtime code (injected at load).
5
+ *
6
+ * Every path is relative to this plugin's own root (`<data dir>/files/<plugin id>/`), `/`-separated,
7
+ * with segments of `[A-Za-z0-9._-]` (no `.`/`..`, at most 8 deep, 256 bytes). Anything else rejects
8
+ * with an `InvalidPath` error before any IO. One payload is capped by the async policy's
9
+ * `input_item_bytes` (8 MiB by default, measured after decompression) — see docs/ASYNC_LIMITS.md.
10
+ */
11
+
12
+ /** Options for {@link Files.read} / {@link Files.readText}. */
13
+ export interface FileReadOptions {
14
+ /** Decompress a gzip file (written with `{ gzip: true }`) off-thread. Default false. */
15
+ gzip?: boolean;
16
+ }
17
+
18
+ /** Options for {@link Files.write}. */
19
+ export interface FileWriteOptions {
20
+ /** Compress with gzip off-thread before writing. Default false. Cannot combine with `append`. */
21
+ gzip?: boolean;
22
+ /**
23
+ * Append instead of replace. Default false: a replacing write is atomic (temp file + rename), so
24
+ * a crash or a concurrent read never observes a torn file. Appends are not atomic.
25
+ */
26
+ append?: boolean;
27
+ }
28
+
29
+ /**
30
+ * Off-thread file IO in this plugin's sandbox. Promises reject with `AsyncQueueFull`,
31
+ * `AsyncPayloadTooLarge`, `AsyncCancelled` (the plugin unloaded first) or a descriptive IO error.
32
+ * @example
33
+ * import { Files } from "@s2script/sdk/files";
34
+ * // persist a binary blob compressed, then read it back — neither step blocks the game thread
35
+ * await Files.write("replays/surf_utopia/wr.bin", frames, { gzip: true });
36
+ * const back = await Files.read("replays/surf_utopia/wr.bin", { gzip: true });
37
+ * if (back) console.log(`replay is ${back.length} bytes`);
38
+ */
39
+ export declare const Files: {
40
+ /** Read a file as bytes (a fresh `Uint8Array`). Resolves `null` when the file does not exist. */
41
+ read(path: string, opts?: FileReadOptions): Promise<Uint8Array | null>;
42
+ /** Read a file as UTF-8 text (invalid sequences become U+FFFD). Resolves `null` when absent. */
43
+ readText(path: string, opts?: FileReadOptions): Promise<string | null>;
44
+ /**
45
+ * Write `data` (bytes, or a string as UTF-8), creating parent directories. The payload is copied
46
+ * synchronously, so the caller may reuse its buffer as soon as this returns.
47
+ */
48
+ write(path: string, data: Uint8Array | string, opts?: FileWriteOptions): Promise<void>;
49
+ /** Delete a file. Resolves `true` if it existed. */
50
+ remove(path: string): Promise<boolean>;
51
+ /**
52
+ * The sorted entry names in a directory (default: the plugin root). Subdirectories end in `/`.
53
+ * A missing directory resolves `[]`.
54
+ */
55
+ list(dir?: string): Promise<string[]>;
56
+ };
package/index.d.ts CHANGED
@@ -24,6 +24,7 @@ export * from "./damage";
24
24
  export * from "./db";
25
25
  export * from "./entity";
26
26
  export * from "./events";
27
+ export * from "./files";
27
28
  export * from "./http";
28
29
  export * from "./interfaces";
29
30
  export * from "./math";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@s2script/sdk",
3
- "version": "0.31.0",
3
+ "version": "0.32.0",
4
4
  "license": "MIT OR Apache-2.0",
5
5
  "description": "s2script SDK — the builtin capability types (imported as @s2script/sdk/entity, …) plus the `s2s` CLI for building Source 2 / CS2 plugins.",
6
6
  "type": "module",
@@ -80,6 +80,9 @@
80
80
  "./http": {
81
81
  "types": "./http.d.ts"
82
82
  },
83
+ "./files": {
84
+ "types": "./files.d.ts"
85
+ },
83
86
  "./interfaces": {
84
87
  "types": "./interfaces.d.ts"
85
88
  },
package/server.d.ts CHANGED
@@ -63,4 +63,15 @@ export declare const Server: {
63
63
  readonly mapName: string;
64
64
  /** The current map time in seconds (`GetGlobals()->curtime`). `0` if unavailable. */
65
65
  readonly gameTime: number;
66
+ /**
67
+ * The integer simulation tick (`GetGlobals()->tickcount`). Monotonic within a map and frozen
68
+ * while the game is paused — count ticks for anything timer-grade instead of differencing the
69
+ * float {@link Server.gameTime}. `0` if unavailable.
70
+ */
71
+ readonly tickCount: number;
72
+ /**
73
+ * Seconds per simulation tick, from the game's own server config (`0.015625` on a 64-tick
74
+ * server). Fixed for the server's lifetime. `0` only when the engine cannot report it.
75
+ */
76
+ readonly tickInterval: number;
66
77
  };