@s2script/sdk 0.20.0 → 0.21.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/commands.d.ts +8 -3
- package/entity.d.ts +34 -0
- package/package.json +1 -1
- package/phrases.d.ts +57 -0
- package/plugin.d.ts +22 -0
- package/sound.d.ts +14 -0
- package/translations.d.ts +39 -9
package/commands.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** @s2script/commands — register server commands. NO runtime code (injected at load). */
|
|
2
|
+
import type { PhraseKey } from "./phrases";
|
|
2
3
|
|
|
3
4
|
import type { HookResultValue } from "./events";
|
|
4
5
|
|
|
@@ -72,9 +73,13 @@ export interface CommandInvocation {
|
|
|
72
73
|
* is printed immediately. The server console (`callerSlot` `-1`) prints to the server console.
|
|
73
74
|
*/
|
|
74
75
|
replyToConsole(message: string): void;
|
|
75
|
-
/**
|
|
76
|
-
* `@s2script/translations` — degrades to the raw `key` if it isn't loaded.
|
|
77
|
-
|
|
76
|
+
/** Reply to the caller, translated for THEIR language (SM's `%t` on the reply path). Soft-deps
|
|
77
|
+
* `@s2script/translations` — degrades to the raw `key` if it isn't loaded.
|
|
78
|
+
*
|
|
79
|
+
* `key` is checked against this plugin's phrase file plus the shared one (see
|
|
80
|
+
* `@s2script/sdk/phrases`); it widens to `string` in a plugin that has no phrase file, so this is
|
|
81
|
+
* never in the way. */
|
|
82
|
+
replyT(key: PhraseKey, ...args: (string | number)[]): void;
|
|
78
83
|
}
|
|
79
84
|
/** A parsed chat trigger: which command + args, and whether it was the silent (`/`) trigger. */
|
|
80
85
|
export interface ChatTrigger {
|
package/entity.d.ts
CHANGED
|
@@ -158,6 +158,40 @@ export declare class EntityRef {
|
|
|
158
158
|
* `trigger_multiple` needs a model to build the physics volume that fires touch. Returns false
|
|
159
159
|
* if the op is unavailable or the ref is stale. */
|
|
160
160
|
setModel(name: string): boolean;
|
|
161
|
+
/** Set this entity's gravity multiplier (`CBaseEntity::SetGravityScale`). 1 is normal, 0 is
|
|
162
|
+
* weightless.
|
|
163
|
+
*
|
|
164
|
+
* Use this rather than writing `m_flGravityScale`: the engine setter early-returns when the value
|
|
165
|
+
* is unchanged and maintains a second field (`m_flActualGravityScale`), so a raw field write
|
|
166
|
+
* appears to succeed and does nothing. Returns false if the op is unavailable, the ref is stale,
|
|
167
|
+
* or `scale` is not finite. */
|
|
168
|
+
setGravityScale(scale: number): boolean;
|
|
169
|
+
/** Add to this entity's velocity, physics-aware (`CBaseEntity::ApplyAbsVelocityImpulse`) — for
|
|
170
|
+
* knockback, boosts, explosions.
|
|
171
|
+
*
|
|
172
|
+
* Additive, unlike `teleport(null, null, velocity)` which sets velocity absolutely; and unlike a
|
|
173
|
+
* direct `m_vecAbsVelocity` write, which skips the partition/physics update. `impulse` is an
|
|
174
|
+
* [x,y,z] triple. A zero impulse is a legal no-op. Returns false if the op is unavailable, the ref
|
|
175
|
+
* is stale, or any component is not finite. */
|
|
176
|
+
applyAbsVelocityImpulse(impulse: number[]): boolean;
|
|
177
|
+
/** Stop a sound playing on this entity (`CBaseEntity::StopSound`). `Sound.stop(name, { entity })`
|
|
178
|
+
* in `@s2script/sdk/sound` is the same call spelled next to `Sound.emit`, and
|
|
179
|
+
* `pawn.stopSound(name)` in `@s2script/cs2` is the pawn-shaped one. Returns false if the op is
|
|
180
|
+
* unavailable or the ref is stale. */
|
|
181
|
+
stopSound(name: string): boolean;
|
|
182
|
+
/** Set a model body group by name (`CBaseModelEntity::SetBodyGroupByName`).
|
|
183
|
+
*
|
|
184
|
+
* There is no schema equivalent — `m_bodyGroupChoices` is a `CUtlOrderedMap`, not a writable
|
|
185
|
+
* scalar. `group` is 32-bit engine-side. Returns false if the op is unavailable, the ref is stale,
|
|
186
|
+
* or `group` is out of 32-bit range. */
|
|
187
|
+
setBodyGroupByName(name: string, group: number): boolean;
|
|
188
|
+
/** Set this entity's model scale (`CBaseModelEntity::SetModelScale`).
|
|
189
|
+
*
|
|
190
|
+
* The argument shape is confirmed against the pinned build; the function's NAME is a catalogue
|
|
191
|
+
* attribution its body does not itself prove, so verify the effect before relying on this in a
|
|
192
|
+
* shipped plugin — see the gamedata comment. Calling it is safe either way. Returns false if the
|
|
193
|
+
* op is unavailable, the ref is stale, or `scale` is not finite. */
|
|
194
|
+
setModelScale(scale: number): boolean;
|
|
161
195
|
/** Read a CUtlVector<CHandle> at (ptrOffs chain -> vectorOff) as live liveness-gated EntityRefs.
|
|
162
196
|
* Follows the pointer chain, reads count@+0 / elements@+8, caps at maxCount. [] if stale/unresolved. */
|
|
163
197
|
readHandleVector(ptrOffs: number[], vectorOff: number, maxCount?: number): EntityRef[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@s2script/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.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",
|
package/phrases.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @s2script/phrases — the phrase keys your plugin is allowed to use.
|
|
3
|
+
*
|
|
4
|
+
* **You do not import this module.** It exists so that `cmd.replyT(...)` and
|
|
5
|
+
* `Translations.translate(...)` know which keys are valid in your plugin, and the build fills it in
|
|
6
|
+
* from the phrase files you load.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* export default plugin((ctx) => {
|
|
10
|
+
* ctx.translations.load("basecomm", "common");
|
|
11
|
+
*
|
|
12
|
+
* cmd.replyT("Usage Gag"); // ok — in translations/basecomm.phrases.json
|
|
13
|
+
* cmd.replyT("No matching players"); // ok — in translations/common.phrases.json
|
|
14
|
+
* cmd.replyT("Usage Gagg"); // compile error — no such key in either
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* ## Writing phrases
|
|
18
|
+
*
|
|
19
|
+
* Create `translations/<your-plugin>.phrases.json` — a flat key to English map. `{1}`, `{2}` … are
|
|
20
|
+
* positional slots filled by the trailing arguments; `{green}`, `{default}` … are colour tags
|
|
21
|
+
* expanded on output (see `@s2script/sdk/chat`). Keys are human-readable English on purpose: an
|
|
22
|
+
* unresolved key renders as the key itself, so it should still read as a sentence.
|
|
23
|
+
*
|
|
24
|
+
* ```json
|
|
25
|
+
* { "Gagged Player": "{green}[SM]{default} Gagged {1} player." }
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* A translator adds `translations/<code>/<your-plugin>.phrases.json` — no code change, no rebuild.
|
|
29
|
+
*
|
|
30
|
+
* ## How the checking works
|
|
31
|
+
*
|
|
32
|
+
* The build reads your `ctx.translations.load(...)` call and writes `src/phrases.generated.d.ts`,
|
|
33
|
+
* filling in {@link PhraseKeys} with the keys of exactly those files. Load a file and its keys
|
|
34
|
+
* become valid; don't, and they don't — so a forgotten `load` is a compile error rather than raw key
|
|
35
|
+
* text printed to a player at runtime. SourceMod enforces the same rule, but only when it happens.
|
|
36
|
+
*
|
|
37
|
+
* That file is derived and gitignored. Until it has been written — a brand-new plugin, say — keys
|
|
38
|
+
* fall back to plain `string` and go unchecked, so nothing is blocked on the build having run.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The set of valid phrase keys, filled in per plugin by its generated declaration.
|
|
43
|
+
*
|
|
44
|
+
* Empty here deliberately. Each plugin's `src/phrases.generated.d.ts` augments this interface, and
|
|
45
|
+
* interface merging turns that into the exact union {@link PhraseKey} resolves to. Never add keys
|
|
46
|
+
* here by hand — this is the shared module, and a key added here would apply to every plugin.
|
|
47
|
+
*/
|
|
48
|
+
export interface PhraseKeys {}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Every phrase key valid in this plugin — the union of the keys in every file it loads.
|
|
52
|
+
*
|
|
53
|
+
* Falls back to `string` when nothing has augmented {@link PhraseKeys}, so a plugin that loads no
|
|
54
|
+
* phrases (or whose generated declaration has not been written yet) compiles unchecked rather than
|
|
55
|
+
* failing to compile at all.
|
|
56
|
+
*/
|
|
57
|
+
export type PhraseKey = [keyof PhraseKeys] extends [never] ? string : Extract<keyof PhraseKeys, string>;
|
package/plugin.d.ts
CHANGED
|
@@ -114,6 +114,26 @@ export interface CtxCommands {
|
|
|
114
114
|
handler: (slot: number, argString: string) => HookResultValue | void,
|
|
115
115
|
): void;
|
|
116
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* The phrase files this plugin uses ({@link PluginContext.translations}).
|
|
119
|
+
*
|
|
120
|
+
* Nothing is loaded automatically — a plugin declares what it needs, the same rule SourceMod's
|
|
121
|
+
* `LoadTranslations` enforces. The build reads this call to work out which keys `cmd.replyT` and
|
|
122
|
+
* `Translations.translate` will accept, so a key from a file you did not load is a compile error.
|
|
123
|
+
*/
|
|
124
|
+
export interface CtxTranslations {
|
|
125
|
+
/**
|
|
126
|
+
* Load `translations/<name>.phrases.json` for each name, in the order given.
|
|
127
|
+
*
|
|
128
|
+
* Order is significant: `translate` takes the first hit within each of its two passes (the
|
|
129
|
+
* client's language, then English), so list your own set before any shared one if you want to be
|
|
130
|
+
* able to override a shared phrase.
|
|
131
|
+
*
|
|
132
|
+
* @example ctx.translations.load("basecomm", "common");
|
|
133
|
+
*/
|
|
134
|
+
load(...names: string[]): void;
|
|
135
|
+
}
|
|
136
|
+
|
|
117
137
|
/** Config live-reload subscription on this plugin's load-scope ({@link PluginContext.config}). */
|
|
118
138
|
export interface CtxConfig {
|
|
119
139
|
/** Fires when the plugin's config file is re-materialized on disk; re-read values inside. */
|
|
@@ -175,6 +195,8 @@ export interface PluginContext {
|
|
|
175
195
|
readonly commands: CtxCommands;
|
|
176
196
|
/** Config live-reload subscription ({@link CtxConfig}). */
|
|
177
197
|
readonly config: CtxConfig;
|
|
198
|
+
/** Phrase files this plugin uses ({@link CtxTranslations}). */
|
|
199
|
+
readonly translations: CtxTranslations;
|
|
178
200
|
/** TopMenu (adminmenu) contribution ({@link CtxTopMenu}). */
|
|
179
201
|
readonly topmenu: CtxTopMenu;
|
|
180
202
|
/** Publish this plugin's manifest-declared interface. Buffered; goes live at Active. */
|
package/sound.d.ts
CHANGED
|
@@ -52,4 +52,18 @@ export declare const Sound: {
|
|
|
52
52
|
* function / stale source entity / an empty `recipients` array). An all-bot-skipped recipient
|
|
53
53
|
* set still emits to nobody (a real engine call, may return a nonzero GUID). */
|
|
54
54
|
emit(name: string, opts?: SoundEmitOptions): number;
|
|
55
|
+
/**
|
|
56
|
+
* Stop a named SoundEvent playing on an entity — the counterpart to {@link Sound.emit}.
|
|
57
|
+
*
|
|
58
|
+
* **`opts.entity` is required**, unlike `emit`. The engine call behind this is an instance method
|
|
59
|
+
* on the entity, so there is no global/2D form to default to the way `emit` falls back to
|
|
60
|
+
* worldspawn. `recipients` and `volume` do not apply: the engine stops the sound for everyone
|
|
61
|
+
* hearing it.
|
|
62
|
+
*
|
|
63
|
+
* Equivalent to `entity.stopSound(name)`; this is the discoverable spelling next to `emit`.
|
|
64
|
+
* `pawn.stopSound(name)` in `@s2script/cs2` is the pawn-shaped one.
|
|
65
|
+
*
|
|
66
|
+
* Returns false when `opts.entity` is absent or stale, or the engine op is unavailable.
|
|
67
|
+
*/
|
|
68
|
+
stop(name: string, opts: { entity: EntityRef }): boolean;
|
|
55
69
|
};
|
package/translations.d.ts
CHANGED
|
@@ -1,20 +1,50 @@
|
|
|
1
1
|
/** @s2script/translations — SourceMod-style i18n (per-client language, phrase files, {1} formatting). */
|
|
2
|
+
import type { PhraseKey } from "./phrases";
|
|
2
3
|
|
|
3
4
|
/** A phrase set: key → template string, where `{1}`/`{2}`/… are positional substitution slots. */
|
|
4
5
|
export type Phrases = Record<string, string>;
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
|
-
* SourceMod-style translation registry
|
|
7
|
-
* `translations/<code>/<name>.phrases.json
|
|
8
|
+
* SourceMod-style translation registry. Phrases live in `translations/<name>.phrases.json`, shipped
|
|
9
|
+
* with the addon and edited by operators; `translations/<code>/<name>.phrases.json` overrides per
|
|
10
|
+
* language, added by a translator with no code change.
|
|
11
|
+
*
|
|
12
|
+
* A plugin declares the files it uses with {@link PluginContext.translations} — nothing is loaded
|
|
13
|
+
* for it automatically, the same rule SourceMod's `LoadTranslations` enforces:
|
|
14
|
+
*
|
|
8
15
|
* @example
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
16
|
+
* export default plugin((ctx) => {
|
|
17
|
+
* ctx.translations.load("basecomm", "common");
|
|
18
|
+
* ctx.commands.registerAdmin("sm_gag", ADMFLAG.CHAT, (cmd) => {
|
|
19
|
+
* cmd.replyT("Usage Gag"); // key-checked
|
|
20
|
+
* Chat.toSlot(p.slot, Translations.translate(p.slot, "Gagged Player", n));
|
|
21
|
+
* });
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* Keys are checked against the files that plugin loads — see `@s2script/sdk/phrases`.
|
|
12
25
|
*/
|
|
13
26
|
export declare const Translations: {
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Register a phrase set by name, populating it from `translations/<name>.phrases.json`.
|
|
29
|
+
*
|
|
30
|
+
* Prefer {@link PluginContext.translations}`.load(...)`, which is what the build reads to work out
|
|
31
|
+
* which keys your plugin may use. This is the lower-level form, for a name computed at runtime or
|
|
32
|
+
* a set with an in-code default — a `seed` here is the starting content, which the file overrides.
|
|
33
|
+
*
|
|
34
|
+
* Registration order is significant: `translate` takes the first hit within each of its two passes
|
|
35
|
+
* (the client's language, then English), so load your own set before any shared one if you want to
|
|
36
|
+
* override a shared phrase.
|
|
37
|
+
*/
|
|
38
|
+
load(name: string, seed?: Phrases): void;
|
|
39
|
+
/**
|
|
40
|
+
* Translate `key` for `slot`'s language (slot < 0 = the server default), substituting positional
|
|
41
|
+
* {1}/{2} args.
|
|
42
|
+
*
|
|
43
|
+
* `key` is checked against the phrase files this plugin loads; it widens to `string` in a plugin
|
|
44
|
+
* that loads none, so this is never in the way. A key found in no loaded set returns the key
|
|
45
|
+
* itself — which is what the checking exists to prevent reaching a player.
|
|
46
|
+
*/
|
|
47
|
+
translate(slot: number, key: PhraseKey, ...args: (string | number)[]): string;
|
|
18
48
|
/** Set the server/console default language code (default "" = root/English). */
|
|
19
49
|
setDefaultLanguage(code: string): void;
|
|
20
50
|
};
|