@s2script/sdk 0.25.1 → 0.27.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/README.md +69 -0
- package/bans.d.ts +5 -2
- package/clients.d.ts +11 -5
- package/contracts/README.md +4 -0
- package/cookies.d.ts +8 -7
- package/damage.d.ts +10 -6
- package/db.d.ts +1 -0
- package/dist/cli.js +3329 -1752
- package/http.d.ts +1 -0
- package/interfaces.d.ts +120 -0
- package/net.d.ts +4 -4
- package/package.json +1 -1
- package/plugin.d.ts +123 -16
- package/sdkhooks.d.ts +11 -6
- package/timers.d.ts +8 -5
- package/unsafe.d.ts +27 -0
- package/ws.d.ts +2 -1
package/README.md
CHANGED
|
@@ -36,6 +36,19 @@ export function OnClientPostAdminCheck(client: Client): void {
|
|
|
36
36
|
}
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
For an existing plugin with `s2script.gamedata` declarations, run
|
|
40
|
+
`npx @s2script/sdk migrate engine-functions [plugin-dir]`. The command analyzes the v1 declarations
|
|
41
|
+
and source references, reports ambiguities, and writes `gamedata/functions.jsonc` only when the
|
|
42
|
+
declared contract can be converted without loss. It refuses an existing destination unless you pass
|
|
43
|
+
`--force`. Its JSON report lists files actually changed and the package/source edits you must make
|
|
44
|
+
manually, including removal of the old `s2script.gamedata` field and authored engine permissions
|
|
45
|
+
when adopting the v2 file. A successful conversion does not verify that the v1 declaration listed
|
|
46
|
+
every native argument or that the resulting call works on the current game build. The command alone
|
|
47
|
+
does not provide the runtime compatibility facades for old source code. V1 entity hooks are refused
|
|
48
|
+
because their callbacks may receive a null receiver, which the current v2 receiver contract cannot
|
|
49
|
+
preserve. With `--force`, the report identifies the exact create-or-replace path; concurrent prior
|
|
50
|
+
existence cannot be established by the atomic rename.
|
|
51
|
+
|
|
39
52
|
This package is **types-only** — the engine injects the implementation at load time, and
|
|
40
53
|
`s2s build` marks `@s2script/*` external rather than bundling it. Capabilities are imported as
|
|
41
54
|
per-capability subpaths (`@s2script/sdk/entity`, `@s2script/sdk/timers`, `@s2script/sdk/clients`, …);
|
|
@@ -110,3 +123,59 @@ reference. Source and issues: [GitHub](https://github.com/s2script/s2script).
|
|
|
110
123
|
## License
|
|
111
124
|
|
|
112
125
|
MIT OR Apache-2.0
|
|
126
|
+
|
|
127
|
+
### Typed plugin interfaces
|
|
128
|
+
|
|
129
|
+
Opt in with `s2script.interfaceProtocol: 2`, export a self-contained `Contract` with `methods` and
|
|
130
|
+
`forwards: { EventName: Notification<Payload> }`, then use `publish(name, implementation)` and
|
|
131
|
+
`use(name)` without caller-selected generics. `s2s build` generates the name association and checks
|
|
132
|
+
wire schemas; `s2s add` obtains only a plugin dependency's types. Include the generated
|
|
133
|
+
`.s2script/interfaces.d.ts` in existing projects' tsconfig files. Protocol 2 needs host API 3.
|
|
134
|
+
|
|
135
|
+
CJS module evaluation runs before the host opens its load window. Register publications,
|
|
136
|
+
subscriptions, binding maps and optional watches inside `OnPluginStart`. Exported handler
|
|
137
|
+
functions and imports can remain at module top level.
|
|
138
|
+
|
|
139
|
+
Inline handlers infer their payload from the provider:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
import { use } from "@s2script/sdk/plugin";
|
|
143
|
+
export function OnPluginStart(): void {
|
|
144
|
+
use("@demo/racing").on("OnRunFinished", event => console.log(event.elapsedMs));
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Use an explicit binding map when a named local export has a different name from the provider
|
|
149
|
+
forward. The returned subscription disposes the whole map:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
import { bindForwards, command } from "@s2script/sdk";
|
|
153
|
+
export function OnRaceFinished(event: { elapsedMs: number }): void {
|
|
154
|
+
console.log(event.elapsedMs);
|
|
155
|
+
}
|
|
156
|
+
export function OnPluginStart(): void {
|
|
157
|
+
const racing = bindForwards("@demo/racing", { OnRunFinished: OnRaceFinished });
|
|
158
|
+
command.server("sm_disable_racing", () => racing.dispose());
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`bindForwards` requires a hard plugin dependency. Optional providers continue to attach through
|
|
163
|
+
`watchOptional`, where named local functions can be passed to the supplied `service.on`.
|
|
164
|
+
See [the complete migration guide](https://github.com/s2script/s2script/blob/main/docs/PLUGIN_INTEROP.md)
|
|
165
|
+
for supported types, copying, dispatch, and compatibility limits.
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
Use `Hook<Payload>` for synchronous decisions and `Transform<Payload, WritableKeys>` for
|
|
169
|
+
validated shallow patches. Producers call `dispatch`; notifications use `emit`. All crossings
|
|
170
|
+
copy supported wire values. Listeners must return synchronously, and invalid/throwing listeners
|
|
171
|
+
contribute Continue. Nested crossings stop at 32 active calls. Retained optional services throw
|
|
172
|
+
`InterfaceUnavailable` after detach; reacquire through `watchOptional` on each provider generation
|
|
173
|
+
and own resources in its scope. `tryUse` is a one-time lookup.
|
|
174
|
+
|
|
175
|
+
For an existing consumer, declare the provider under `s2script.pluginDependencies` or
|
|
176
|
+
`optionalPluginDependencies`, run `s2s add <provider>`, include `.s2script/interfaces.d.ts`, and
|
|
177
|
+
rebuild with `s2s build`. Acquisition needs only the verified declaration. Rebuild and deploy the
|
|
178
|
+
producer and consumers together for protocol 2; API 3 hosts still accept legacy API-2/protocol-1
|
|
179
|
+
archives, while old API-2 hosts reject new API-3 builds. See the
|
|
180
|
+
[acceptance workspace](https://github.com/s2script/s2script/tree/main/tools/interop-acceptance)
|
|
181
|
+
for executable examples and the separate live verification sequence.
|
package/bans.d.ts
CHANGED
|
@@ -38,9 +38,12 @@ export interface BanEntry {
|
|
|
38
38
|
* if (b && (b.until === 0 || b.until > Date.now() / 1000)) c.kickWithReason(b.reason);
|
|
39
39
|
*/
|
|
40
40
|
export declare const Bans: {
|
|
41
|
-
/** Add
|
|
41
|
+
/** Add/overwrite the host cache, then attempt to rewrite bans.json. Returns void;
|
|
42
|
+
* persistence failure is not acknowledged and does not roll back the cache.
|
|
43
|
+
* An immediate get() confirms cache visibility only, not a fresh or durable write.
|
|
44
|
+
* `minutes <= 0` = permanent. */
|
|
42
45
|
add(steamId: string, minutes: number, reason?: string): void;
|
|
43
|
-
/** Remove
|
|
46
|
+
/** Remove from cache and attempt persistence. Returns whether a cache key existed, not disk acknowledgement. */
|
|
44
47
|
remove(steamId: string): boolean;
|
|
45
48
|
/** Get a ban by SteamID64, or null if not banned. */
|
|
46
49
|
get(steamId: string): BanInfo | null;
|
package/clients.d.ts
CHANGED
|
@@ -3,11 +3,17 @@
|
|
|
3
3
|
* Resolved at runtime via globalThis.__s2pkg_clients. Import: import { Client, Clients } from "./clients";
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* A handle to one connection lifetime. Reusing a slot, even for the same SteamID, never revives it.
|
|
8
|
+
* Stale handles return "0" for steamId, "" for name/ip, -1 for userId/signonState,
|
|
9
|
+
* false for booleans; void actions do nothing and command actions return false.
|
|
10
|
+
* OnClientDisconnect receives a read-only identity snapshot during its synchronous callback;
|
|
11
|
+
* isValid() is already false. Capture identity before awaiting; afterward stale defaults apply.
|
|
12
|
+
*/
|
|
7
13
|
export declare class Client {
|
|
8
|
-
/** The client's 0-based engine slot (`CPlayerSlot`) —
|
|
14
|
+
/** The client's 0-based engine slot (`CPlayerSlot`) — not sufficient by itself to identify a connection. */
|
|
9
15
|
readonly slot: number;
|
|
10
|
-
/** True while
|
|
16
|
+
/** True while this exact connection occupies the slot. */
|
|
11
17
|
isValid(): boolean;
|
|
12
18
|
/** Decimal SteamID64; "0" for a bot or an unauthenticated client. */
|
|
13
19
|
readonly steamId: string;
|
|
@@ -15,9 +21,9 @@ export declare class Client {
|
|
|
15
21
|
readonly name: string;
|
|
16
22
|
/** Engine user-id; -1 if none. */
|
|
17
23
|
readonly userId: number;
|
|
18
|
-
/** Tracked signon state: 0 = none/disconnected, 2 = connected, 5 = spawned, 6 = full (in-game); -1
|
|
24
|
+
/** Tracked signon state: 0 = none/disconnected, 2 = connected, 5 = spawned, 6 = full (in-game); -1 for a stale handle. */
|
|
19
25
|
readonly signonState: number;
|
|
20
|
-
/** True for a fake client (bot) —
|
|
26
|
+
/** True for a fake client (bot) — false for stale handles. */
|
|
21
27
|
readonly isBot: boolean;
|
|
22
28
|
/** Disconnect this client. */
|
|
23
29
|
kick(reason?: string): void;
|
package/contracts/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Standard interface contracts
|
|
2
2
|
|
|
3
|
+
The [legacy-contracts example](../../../examples/legacy-contracts/README.md)
|
|
4
|
+
demonstrates these protocol 1 community interfaces, including asynchronous
|
|
5
|
+
workshop methods. It is a separate companion to the protocol 2 cookbook.
|
|
6
|
+
|
|
3
7
|
These are **type-only contracts for inter-plugin interfaces** — not SDK capability modules.
|
|
4
8
|
|
|
5
9
|
The framework deliberately ships **no implementation** for anything in here. Each contract describes
|
package/cookies.d.ts
CHANGED
|
@@ -41,15 +41,16 @@ export declare const Cookies: {
|
|
|
41
41
|
register(name: string, opts?: CookieOptions): Cookie;
|
|
42
42
|
/** Cache value for this client (a stored "" is a real value), else the cookie's default. Default for bots. */
|
|
43
43
|
get(client: Client, cookie: Cookie): string;
|
|
44
|
-
/**
|
|
45
|
-
|
|
44
|
+
/** Accept a cache change into the bounded host persistence outbox. Returns false for invalid/stale/bot
|
|
45
|
+
* clients or exhausted capacity, without changing the cache. True remains host-owned until DB ACK;
|
|
46
|
+
* it is not a durability acknowledgement. Check false and report, shed, or retry the change. */
|
|
47
|
+
set(client: Client, cookie: Cookie, value: string): boolean;
|
|
46
48
|
/** Has this client's cookies finished loading from the DB? */
|
|
47
49
|
areCached(client: Client): boolean;
|
|
48
50
|
/** Unix timestamp of the cookie's last write (set or DB load), or 0 if never set. 0 for bots. */
|
|
49
51
|
getTime(client: Client, cookie: Cookie): number;
|
|
50
|
-
/**
|
|
51
|
-
*
|
|
52
|
-
* clientprefs
|
|
53
|
-
|
|
54
|
-
setAuthId(steamId: string, cookie: Cookie, value: string): void;
|
|
52
|
+
/** Accept an online or offline SteamID cookie change under the same bounded admission contract as set.
|
|
53
|
+
* False leaves both cache and outbox unchanged (including empty/"0" identity). Accepted writes
|
|
54
|
+
* survive clientprefs reload and same-process core reinit, but not process exit or library destruction. */
|
|
55
|
+
setAuthId(steamId: string, cookie: Cookie, value: string): boolean;
|
|
55
56
|
};
|
package/damage.d.ts
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @s2script/damage — the
|
|
3
|
-
*
|
|
2
|
+
* @s2script/damage — the borrowed {@link DamageInfo} view of the current damage event.
|
|
3
|
+
* Type-only: the view is supplied by the selected game package (its damage function and damage-info
|
|
4
|
+
* layout are game facts; CS2 maps `CTakeDamageInfo`), through the engine-generic `SDKHook`.
|
|
4
5
|
*
|
|
5
6
|
* Subscribe with `SDKHook` (`SDKHookType.OnTakeDamage` / `OnTakeDamagePost`), not a global mux.
|
|
6
7
|
*/
|
|
7
8
|
import type { EntityRef } from "./entity";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
|
-
* A
|
|
11
|
-
* `OnTakeDamagePost` SDKHook)
|
|
11
|
+
* A borrowed view of the current damage event, valid only during the synchronous `OnTakeDamage` or
|
|
12
|
+
* `OnTakeDamagePost` SDKHook callback: reading or writing it afterwards (including after an `await`)
|
|
13
|
+
* throws "expired borrowed view". Returning `HookResult.Handled`/`Stop` from `OnTakeDamage` blocks the
|
|
14
|
+
* hit by setting damage to 0 after every handler ran; the engine's damage function still runs.
|
|
12
15
|
* @example
|
|
13
16
|
* import type { DamageInfo } from "@s2script/sdk";
|
|
14
17
|
* function onTakeDamage(info: DamageInfo) { info.damage = info.damage / 2; }
|
|
15
18
|
*/
|
|
16
19
|
export interface DamageInfo {
|
|
17
20
|
/**
|
|
18
|
-
* The damage amount (`m_flDamage`). On the pre-hook, assigning MODIFIES the
|
|
19
|
-
* 0 to block.
|
|
21
|
+
* The damage amount (`m_flDamage`). On the pre-hook, assigning MODIFIES the damage the engine
|
|
22
|
+
* applies (later handlers see it); set to 0 to block. A non-finite value is refused (the damage
|
|
23
|
+
* keeps its prior value). On `OnTakeDamagePost`, assignment is ignored (the original already ran).
|
|
20
24
|
*/
|
|
21
25
|
damage: number;
|
|
22
26
|
/** The damage-type bit flags (m_bitsDamageType). */
|
package/db.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** Async queries/execute reject with AsyncQueueFull or AsyncPayloadTooLarge before acceptance. Queries exceeding the configured row or retained-byte limit reject with DatabaseResultTooLarge. */
|
|
1
2
|
/** @s2script/db — engine-generic async SQLite database. NO runtime code (injected as __s2pkg_db). */
|
|
2
3
|
|
|
3
4
|
/** A value bindable as a SQL parameter or returned in a {@link Row}. */
|