@amxts/core 0.2.4 → 0.3.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 +5 -5
- package/README.ru.md +5 -5
- package/as/amxts.d.ts +13 -3
- package/as/entities.ts +571 -501
- package/as/events.ts +3323 -557
- package/as/facade.ts +3079 -718
- package/as/fetch.ts +2 -2
- package/as/fs.ts +352 -59
- package/as/hlds.ts +121 -120
- package/as/hooks.ts +10585 -5177
- package/as/lib/check.ts +3 -2
- package/as/natives.ts +856 -1272
- package/as/promise.ts +37 -27
- package/as/vector.ts +94 -14
- package/includes/order.txt +17 -19
- package/node_modules/assemblyscript/std/assembly/index.d.ts +1 -1
- package/package.json +9 -6
- package/runtime/deps/assemblyscript/dist/asc.js +136 -42
- package/runtime/deps/assemblyscript/dist/assemblyscript.js +141 -141
- package/runtime/licenses/README.md +9 -7
- package/runtime/licenses/ReGameDLL-LICENSE +21 -0
- package/runtime/licenses/ReHLDS-LICENSE +21 -0
- package/runtime/licenses/zlib-LICENSE +22 -0
- package/runtime/natives.txt +618 -523
- package/runtime/patches/README.md +87 -1
- package/runtime/patches/assemblyscript-0.28.20-amxts.patch +4838 -416
- package/runtime/patches/wamr-2.4.5-amxts.patch +417 -5
- package/scripts/auto-imports.ts +1 -1
- package/scripts/build-identity.ts +102 -65
- package/scripts/build-wasm.ts +12 -12
- package/scripts/check.ts +4 -1
- package/scripts/client-messages.ts +73 -1
- package/scripts/compile-cache.ts +11 -8
- package/scripts/compile-pool.ts +6 -3
- package/scripts/compile-worker.ts +23 -23
- package/scripts/compile.ts +142 -19
- package/scripts/docs/as/amxts.ts +10 -4
- package/scripts/docs/as/facade.ts +1779 -275
- package/scripts/docs/as/fetch.ts +2 -2
- package/scripts/docs/as/fs.ts +190 -6
- package/scripts/docs/as/vector.ts +81 -0
- package/scripts/docs/entities.ts +12 -0
- package/scripts/docs/events.ts +49 -13
- package/scripts/docs/game.ts +6 -0
- package/scripts/docs/messages.ts +10 -1
- package/scripts/hlds-events.ts +11 -11
- package/scripts/includes.ts +3 -4
- package/scripts/leaf-natives.ts +84 -0
- package/scripts/player-fields.ts +1 -1
- package/scripts/plugin-natives.ts +1 -1
- package/scripts/prebuilt.ts +41 -10
- package/scripts/project.ts +2 -3
- package/scripts/reapi-events.ts +9 -9
- package/scripts/server-env.ts +145 -0
- package/scripts/shared-modules.ts +23 -7
- package/scripts/system.ts +1 -1
- package/scripts/tracked-fs.ts +11 -2
- package/scripts/typed-commands.ts +153 -15
- package/scripts/upgrade-calls.ts +225 -0
- package/scripts/upgrade-names.ts +1 -4
- package/scripts/upgrade.ts +26 -11
- package/src/cli-api.mjs +3 -2
- package/src/system.mjs +21 -11
- package/src/testing/compile.ts +31 -8
- package/src/testing/coroutines.ts +0 -10
- package/src/testing/memory.ts +89 -2
- package/src/testing/natives.ts +67 -30
- package/src/testing/server.ts +1094 -155
- package/src/testing/tables.ts +23 -6
- package/src/typecheck.mjs +110 -0
- package/runtime/licenses/Bun-LICENSE.md +0 -84
package/scripts/docs/as/fetch.ts
CHANGED
|
@@ -543,7 +543,7 @@ export default {
|
|
|
543
543
|
|
|
544
544
|
const { data, error } = await useFetch<Weather>("https://example.com/weather", { query: { city: "Paris" } });
|
|
545
545
|
if (error) return console.error(error.message);
|
|
546
|
-
print(
|
|
546
|
+
player.print(\`\${data!.temperature} °C\`);
|
|
547
547
|
\`\`\`
|
|
548
548
|
|
|
549
549
|
A body that is an object goes as JSON: \`useFetch<Answer, Report>(url, { method: "POST", body: report })\`.
|
|
@@ -559,7 +559,7 @@ export default {
|
|
|
559
559
|
|
|
560
560
|
const { data, error } = await useFetch<Weather>("https://example.com/weather", { query: { city: "Paris" } });
|
|
561
561
|
if (error) return console.error(error.message);
|
|
562
|
-
print(
|
|
562
|
+
player.print(\`\${data!.temperature} °C\`);
|
|
563
563
|
\`\`\`
|
|
564
564
|
|
|
565
565
|
Тело-объект уходит как JSON: \`useFetch<Answer, Report>(url, { method: "POST", body: report })\`.
|
package/scripts/docs/as/fs.ts
CHANGED
|
@@ -31,21 +31,25 @@ export default {
|
|
|
31
31
|
},
|
|
32
32
|
'writeFileSync': {
|
|
33
33
|
en: `
|
|
34
|
-
Writes text
|
|
35
|
-
opened (a folder that
|
|
34
|
+
Writes text, or bytes - a \`Uint8Array\` or an \`ArrayBuffer\` - to a file,
|
|
35
|
+
replacing what was there; \`false\` when it cannot be opened (a folder that
|
|
36
|
+
does not exist, for one). Bytes are not written past the game folder.
|
|
36
37
|
|
|
37
38
|
\`\`\`ts
|
|
38
39
|
fs.writeFileSync("addons/amxmodx/data/last-map.txt", server.map);
|
|
40
|
+
fs.writeFileSync("maps/kz_map.bsp", await response.arrayBuffer());
|
|
39
41
|
\`\`\`
|
|
40
42
|
|
|
41
43
|
Pawn: \`fopen\`, \`fputs\`
|
|
42
44
|
`,
|
|
43
45
|
ru: `
|
|
44
|
-
Записывает текст
|
|
45
|
-
удалось открыть (например,
|
|
46
|
+
Записывает текст или байты — \`Uint8Array\` или \`ArrayBuffer\` — в файл
|
|
47
|
+
вместо того, что там было; \`false\`, если файл не удалось открыть (например,
|
|
48
|
+
такой папки нет). Байты не пишутся за пределы папки игры.
|
|
46
49
|
|
|
47
50
|
\`\`\`ts
|
|
48
51
|
fs.writeFileSync("addons/amxmodx/data/last-map.txt", server.map);
|
|
52
|
+
fs.writeFileSync("maps/kz_map.bsp", await response.arrayBuffer());
|
|
49
53
|
\`\`\`
|
|
50
54
|
|
|
51
55
|
Pawn: \`fopen\`, \`fputs\`
|
|
@@ -53,16 +57,70 @@ export default {
|
|
|
53
57
|
},
|
|
54
58
|
'appendFileSync': {
|
|
55
59
|
en: `
|
|
56
|
-
Adds text to the end of a file, making it if there is none; \`false\` when it cannot be opened.
|
|
60
|
+
Adds text or bytes to the end of a file, making it if there is none; \`false\` when it cannot be opened.
|
|
57
61
|
|
|
58
62
|
Pawn: \`fopen(path, "a")\`, \`fputs\`
|
|
59
63
|
`,
|
|
60
64
|
ru: `
|
|
61
|
-
Дописывает текст в конец файла, создавая его, если файла нет; \`false\`, если его не удалось открыть.
|
|
65
|
+
Дописывает текст или байты в конец файла, создавая его, если файла нет; \`false\`, если его не удалось открыть.
|
|
62
66
|
|
|
63
67
|
Pawn: \`fopen(path, "a")\`, \`fputs\`
|
|
64
68
|
`,
|
|
65
69
|
},
|
|
70
|
+
'readBytesSync': {
|
|
71
|
+
en: `
|
|
72
|
+
Reads a whole file as bytes; \`null\` when it cannot be opened or the path
|
|
73
|
+
leaves the game folder.
|
|
74
|
+
`,
|
|
75
|
+
ru: `
|
|
76
|
+
Читает весь файл как байты; \`null\`, если его не удалось открыть или путь
|
|
77
|
+
ведёт за пределы папки игры.
|
|
78
|
+
`,
|
|
79
|
+
},
|
|
80
|
+
'readBytes': {
|
|
81
|
+
en: `\`readBytesSync\` as a promise, rejected when the file cannot be opened.`,
|
|
82
|
+
ru: `\`readBytesSync\` в виде промиса; отклоняется, если файл не удалось открыть.`,
|
|
83
|
+
},
|
|
84
|
+
'ArchiveEntry': {
|
|
85
|
+
en: `A file of an archive, from \`extract\`: its path inside the archive and its bytes.`,
|
|
86
|
+
ru: `Файл архива из \`extract\`: его путь внутри архива и его байты.`,
|
|
87
|
+
},
|
|
88
|
+
'ArchiveEntry.path': {
|
|
89
|
+
en: `The path inside the archive, \`/\` between folders: \`"maps/de_dust2.bsp"\`.`,
|
|
90
|
+
ru: `Путь внутри архива, \`/\` между папками: \`"maps/de_dust2.bsp"\`.`,
|
|
91
|
+
},
|
|
92
|
+
'ArchiveEntry.data': {
|
|
93
|
+
en: `The file's bytes.`,
|
|
94
|
+
ru: `Байты файла.`,
|
|
95
|
+
},
|
|
96
|
+
'extract': {
|
|
97
|
+
en: `
|
|
98
|
+
The files of an archive, with their paths inside it; folders are not
|
|
99
|
+
listed. The archive's kind is read off its first bytes: a zip archive,
|
|
100
|
+
stored or deflated. Throws an \`Error\` for a kind it does not read - naming
|
|
101
|
+
the ones it does - an entry whose bytes do not check out, and a path that
|
|
102
|
+
would leave the folder it is unpacked into.
|
|
103
|
+
|
|
104
|
+
\`\`\`ts
|
|
105
|
+
for (const entry of fs.extract(await response.arrayBuffer())) {
|
|
106
|
+
fs.writeFileSync(entry.path, entry.data);
|
|
107
|
+
}
|
|
108
|
+
\`\`\`
|
|
109
|
+
`,
|
|
110
|
+
ru: `
|
|
111
|
+
Файлы архива с их путями внутри него; папки не перечисляются. Вид архива
|
|
112
|
+
читается по его первым байтам: zip-архив, сохранённый как есть или сжатый
|
|
113
|
+
deflate. Бросает \`Error\` для вида, который не читает, — называя те, что
|
|
114
|
+
читает, — для файла, чьи байты не сходятся, и для пути, который ведёт за
|
|
115
|
+
пределы папки, куда архив распаковывается.
|
|
116
|
+
|
|
117
|
+
\`\`\`ts
|
|
118
|
+
for (const entry of fs.extract(await response.arrayBuffer())) {
|
|
119
|
+
fs.writeFileSync(entry.path, entry.data);
|
|
120
|
+
}
|
|
121
|
+
\`\`\`
|
|
122
|
+
`,
|
|
123
|
+
},
|
|
66
124
|
'existsSync': {
|
|
67
125
|
en: `
|
|
68
126
|
\`true\` when the file or folder exists.
|
|
@@ -170,4 +228,130 @@ export default {
|
|
|
170
228
|
en: `\`readdirSync\` as a promise, rejected when there is no such folder.`,
|
|
171
229
|
ru: `\`readdirSync\` в виде промиса; отклоняется, если такой папки нет.`,
|
|
172
230
|
},
|
|
231
|
+
'unlinkSync': {
|
|
232
|
+
en: `
|
|
233
|
+
Deletes a file; \`false\` when there is none or it cannot be deleted.
|
|
234
|
+
|
|
235
|
+
Pawn: \`delete_file\`, \`unlink\`
|
|
236
|
+
`,
|
|
237
|
+
ru: `
|
|
238
|
+
Удаляет файл; \`false\`, если его нет или его не удалось удалить.
|
|
239
|
+
|
|
240
|
+
Pawn: \`delete_file\`, \`unlink\`
|
|
241
|
+
`,
|
|
242
|
+
},
|
|
243
|
+
'renameSync': {
|
|
244
|
+
en: `
|
|
245
|
+
Moves or renames a file: \`fs.renameSync("addons/amxmodx/data/top.txt",
|
|
246
|
+
"addons/amxmodx/data/top.old")\`; \`false\` when it cannot.
|
|
247
|
+
|
|
248
|
+
Pawn: \`rename_file\`
|
|
249
|
+
`,
|
|
250
|
+
ru: `
|
|
251
|
+
Перемещает или переименовывает файл: \`fs.renameSync("addons/amxmodx/data/top.txt",
|
|
252
|
+
"addons/amxmodx/data/top.old")\`; \`false\`, если не удалось.
|
|
253
|
+
|
|
254
|
+
Pawn: \`rename_file\`
|
|
255
|
+
`,
|
|
256
|
+
},
|
|
257
|
+
'rmdirSync': {
|
|
258
|
+
en: `
|
|
259
|
+
Deletes an empty folder; \`false\` when there is none, it holds something or
|
|
260
|
+
it cannot be deleted.
|
|
261
|
+
|
|
262
|
+
Pawn: \`rmdir\`
|
|
263
|
+
`,
|
|
264
|
+
ru: `
|
|
265
|
+
Удаляет пустую папку; \`false\`, если её нет, в ней что-то есть или её не
|
|
266
|
+
удалось удалить.
|
|
267
|
+
|
|
268
|
+
Pawn: \`rmdir\`
|
|
269
|
+
`,
|
|
270
|
+
},
|
|
271
|
+
'Stats': {
|
|
272
|
+
en: `
|
|
273
|
+
A file's or a folder's facts from \`statSync\`, as Node's \`fs.Stats\`.
|
|
274
|
+
`,
|
|
275
|
+
ru: `
|
|
276
|
+
Сведения о файле или папке из \`statSync\`, как \`fs.Stats\` в Node.
|
|
277
|
+
`,
|
|
278
|
+
},
|
|
279
|
+
'Stats.size': {
|
|
280
|
+
en: `
|
|
281
|
+
The size in bytes; \`0\` for a folder.
|
|
282
|
+
`,
|
|
283
|
+
ru: `
|
|
284
|
+
Размер в байтах; \`0\` для папки.
|
|
285
|
+
`,
|
|
286
|
+
},
|
|
287
|
+
'Stats.mtime': {
|
|
288
|
+
en: `
|
|
289
|
+
The moment it last changed.
|
|
290
|
+
`,
|
|
291
|
+
ru: `
|
|
292
|
+
Момент его последнего изменения.
|
|
293
|
+
`,
|
|
294
|
+
},
|
|
295
|
+
'Stats.isFile': {
|
|
296
|
+
en: `
|
|
297
|
+
Whether it is a file.
|
|
298
|
+
`,
|
|
299
|
+
ru: `
|
|
300
|
+
Файл ли это.
|
|
301
|
+
`,
|
|
302
|
+
},
|
|
303
|
+
'Stats.isDirectory': {
|
|
304
|
+
en: `
|
|
305
|
+
Whether it is a folder.
|
|
306
|
+
`,
|
|
307
|
+
ru: `
|
|
308
|
+
Папка ли это.
|
|
309
|
+
`,
|
|
310
|
+
},
|
|
311
|
+
'statSync': {
|
|
312
|
+
en: `
|
|
313
|
+
A file's or a folder's size and the moment it last changed; \`null\` when
|
|
314
|
+
there is none: \`fs.statSync("addons/amxmodx/logs/error.log")?.size\`.
|
|
315
|
+
|
|
316
|
+
Pawn: \`file_size\`, \`GetFileTime\`
|
|
317
|
+
`,
|
|
318
|
+
ru: `
|
|
319
|
+
Размер файла или папки и момент последнего изменения; \`null\`, если их нет:
|
|
320
|
+
\`fs.statSync("addons/amxmodx/logs/error.log")?.size\`.
|
|
321
|
+
|
|
322
|
+
Pawn: \`file_size\`, \`GetFileTime\`
|
|
323
|
+
`,
|
|
324
|
+
},
|
|
325
|
+
'unlink': {
|
|
326
|
+
en: `
|
|
327
|
+
\`unlinkSync\` as a promise, rejected when the file cannot be deleted.
|
|
328
|
+
`,
|
|
329
|
+
ru: `
|
|
330
|
+
\`unlinkSync\` в виде промиса; отклоняется, если файл не удалось удалить.
|
|
331
|
+
`,
|
|
332
|
+
},
|
|
333
|
+
'rename': {
|
|
334
|
+
en: `
|
|
335
|
+
\`renameSync\` as a promise, rejected when the file cannot be moved.
|
|
336
|
+
`,
|
|
337
|
+
ru: `
|
|
338
|
+
\`renameSync\` в виде промиса; отклоняется, если файл не удалось переместить.
|
|
339
|
+
`,
|
|
340
|
+
},
|
|
341
|
+
'rmdir': {
|
|
342
|
+
en: `
|
|
343
|
+
\`rmdirSync\` as a promise, rejected when the folder cannot be deleted.
|
|
344
|
+
`,
|
|
345
|
+
ru: `
|
|
346
|
+
\`rmdirSync\` в виде промиса; отклоняется, если папку не удалось удалить.
|
|
347
|
+
`,
|
|
348
|
+
},
|
|
349
|
+
'stat': {
|
|
350
|
+
en: `
|
|
351
|
+
\`statSync\` as a promise, rejected when there is no such file or folder.
|
|
352
|
+
`,
|
|
353
|
+
ru: `
|
|
354
|
+
\`statSync\` в виде промиса; отклоняется, если такого файла или папки нет.
|
|
355
|
+
`,
|
|
356
|
+
},
|
|
173
357
|
};
|
|
@@ -45,4 +45,85 @@ export default {
|
|
|
45
45
|
en: `A new vector in the same direction, one unit long; a zero vector stays zero.`,
|
|
46
46
|
ru: `Новый вектор того же направления, длиной в единицу; нулевой вектор так и остаётся нулевым.`,
|
|
47
47
|
},
|
|
48
|
+
'Vector.fromAngles': {
|
|
49
|
+
en: `
|
|
50
|
+
The direction angles look in, one unit long:
|
|
51
|
+
\`Vector.fromAngles(player.viewAngle).scale(500)\` is a push the way the
|
|
52
|
+
player looks.
|
|
53
|
+
|
|
54
|
+
Pawn: \`angle_vector(..., ANGLEVECTOR_FORWARD, ...)\`, \`velocity_by_aim\`
|
|
55
|
+
`,
|
|
56
|
+
ru: `
|
|
57
|
+
Направление, куда смотрят углы, длиной в единицу:
|
|
58
|
+
\`Vector.fromAngles(player.viewAngle).scale(500)\` — толчок туда, куда смотрит
|
|
59
|
+
игрок.
|
|
60
|
+
|
|
61
|
+
Pawn: \`angle_vector(..., ANGLEVECTOR_FORWARD, ...)\`, \`velocity_by_aim\`
|
|
62
|
+
`,
|
|
63
|
+
},
|
|
64
|
+
'Vector.directions': {
|
|
65
|
+
en: `
|
|
66
|
+
The three directions of angles, one unit long each: where they look,
|
|
67
|
+
to their right and above them - \`const { forward, right } =
|
|
68
|
+
Vector.directions(player.viewAngle)\`.
|
|
69
|
+
|
|
70
|
+
Pawn: \`angle_vector\`, \`engfunc(EngFunc_MakeVectors, ...)\`
|
|
71
|
+
`,
|
|
72
|
+
ru: `
|
|
73
|
+
Три направления углов, каждое длиной в единицу: куда они смотрят, вправо от
|
|
74
|
+
них и вверх — \`const { forward, right } = Vector.directions(player.viewAngle)\`.
|
|
75
|
+
|
|
76
|
+
Pawn: \`angle_vector\`, \`engfunc(EngFunc_MakeVectors, ...)\`
|
|
77
|
+
`,
|
|
78
|
+
},
|
|
79
|
+
'Vector.toAngles': {
|
|
80
|
+
en: `
|
|
81
|
+
The angles that look along this vector, as a player's view holds them -
|
|
82
|
+
a pitch below the horizon positive: \`player.viewAngle =
|
|
83
|
+
target.subtract(player.eyes).toAngles()\`. \`Vector.fromAngles\` turns
|
|
84
|
+
them back.
|
|
85
|
+
|
|
86
|
+
Pawn: \`vector_to_angle\`, \`engfunc(EngFunc_VecToAngles, ...)\`
|
|
87
|
+
`,
|
|
88
|
+
ru: `
|
|
89
|
+
Углы, которые смотрят вдоль этого вектора, как их держит взгляд игрока, —
|
|
90
|
+
наклон ниже горизонта положительный: \`player.viewAngle =
|
|
91
|
+
target.subtract(player.eyes).toAngles()\`. \`Vector.fromAngles\` превращает их
|
|
92
|
+
обратно.
|
|
93
|
+
|
|
94
|
+
Pawn: \`vector_to_angle\`, \`engfunc(EngFunc_VecToAngles, ...)\`
|
|
95
|
+
`,
|
|
96
|
+
},
|
|
97
|
+
'Directions': {
|
|
98
|
+
en: `
|
|
99
|
+
The three directions of angles: ahead, to the right and up - \`Vector.directions\`.
|
|
100
|
+
`,
|
|
101
|
+
ru: `
|
|
102
|
+
Три направления углов: вперёд, вправо и вверх — \`Vector.directions\`.
|
|
103
|
+
`,
|
|
104
|
+
},
|
|
105
|
+
'Directions.forward': {
|
|
106
|
+
en: `
|
|
107
|
+
The direction they look in.
|
|
108
|
+
`,
|
|
109
|
+
ru: `
|
|
110
|
+
Направление, куда они смотрят.
|
|
111
|
+
`,
|
|
112
|
+
},
|
|
113
|
+
'Directions.right': {
|
|
114
|
+
en: `
|
|
115
|
+
To their right.
|
|
116
|
+
`,
|
|
117
|
+
ru: `
|
|
118
|
+
Вправо от них.
|
|
119
|
+
`,
|
|
120
|
+
},
|
|
121
|
+
'Directions.up': {
|
|
122
|
+
en: `
|
|
123
|
+
Above them.
|
|
124
|
+
`,
|
|
125
|
+
ru: `
|
|
126
|
+
Вверх от них.
|
|
127
|
+
`,
|
|
128
|
+
},
|
|
48
129
|
};
|
package/scripts/docs/entities.ts
CHANGED
|
@@ -737,6 +737,10 @@ export const ENTITY_FIELDS: Record<string, Text> = {
|
|
|
737
737
|
en: `The player's field of view in degrees: \`90\` is normal, \`40\` and \`10\` through a sniper scope. Setting it widens or narrows his view - \`110\` shows more - until the game sets it again: at spawn, when he draws a weapon, when he zooms.`,
|
|
738
738
|
ru: `Поле зрения игрока в градусах: \`90\` — обычное, \`40\` и \`10\` — в снайперский прицел. Запись расширяет или сужает обзор — \`110\` показывает больше, — пока игра не поставит своё: при появлении, когда он достаёт оружие, когда приближает прицел.`,
|
|
739
739
|
},
|
|
740
|
+
m_flFallVelocity: {
|
|
741
|
+
en: `The player's falling speed, units per second, positive downwards: the one the game works fall damage out from on landing. Setting it sets the entity's \`fallVelocity\` too - \`player.fallVelocity = 0\` lands him without damage.`,
|
|
742
|
+
ru: `Скорость падения игрока, единиц в секунду, вниз положительная: по ней игра считает урон при приземлении. Запись ставит и \`fallVelocity\` сущности — \`player.fallVelocity = 0\` приземляет без урона.`,
|
|
743
|
+
},
|
|
740
744
|
m_iLastZoom: {
|
|
741
745
|
en: `The player's zoom (field of view) to go back to after a sniper rifle reloads or fires.`,
|
|
742
746
|
ru: `Зум игрока (поле зрения), к которому вернуться после перезарядки или выстрела снайперской винтовки.`,
|
|
@@ -1983,6 +1987,14 @@ Pawn: \`is_valid_ent\`, \`is_entity\``,
|
|
|
1983
1987
|
ru: `\`true\`, пока сущность есть в мире: \`false\`, когда движок её освободил (\`remove()\` освобождает её в конце кадра), для ушедшего игрока и для \`0\` — «нет сущности». Номер из события или хука может указывать на сущность, которой уже нет.
|
|
1984
1988
|
|
|
1985
1989
|
Pawn: \`is_valid_ent\`, \`is_entity\``,
|
|
1990
|
+
},
|
|
1991
|
+
'Entity.dropToFloor': {
|
|
1992
|
+
en: `Drops the entity straight down onto what is under it, as the game puts an item on the floor when a map starts: \`true\` when it landed, \`false\` when there is nothing under it within 256 units or it is stuck in something.
|
|
1993
|
+
|
|
1994
|
+
Pawn: \`drop_to_floor\`, \`engfunc(EngFunc_DropToFloor, ...)\``,
|
|
1995
|
+
ru: `Опускает сущность вертикально вниз на то, что под ней, как игра кладёт предмет на пол при старте карты: \`true\`, если она опустилась, \`false\`, если под ней ничего нет в пределах 256 единиц или она во что-то застряла.
|
|
1996
|
+
|
|
1997
|
+
Pawn: \`drop_to_floor\`, \`engfunc(EngFunc_DropToFloor, ...)\``,
|
|
1986
1998
|
},
|
|
1987
1999
|
'Entity.emitSound': {
|
|
1988
2000
|
en: `Plays a sound from the entity, heard by everyone near and fading with distance: \`player.emitSound("myplugin/hit.wav")\`. The path is under \`sound/\`, as \`server.precache\` takes it; \`options\` set the channel, the volume, the attenuation and the pitch.
|
package/scripts/docs/events.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Our own words for the server events, in both languages the project speaks.
|
|
2
2
|
//
|
|
3
|
-
// scripts/generate-
|
|
3
|
+
// scripts/generate-image.ts writes these into as/events.ts as the tooltips an
|
|
4
4
|
// editor shows on `server.addEventListener("...")`, on the event class and on
|
|
5
5
|
// each of its fields. The language is AMXTS_DOCS_LANG in .env ("en" by
|
|
6
6
|
// default, or "ru"). An event missing here, or missing a language, falls back
|
|
@@ -59,16 +59,10 @@ export const EVENTS: Record<string, EventDoc> = {
|
|
|
59
59
|
},
|
|
60
60
|
plugin_end: {
|
|
61
61
|
summary: {
|
|
62
|
-
en: `The
|
|
63
|
-
ru:
|
|
62
|
+
en: `The plugin stops - the map ends, the server shuts down, or \`amxts_reload\`/\`amxts_unload\` stops it: save what has to survive.`,
|
|
63
|
+
ru: `Плагин останавливается — карта заканчивается, сервер выключается или его останавливает \`amxts_reload\`/\`amxts_unload\`: сохраните то, что должно это пережить.`,
|
|
64
64
|
},
|
|
65
65
|
},
|
|
66
|
-
plugin_pause: {
|
|
67
|
-
summary: { en: `An admin paused this plugin.`, ru: `Админ поставил плагин на паузу.` },
|
|
68
|
-
},
|
|
69
|
-
plugin_unpause: {
|
|
70
|
-
summary: { en: `An admin resumed this plugin.`, ru: `Админ снял плагин с паузы.` },
|
|
71
|
-
},
|
|
72
66
|
server_changelevel: {
|
|
73
67
|
summary: {
|
|
74
68
|
en: `The server is about to change the map.`,
|
|
@@ -78,6 +72,23 @@ export const EVENTS: Record<string, EventDoc> = {
|
|
|
78
72
|
map: { en: `The map the server changes to, e.g. \`"de_dust2"\`.`, ru: `Карта, на которую переходит сервер, например \`"de_dust2"\`.` },
|
|
79
73
|
},
|
|
80
74
|
},
|
|
75
|
+
plugin_log: {
|
|
76
|
+
summary: {
|
|
77
|
+
en: `A line the game writes to its log - a round's end, a kill, a bomb planted: \`event.text\` whole, \`event.args\` its parts.`,
|
|
78
|
+
ru: `Строка, которую игра пишет в свой лог, — конец раунда, убийство, заложенная бомба: \`event.text\` целиком, \`event.args\` по частям.`,
|
|
79
|
+
},
|
|
80
|
+
fields: {
|
|
81
|
+
text: {
|
|
82
|
+
en: `The line as the game logs it, without the date: \`World triggered "Round_Start"\`.`,
|
|
83
|
+
ru: `Строка так, как её пишет игра, без даты: \`World triggered "Round_Start"\`.`,
|
|
84
|
+
},
|
|
85
|
+
args: {
|
|
86
|
+
en: `The line in parts, as AMX Mod X splits it: a quoted text, a text in parentheses and the words between, each one part - \`World triggered "Round_Draw"\` is \`["World triggered", "Round_Draw"]\`.`,
|
|
87
|
+
ru: `Строка по частям, как её делит AMX Mod X: текст в кавычках, текст в скобках и слова между ними — каждое отдельной частью; \`World triggered "Round_Draw"\` — это \`["World triggered", "Round_Draw"]\`.`,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
example: `server.addEventListener("log", (event) => {\n\tif (event.text.startsWith("World triggered")) console.log(event.args[1]);\n});`,
|
|
91
|
+
},
|
|
81
92
|
client_connect: {
|
|
82
93
|
summary: {
|
|
83
94
|
en: `A player started connecting. The player is not in the game yet: show him anything after \`"putInServer"\`.`,
|
|
@@ -117,7 +128,7 @@ export const EVENTS: Record<string, EventDoc> = {
|
|
|
117
128
|
ru: `Игрок зашёл и уже в игре: момент поприветствовать его.`,
|
|
118
129
|
},
|
|
119
130
|
fields: { player },
|
|
120
|
-
example: `server.addEventListener("putInServer", (event) => {\n\
|
|
131
|
+
example: `server.addEventListener("putInServer", (event) => {\n\tevent.player.print("Welcome!");\n});`,
|
|
121
132
|
},
|
|
122
133
|
client_disconnected: {
|
|
123
134
|
summary: {
|
|
@@ -154,10 +165,30 @@ export const EVENTS: Record<string, EventDoc> = {
|
|
|
154
165
|
},
|
|
155
166
|
client_command: {
|
|
156
167
|
summary: {
|
|
157
|
-
en: `A player sent a console command
|
|
158
|
-
ru: `Игрок отправил консольную
|
|
168
|
+
en: `A player sent a console command - a chat line is \`say\` or \`say_team\`. For one command, \`server.addCommand("name", handler)\` is simpler.`,
|
|
169
|
+
ru: `Игрок отправил консольную команду — строка в чат это \`say\` или \`say_team\`. Для одной команды проще \`server.addCommand("name", handler)\`.`,
|
|
159
170
|
},
|
|
160
|
-
|
|
171
|
+
notes: [],
|
|
172
|
+
fields: {
|
|
173
|
+
player,
|
|
174
|
+
command: {
|
|
175
|
+
en: `The command's name, as typed, e.g. \`"say"\`, \`"say_team"\`, \`"buy"\`.`,
|
|
176
|
+
ru: `Имя команды, как её ввели, например \`"say"\`, \`"say_team"\`, \`"buy"\`.`,
|
|
177
|
+
},
|
|
178
|
+
args: {
|
|
179
|
+
en: `The command's words after its name; for \`say\` and \`say_team\`, the words of the chat line - \`say /cp now\` is \`["/cp", "now"]\`.`,
|
|
180
|
+
ru: `Слова команды после имени; у \`say\` и \`say_team\` — слова строки чата: \`say /cp now\` — это \`["/cp", "now"]\`.`,
|
|
181
|
+
},
|
|
182
|
+
text: {
|
|
183
|
+
en: `The command's text after its name, as one line; for \`say\` and \`say_team\`, the chat line without its quotes.`,
|
|
184
|
+
ru: `Текст команды после имени одной строкой; у \`say\` и \`say_team\` — строка чата без кавычек.`,
|
|
185
|
+
},
|
|
186
|
+
preventDefault: {
|
|
187
|
+
en: `Stops the command: the game does not run it - a chat line is not said - and no plugin's \`server.addCommand\` hears it. The other listeners of \`"command"\` still do.`,
|
|
188
|
+
ru: `Останавливает команду: игра её не выполняет — строка чата не уходит в чат, — и её не слышит ни один \`server.addCommand\` плагинов. Остальные слушатели \`"command"\` её слышат.`,
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
example: `server.addEventListener("command", (event) => {\n\tif (event.command == "say" && event.args[0] == "/cp") checkpoint(event.player);\n});`,
|
|
161
192
|
},
|
|
162
193
|
client_infochanged: {
|
|
163
194
|
summary: {
|
|
@@ -221,6 +252,11 @@ export const EVENTS: Record<string, EventDoc> = {
|
|
|
221
252
|
iparam2: { en: `The event's second whole-number parameter.`, ru: `Второй целый параметр события.` },
|
|
222
253
|
bparam1: { en: `The event's first flag parameter, \`1\` or \`0\`.`, ru: `Первый параметр-флаг события, \`1\` или \`0\`.` },
|
|
223
254
|
bparam2: { en: `The event's second flag parameter, \`1\` or \`0\`.`, ru: `Второй параметр-флаг события, \`1\` или \`0\`.` },
|
|
255
|
+
preventDefault: { en: `Stops the event: no player gets it - a shot's sound and flash with it.`, ru: `Останавливает событие: его не получает ни один игрок — вместе со звуком и вспышкой выстрела.` },
|
|
256
|
+
recipients: {
|
|
257
|
+
en: `Plays the event only to these of the players it would reach - \`event.recipients = players.filter(...)\`; the others do not hear the shot. The player who caused it is not left out by it.`,
|
|
258
|
+
ru: `Проигрывает событие только этим из игроков, до которых оно дошло бы, — \`event.recipients = players.filter(...)\`; остальные не слышат выстрела. Игрока, из-за которого оно случилось, это не исключает.`,
|
|
259
|
+
},
|
|
224
260
|
},
|
|
225
261
|
},
|
|
226
262
|
};
|
package/scripts/docs/game.ts
CHANGED
|
@@ -30,6 +30,12 @@ const theWeapon: Text = { en: `The weapon the event is about - one of the class
|
|
|
30
30
|
const theEntity: Text = { en: `The entity the event is about - one of the class \`classname\` names.`, ru: `Сущность, о которой событие, — одного класса, названного в \`classname\`.` };
|
|
31
31
|
|
|
32
32
|
export const GAME: Record<string, GameDoc> = {
|
|
33
|
+
entityState: {
|
|
34
|
+
summary: {
|
|
35
|
+
en: `The state of an entity a player can see, as he is sent it each frame: its place, angles, look - written for him alone - or hidden from him with \`event.preventDefault()\`. \`{ classname }\` names the entities a listener is about; the module passes only those.`,
|
|
36
|
+
ru: `Состояние сущности, которую видит игрок, как он получает его каждый кадр: её место, углы, вид — изменённые только для него, — или скрытая от него через \`event.preventDefault()\`. \`{ classname }\` называет сущности, о которых слушатель; модуль передаёт только их.`,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
33
39
|
touch: {
|
|
34
40
|
summary: {
|
|
35
41
|
en: `An entity touched another: \`event.toucher\` moved into \`event.touched\`. Pass the classes it is about as the third argument - \`{ toucher: "player", touched: "player" }\` - so only those touches reach the plugin; \`event.preventDefault()\` blocks the touch.`,
|
package/scripts/docs/messages.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Our own words for the messages the server sends its clients, as
|
|
2
2
|
// server.addMessageListener(name, ...) hears them - in both languages.
|
|
3
|
-
// scripts/generate-
|
|
3
|
+
// scripts/generate-image.ts writes them into as/events.ts as the tooltips an
|
|
4
4
|
// editor shows on the name, the event and its fields: the summary, then the
|
|
5
5
|
// game's name of the message, so a Pawn author who searches for `DeathMsg`
|
|
6
6
|
// finds `death`. A name that hears a few of the game's messages has its words
|
|
@@ -427,6 +427,7 @@ export const MESSAGES: Record<string, EventDoc> = {
|
|
|
427
427
|
slot: { en: `The slot the weapon is in, from \`0\`.`, ru: `Слот оружия, с \`0\`.` },
|
|
428
428
|
position: { en: `The weapon's place in the slot, from \`0\`.`, ru: `Место оружия в слоте, с \`0\`.` },
|
|
429
429
|
weapon: { en: `The weapon, by its kind, e.g. \`"ak47"\`.`, ru: `Оружие по его виду, например \`"ak47"\`.` },
|
|
430
|
+
flags: { en: `The weapon's ITEM_FLAG_* bits: \`8\` for one thrown when it is empty, \`16\` for one used only once.`, ru: `Биты ITEM_FLAG_* оружия: \`8\` — выбрасывается, когда пусто, \`16\` — используется один раз.` },
|
|
430
431
|
},
|
|
431
432
|
},
|
|
432
433
|
WeapPickup: {
|
|
@@ -460,3 +461,11 @@ export const ANY_MESSAGE: { args: Text; player: Text } = {
|
|
|
460
461
|
args: { en: `Its arguments are read by place, through \`event.args\`.`, ru: `Его аргументы читаются по месту, через \`event.args\`.` },
|
|
461
462
|
player: receiver,
|
|
462
463
|
};
|
|
464
|
+
|
|
465
|
+
/** The words of a message's fields for sending: what player.send and server.send take for a name. */
|
|
466
|
+
export function sendFields(name: string, message: string): Text {
|
|
467
|
+
return {
|
|
468
|
+
en: `What \`player.send("${name}", ...)\` and \`server.send("${name}", ...)\` take: the game's \`${message}\` message, each field one of its arguments. A field left out goes as \`0\` or empty text.\n\nPawn: \`message_begin(..., get_user_msgid("${message}"))\`, \`write_*\`, \`message_end\``,
|
|
469
|
+
ru: `Что принимают \`player.send("${name}", ...)\` и \`server.send("${name}", ...)\`: сообщение игры \`${message}\`, каждое поле — один его аргумент. Пропущенное поле уходит как \`0\` или пустой текст.\n\nPawn: \`message_begin(..., get_user_msgid("${message}"))\`, \`write_*\`, \`message_end\``,
|
|
470
|
+
};
|
|
471
|
+
}
|
package/scripts/hlds-events.ts
CHANGED
|
@@ -43,8 +43,8 @@ function noAnswer(en: string, ru: string): Text {
|
|
|
43
43
|
|
|
44
44
|
function buy(en: string, ru: string): Text {
|
|
45
45
|
return noAnswer(
|
|
46
|
-
`heard
|
|
47
|
-
|
|
46
|
+
`heard as the game checks the purchase, for an item a buy command or a buy menu names: \`preventDefault()\` stops it; ${en}`,
|
|
47
|
+
`слышно, когда игра проверяет покупку, для предмета, который называет команда покупки или меню покупки: \`preventDefault()\` отменяет её; ${ru}`,
|
|
48
48
|
);
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -79,7 +79,7 @@ export const HEARD: Record<string, HeardEvent> = {
|
|
|
79
79
|
},
|
|
80
80
|
gameThink: { class: 'B', backend: 'server_frame', gaps: after },
|
|
81
81
|
mapReset: { class: 'B', backend: 'the decal_reset.sc playback CleanUpMap ends with', gaps: after },
|
|
82
|
-
intermission: { class: 'B', backend: '
|
|
82
|
+
intermission: { class: 'B', backend: 'the engine message 30 (SVC_INTERMISSION)', gaps: after },
|
|
83
83
|
changeLevel: { class: 'B', backend: 'server_changelevel', gaps: { en: '`preventDefault()` does nothing', ru: '`preventDefault()` ничего не делает' } },
|
|
84
84
|
|
|
85
85
|
// Spawning and dying.
|
|
@@ -138,15 +138,15 @@ export const HEARD: Record<string, HeardEvent> = {
|
|
|
138
138
|
'`amount` — на сколько сдвинулись его деньги с тех пор, как игра в последний раз их ему прислала, а `reason` читается как `"none"`',
|
|
139
139
|
),
|
|
140
140
|
},
|
|
141
|
-
buyWeapon: { class: 'B', backend: '
|
|
142
|
-
buyItem: { class: 'B', backend: '
|
|
143
|
-
buyAmmo: { class: 'B', backend: '
|
|
141
|
+
buyWeapon: { class: 'B', backend: 'the game\'s CanBuyThis, a weapon (CS_OnBuy\'s place)', gaps: buy('`event.result` reads as `null`', '`event.result` читается как `null`') },
|
|
142
|
+
buyItem: { class: 'B', backend: 'the game\'s CanPlayerBuy and GiveNamedItem, the equipment (CS_OnBuy\'s place)', gaps: buy('heard for the equipment menu\'s items', 'слышно для предметов меню снаряжения') },
|
|
143
|
+
buyAmmo: { class: 'B', backend: 'the game\'s GiveNamedItem, ammo (CS_OnBuy\'s place)', gaps: buy('`weapon` reads as the world, `blinkMoney` as `true`', '`weapon` читается как мир, `blinkMoney` — как `true`') },
|
|
144
144
|
itemRestricted: {
|
|
145
145
|
class: 'B',
|
|
146
|
-
backend: '
|
|
146
|
+
backend: 'the game\'s ClientCommand, a buy command or a buy menu\'s number (CS_OnBuyAttempt\'s place)',
|
|
147
147
|
gaps: {
|
|
148
|
-
en: 'asked only for `"buying"`,
|
|
149
|
-
ru: 'спрашивается только про `"buying"`,
|
|
148
|
+
en: 'asked only for `"buying"`, as a player asks to buy: answering `true` forbids the purchase, `false` lets the game go on',
|
|
149
|
+
ru: 'спрашивается только про `"buying"`, когда игрок просит покупку: ответ `true` запрещает покупку, `false` оставляет решение игре',
|
|
150
150
|
},
|
|
151
151
|
},
|
|
152
152
|
|
|
@@ -234,7 +234,7 @@ export const HEARD: Record<string, HeardEvent> = {
|
|
|
234
234
|
},
|
|
235
235
|
},
|
|
236
236
|
|
|
237
|
-
// Precaching:
|
|
237
|
+
// Precaching: the engine's functions, hooked as the plugin loads, before the game's own precaches.
|
|
238
238
|
precacheModel: { class: 'B', backend: 'FM_PrecacheModel', gaps: precached },
|
|
239
239
|
precacheSound: { class: 'B', backend: 'FM_PrecacheSound', gaps: precached },
|
|
240
240
|
precacheFile: { class: 'B', backend: 'FM_PrecacheGeneric', gaps: precached },
|
|
@@ -341,7 +341,7 @@ export interface HeardField {
|
|
|
341
341
|
}
|
|
342
342
|
|
|
343
343
|
export const HEARD_FIELDS: Record<string, HeardField> = {
|
|
344
|
-
gameName: { class: 'A', backend: '
|
|
344
|
+
gameName: { class: 'A', backend: 'the game\'s GetGameDescription read, and answered with the text written' },
|
|
345
345
|
timeLimit: {
|
|
346
346
|
class: 'B',
|
|
347
347
|
backend: 'mp_timelimit and AMX Mod X\'s time left',
|
package/scripts/includes.ts
CHANGED
|
@@ -14,9 +14,8 @@
|
|
|
14
14
|
* includes/ and AMX Mod X's. The core's includes/vendor/ is the core's own:
|
|
15
15
|
* a project sees what its server has.
|
|
16
16
|
*
|
|
17
|
-
* Everything available is parsed for its natives, but the
|
|
18
|
-
* what order.txt lists
|
|
19
|
-
* load makes AMX Mod X refuse the plugin, and the runtime goes down with it.
|
|
17
|
+
* Everything available is parsed for its natives, but the natives' image
|
|
18
|
+
* pulls only what order.txt lists.
|
|
20
19
|
*/
|
|
21
20
|
import { realpathSync } from 'node:fs';
|
|
22
21
|
import { join, resolve } from 'node:path';
|
|
@@ -91,7 +90,7 @@ export function readInclude(name: string): string {
|
|
|
91
90
|
}
|
|
92
91
|
|
|
93
92
|
/**
|
|
94
|
-
* Parses includes/order.txt. A bare name is included and (by the
|
|
93
|
+
* Parses includes/order.txt. A bare name is included and (by the image's
|
|
95
94
|
* generator) pulled; a line starting with `-` is a deny marker - the name
|
|
96
95
|
* still has to resolve (an include that #includes it needs it on disk), but
|
|
97
96
|
* it is excluded from whatever build the caller pulls into a native table.
|