@amxts/core 0.2.0 → 0.2.2
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 +7 -6
- package/README.ru.md +7 -6
- package/as/events.ts +2 -2
- package/as/tsconfig.json +1 -0
- package/package.json +5 -5
- package/scripts/compile-cache.ts +4 -2
- package/scripts/docs/events.ts +2 -2
- package/scripts/prepare.ts +3 -0
- package/scripts/upgrade.ts +30 -3
- package/src/testing/index.ts +2 -1
- package/src/testing/server.ts +7 -1
- package/src/testing/setup.ts +1 -1
package/README.md
CHANGED
|
@@ -28,10 +28,10 @@ plugin.
|
|
|
28
28
|
`player.team == "CT"`, `player.hideHud.push("money")`,
|
|
29
29
|
`entity.renderMode = "additive"`.
|
|
30
30
|
- **Events as in the DOM.** `server.addEventListener("putInServer", ...)`,
|
|
31
|
-
`game.addEventListener("takeDamage", ...)` for the game's events (
|
|
31
|
+
`game.addEventListener("takeDamage", ...)` for the game's events (ReAPI's
|
|
32
32
|
hookchains and Ham Sandwich's functions), with
|
|
33
33
|
`event.preventDefault()` and an answer by `return`.
|
|
34
|
-
- **The editor knows the game.** Every native,
|
|
34
|
+
- **The editor knows the game.** Every native, ReAPI field and hookchain
|
|
35
35
|
comes with its type and a tooltip in English or Russian; a typo is a red
|
|
36
36
|
line, not a runtime error.
|
|
37
37
|
- **No import lines.** `Player`, `server`, `print` and the modules' names are
|
|
@@ -54,10 +54,11 @@ On the server:
|
|
|
54
54
|
`amxts_amxx_i386.so`, both tested on a real server. A plugin is compiled
|
|
55
55
|
for its server's system, which the build reads off the server's folder
|
|
56
56
|
(or `--os`).
|
|
57
|
-
- **ReHLDS with ReGameDLL and
|
|
58
|
-
on plain HLDS, where entity fields
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
- **ReHLDS with ReGameDLL and ReAPI** - recommended. amxts is tested on it and
|
|
58
|
+
on plain HLDS, where the entity fields work through AMX Mod X's own modules
|
|
59
|
+
and the game events come through Ham Sandwich, the game's log and its
|
|
60
|
+
messages: most of them after the game has acted, and a few of ReGameDLL's
|
|
61
|
+
not at all.
|
|
61
62
|
- **AMX Mod X 1.9** or later.
|
|
62
63
|
|
|
63
64
|
To write plugins: [Node.js](https://nodejs.org) 20.12+. The build runs on
|
package/README.ru.md
CHANGED
|
@@ -29,9 +29,9 @@ Mod X рядом с Pawn-плагинами. Они вызывают друг д
|
|
|
29
29
|
`entity.renderMode = "additive"`.
|
|
30
30
|
- **События как в DOM.** `server.addEventListener("putInServer", ...)`,
|
|
31
31
|
`game.addEventListener("takeDamage", ...)` для событий игры (хукчейнов
|
|
32
|
-
|
|
32
|
+
ReAPI и функций Ham Sandwich), с
|
|
33
33
|
`event.preventDefault()` и ответом через `return`.
|
|
34
|
-
- **Редактор знает игру.** Каждый натив, поле
|
|
34
|
+
- **Редактор знает игру.** Каждый натив, поле ReAPI и хукчейн — с типом и
|
|
35
35
|
подсказкой на русском или английском; опечатка — красная строка, а не
|
|
36
36
|
ошибка на сервере.
|
|
37
37
|
- **Без строк импорта.** `Player`, `server`, `print` и имена модулей
|
|
@@ -56,10 +56,11 @@ Mod X рядом с Pawn-плагинами. Они вызывают друг д
|
|
|
56
56
|
`amxts_amxx_i386.so`, оба проверены на настоящем сервере. Плагин
|
|
57
57
|
компилируется под систему своего сервера, которую сборка узнаёт по папке
|
|
58
58
|
сервера (или по `--os`).
|
|
59
|
-
- **ReHLDS с ReGameDLL и
|
|
60
|
-
на обычном HLDS, где поля сущностей
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
- **ReHLDS с ReGameDLL и ReAPI** — рекомендуется. amxts проверяется на нём и
|
|
60
|
+
на обычном HLDS, где поля сущностей работают через собственные модули AMX
|
|
61
|
+
Mod X, а события игры приходят через Ham Sandwich, лог игры и её сообщения:
|
|
62
|
+
большинство — когда игра уже сделала своё, а некоторые события ReGameDLL не
|
|
63
|
+
приходят вовсе.
|
|
63
64
|
- **AMX Mod X 1.9** или новее.
|
|
64
65
|
|
|
65
66
|
Для разработки плагинов: [Node.js](https://nodejs.org) 20.12+. Сборка работает
|
package/as/events.ts
CHANGED
|
@@ -68,7 +68,7 @@ export class ServerChangelevelEvent {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
|
-
* Every
|
|
71
|
+
* Every plugin has started: the moment to create forwards other plugins listen to. The configs run after it: read cvars in `"configsExecuted"`.
|
|
72
72
|
*
|
|
73
73
|
* Note: When this forward is called, most plugins should have registered their cvars and commands already.
|
|
74
74
|
*
|
|
@@ -2255,7 +2255,7 @@ export interface ServerEventMap {
|
|
|
2255
2255
|
*/
|
|
2256
2256
|
changeLevel: ServerChangelevelEvent;
|
|
2257
2257
|
/**
|
|
2258
|
-
* Every
|
|
2258
|
+
* Every plugin has started: the moment to create forwards other plugins listen to. The configs run after it: read cvars in `"configsExecuted"`.
|
|
2259
2259
|
*
|
|
2260
2260
|
* Pawn: `plugin_cfg`
|
|
2261
2261
|
*/
|
package/as/tsconfig.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amxts/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.2",
|
|
5
5
|
"description": "Counter-Strike 1.6 plugins in TypeScript: compiled ahead of time and run inside AMX Mod X, next to Pawn plugins.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "kukson777",
|
|
@@ -104,12 +104,12 @@
|
|
|
104
104
|
"assemblyscript": "0.28.20"
|
|
105
105
|
},
|
|
106
106
|
"optionalDependencies": {
|
|
107
|
-
"@amxts/wamrc-linux-x64": "^0.2.
|
|
108
|
-
"@amxts/wamrc-win32-x64": "^0.2.
|
|
107
|
+
"@amxts/wamrc-linux-x64": "^0.2.2",
|
|
108
|
+
"@amxts/wamrc-win32-x64": "^0.2.2"
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
|
111
|
-
"@amxts/config-core": "^0.1.
|
|
112
|
-
"@amxts/menu-core": "^0.2.
|
|
111
|
+
"@amxts/config-core": "^0.1.2",
|
|
112
|
+
"@amxts/menu-core": "^0.2.1",
|
|
113
113
|
"@e18e/eslint-plugin": "^0.8.1",
|
|
114
114
|
"@eslint-community/eslint-plugin-eslint-comments": "^4.8.1",
|
|
115
115
|
"@stylistic/eslint-plugin": "^5.10.0",
|
package/scripts/compile-cache.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Compiles kept on disk, reused while what they read is the same.
|
|
2
2
|
//
|
|
3
3
|
// A compile is keyed by everything that is not a file it read - the
|
|
4
|
-
// compiler, the hood's scripts, the
|
|
4
|
+
// compiler, the hood's scripts, the version the core builds as (a plugin
|
|
5
|
+
// carries it in its ABI), the flags, the project and its config - and
|
|
5
6
|
// stored with every file read it made (scripts/tracked-fs.ts): the entry, what
|
|
6
7
|
// it imports, the facade and the generated API, the module packages. It is
|
|
7
8
|
// taken again only while each of those reads sees the same thing it saw, so a
|
|
@@ -15,6 +16,7 @@ import type { Reads } from './tracked-fs';
|
|
|
15
16
|
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
16
17
|
import { dirname, join, resolve } from 'node:path';
|
|
17
18
|
import { fileURLToPath } from 'node:url';
|
|
19
|
+
import { coreVersion } from './build-identity';
|
|
18
20
|
import { listIncludes } from './includes';
|
|
19
21
|
import { currentProjectDir, loadProject } from './project';
|
|
20
22
|
import { hashOf, recordReads, unchanged } from './tracked-fs';
|
|
@@ -118,7 +120,7 @@ export function diskCache(dir: string | null, code: () => string, ownIncludes: s
|
|
|
118
120
|
let identity: string | null = null;
|
|
119
121
|
const fileOf = (parts: unknown[]) => {
|
|
120
122
|
identity ??= hashOf(`${FORMAT}\n${code()}`);
|
|
121
|
-
return join(dir!, `${hashOf(JSON.stringify([identity, projectIdentity(ownIncludes), ...parts]))}.json`);
|
|
123
|
+
return join(dir!, `${hashOf(JSON.stringify([identity, coreVersion(), projectIdentity(ownIncludes), ...parts]))}.json`);
|
|
122
124
|
};
|
|
123
125
|
|
|
124
126
|
let pruned = false;
|
package/scripts/docs/events.ts
CHANGED
|
@@ -53,8 +53,8 @@ export const EVENTS: Record<string, EventDoc> = {
|
|
|
53
53
|
},
|
|
54
54
|
plugin_cfg: {
|
|
55
55
|
summary: {
|
|
56
|
-
en: `Every
|
|
57
|
-
ru: `Все
|
|
56
|
+
en: `Every plugin has started: the moment to create forwards other plugins listen to. The configs run after it: read cvars in \`"configsExecuted"\`.`,
|
|
57
|
+
ru: `Все плагины запустились: момент создавать форварды для других плагинов. Конфиги выполняются после него: квары читайте в \`"configsExecuted"\`.`,
|
|
58
58
|
},
|
|
59
59
|
},
|
|
60
60
|
plugin_end: {
|
package/scripts/prepare.ts
CHANGED
|
@@ -115,6 +115,9 @@ const tsconfig = {
|
|
|
115
115
|
// plugin declares is its own, never a global another plugin's name
|
|
116
116
|
// collides with.
|
|
117
117
|
moduleDetection: 'force',
|
|
118
|
+
// `catch (error)` reads `error.message` as the compiler takes it: the
|
|
119
|
+
// base config's strict mode would make the caught value `unknown`.
|
|
120
|
+
useUnknownInCatchVariables: false,
|
|
118
121
|
paths,
|
|
119
122
|
},
|
|
120
123
|
include: [
|
package/scripts/upgrade.ts
CHANGED
|
@@ -30,11 +30,12 @@ import type { Kind } from './upgrade-names';
|
|
|
30
30
|
// with its title (scripts/upgrade-menus.ts). What is rewritten no longer
|
|
31
31
|
// matches, so a second run changes nothing.
|
|
32
32
|
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
33
|
-
import { join, relative, resolve } from 'node:path';
|
|
33
|
+
import { basename, dirname, join, relative, resolve } from 'node:path';
|
|
34
34
|
import { fileURLToPath } from 'node:url';
|
|
35
35
|
import ts from 'typescript';
|
|
36
36
|
import { MESSAGE_NAMES } from './client-messages';
|
|
37
37
|
import { CORE_ENTRIES, CORE_PLUGINS, loadProject } from './project';
|
|
38
|
+
import { apiFiles, serverFolder } from './system';
|
|
38
39
|
import { c, log } from './ui';
|
|
39
40
|
import { upgradeMenus } from './upgrade-menus';
|
|
40
41
|
import { COMMON, EVENTS, FLAG_NAMES, GAME_EVENT_FIELDS, HIDDEN, HIDDEN_EVENTS, JOIN_OPTIONS, RENAMED, SERVER_EVENT_CLASSES, SERVER_EVENT_FIELDS, SERVER_EVENTS, SERVER_EVENTS_BY_HAND, SERVER_FIELD_CLASSES, SERVER_GAME_EVENTS } from './upgrade-names';
|
|
@@ -774,15 +775,41 @@ export function upgradeFlags(file: string, text: string): { text: string; change
|
|
|
774
775
|
/** Folders that are not the project's code: what is installed, built or generated. */
|
|
775
776
|
const SKIP = new Set(['node_modules', 'dist', '.amxts', '.git']);
|
|
776
777
|
|
|
778
|
+
/** A server's addons/amxts: the module's files, written over on every start. */
|
|
779
|
+
const SERVER_FOLDER = /[\\/]addons[\\/]amxts$/i;
|
|
780
|
+
|
|
777
781
|
/** The project's TypeScript files: its plugins, its tests and fixtures, a module's sources. */
|
|
778
782
|
function codeFiles(dir: string, skip: Set<string>): string[] {
|
|
779
783
|
return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
|
780
784
|
const path = join(dir, entry.name);
|
|
781
|
-
if (entry.isDirectory()) return SKIP.has(entry.name) || skip.has(path) || entry.name.startsWith('.') ? [] : codeFiles(path, skip);
|
|
785
|
+
if (entry.isDirectory()) return SKIP.has(entry.name) || skip.has(path) || entry.name.startsWith('.') || SERVER_FOLDER.test(path) ? [] : codeFiles(path, skip);
|
|
782
786
|
return /\.(?:ts|mts|cts)$/.test(entry.name) ? [path] : [];
|
|
783
787
|
});
|
|
784
788
|
}
|
|
785
789
|
|
|
790
|
+
/** The server's addons/amxts that AMXTS_SERVER names, or '' when it names none. */
|
|
791
|
+
function serverDir(): string {
|
|
792
|
+
try {
|
|
793
|
+
const dir = serverFolder(process.env.AMXTS_SERVER ?? '');
|
|
794
|
+
return dir && resolve(dir);
|
|
795
|
+
} catch {
|
|
796
|
+
return '';
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
* The project's code to upgrade. The module's own files - the API a server
|
|
802
|
+
* writes beside its plugins, at the core's version it runs - are not, in the
|
|
803
|
+
* server's folder or a copy of one; a file of that name in the plugins
|
|
804
|
+
* folder is the author's.
|
|
805
|
+
*/
|
|
806
|
+
function projectFiles(dir: string, pluginsDir: string, outDir: string): string[] {
|
|
807
|
+
// The API at the top of as/, and the editor's globals: what the module
|
|
808
|
+
// writes beside the plugins (scripts/server-files.ts).
|
|
809
|
+
const theirs = new Set([...apiFiles(), 'imports.d.ts']);
|
|
810
|
+
return codeFiles(dir, new Set([outDir, serverDir()])).filter(file => !theirs.has(basename(file)) || dirname(file) === pluginsDir);
|
|
811
|
+
}
|
|
812
|
+
|
|
786
813
|
/** Rewrites the project in `dir`: every change, in the order of the files, and what is left to do by hand. `write: false` only lists them. */
|
|
787
814
|
export function upgradeProject(dir: string, { write = true } = {}): { changes: Change[]; left: Left[] } {
|
|
788
815
|
const project = loadProject(dir);
|
|
@@ -790,7 +817,7 @@ export function upgradeProject(dir: string, { write = true } = {}): { changes: C
|
|
|
790
817
|
const renames = renamesFor(project.modules, place => ownFolder && existsSync(join(project.pluginsDir, place)));
|
|
791
818
|
const changes: Change[] = [];
|
|
792
819
|
const left: Left[] = [];
|
|
793
|
-
for (const file of
|
|
820
|
+
for (const file of projectFiles(project.dir, resolve(project.pluginsDir), project.outDir)) {
|
|
794
821
|
const text = readFileSync(file, 'utf8');
|
|
795
822
|
const name = relative(project.dir, file).replace(/\\/g, '/');
|
|
796
823
|
const http = dropHttpImports(name, text);
|
package/src/testing/index.ts
CHANGED
|
@@ -26,7 +26,8 @@ export { constant } from './tables';
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Compiles a plugin (once per test run), loads it into a new fake server and
|
|
29
|
-
* starts the map: its top level runs, then plugin_init and
|
|
29
|
+
* starts the map: its top level runs, then plugin_init, plugin_cfg and
|
|
30
|
+
* OnConfigsExecuted.
|
|
30
31
|
*
|
|
31
32
|
* Several plugins go into one server as an array - they hear each other's
|
|
32
33
|
* forwards and natives, as on a real one.
|
package/src/testing/server.ts
CHANGED
|
@@ -826,11 +826,17 @@ export class FakeServer {
|
|
|
826
826
|
return plugin;
|
|
827
827
|
}
|
|
828
828
|
|
|
829
|
-
/**
|
|
829
|
+
/**
|
|
830
|
+
* What a map start sends, in AMX Mod X's order: plugin_precache,
|
|
831
|
+
* plugin_init, plugin_cfg, then OnAutoConfigsBuffered and
|
|
832
|
+
* OnConfigsExecuted, once the server has run its configs.
|
|
833
|
+
*/
|
|
830
834
|
start(): void {
|
|
831
835
|
this.fire('plugin_precache');
|
|
832
836
|
this.fire('plugin_init');
|
|
833
837
|
this.fire('plugin_cfg');
|
|
838
|
+
this.fire('OnAutoConfigsBuffered');
|
|
839
|
+
this.fire('OnConfigsExecuted');
|
|
834
840
|
}
|
|
835
841
|
|
|
836
842
|
// ------------------------------------------------------------ what a test reads
|
package/src/testing/setup.ts
CHANGED
|
@@ -27,7 +27,7 @@ export interface SetupOptions extends ServerOptions {
|
|
|
27
27
|
* `["welcome"]` - in this order; all of them when left out, none for `[]`.
|
|
28
28
|
*/
|
|
29
29
|
plugins?: string[];
|
|
30
|
-
/** Starts the map - plugin_init, then
|
|
30
|
+
/** Starts the map - plugin_init, plugin_cfg, then OnConfigsExecuted - once everything is loaded. True when left out. */
|
|
31
31
|
start?: boolean;
|
|
32
32
|
}
|
|
33
33
|
|