@amxts/resemiclip 0.1.0 → 0.1.1

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 CHANGED
@@ -50,14 +50,14 @@ Teammates walk through each other:
50
50
  semiclip.rule = (player, target) => player.team == target.team;
51
51
  ```
52
52
 
53
- Setting the rule is all it takes: the module works every pair out, and works a player's pairs out again when he spawns, dies, changes sides, comes or leaves. Setting `rule` takes the rules over from ReSemiclip's config; `semiclip.rule = null` gives them back, and so does the plugins' reload or a map change until a rule is set again.
53
+ Setting the rule is all it takes: the module works every pair out, and works a player's pairs out again when he spawns, dies, changes sides, comes or leaves. Setting `rule` takes the rules over from ReSemiclip's config; `semiclip.rule = null` gives them back, and so do the plugins' reload, a map change and the plugin that set the rule stopping - unloaded or reloaded - until a rule is set again.
54
54
 
55
55
  ### A rule that changes in play
56
56
 
57
57
  `spawnProtected` below is the plugin's own [field on `Player`](https://amxts.github.io/docs/game/players#shared-player-fields), declared with `declare module`: it starts `false`, every plugin on the server reads and writes it, and it is cleared when the player leaves. A player who has just spawned walks through everyone alive for 3 seconds, and teammates walk through each other:
58
58
 
59
59
  ```ts
60
- declare module "~/facade" {
60
+ declare module "@amxts/core" {
61
61
  interface Player {
62
62
  spawnProtected: boolean;
63
63
  }
package/README.ru.md CHANGED
@@ -50,14 +50,14 @@ export default defineConfig({
50
50
  semiclip.rule = (player, target) => player.team == target.team;
51
51
  ```
52
52
 
53
- Больше ничего не нужно: модуль рассчитывает каждую пару и заново рассчитывает пары игрока, когда тот появляется, умирает, меняет команду, входит или уходит. Присваивание `rule` забирает правила у конфига ReSemiclip; `semiclip.rule = null` возвращает их, и так же — перезагрузка плагинов или смена карты, пока правило не задано снова.
53
+ Больше ничего не нужно: модуль рассчитывает каждую пару и заново рассчитывает пары игрока, когда тот появляется, умирает, меняет команду, входит или уходит. Присваивание `rule` забирает правила у конфига ReSemiclip; `semiclip.rule = null` возвращает их, и так же — перезагрузка плагинов, смена карты и остановка плагина, который задал правило (его выгрузили или перезагрузили), пока правило не задано снова.
54
54
 
55
55
  ### Правило, которое меняется в игре
56
56
 
57
57
  `spawnProtected` ниже — собственное [поле плагина в `Player`](https://amxts.github.io/ru/docs/game/players#общие-поля-игрока), объявленное через `declare module`: сначала оно `false`, его читают и пишут все плагины сервера, а когда игрок уходит, оно сбрасывается. Только что появившийся игрок 3 секунды проходит сквозь всех живых, а союзники — сквозь друг друга:
58
58
 
59
59
  ```ts
60
- declare module "~/facade" {
60
+ declare module "@amxts/core" {
61
61
  interface Player {
62
62
  spawnProtected: boolean;
63
63
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@amxts/resemiclip",
3
3
  "type": "module",
4
- "version": "0.1.0",
4
+ "version": "0.1.1",
5
5
  "description": "Who walks through whom, for amxts plugins: the ReSemiclip module's rules as players, not bit masks.",
6
6
  "author": {
7
7
  "name": "kukson777",
@@ -40,7 +40,7 @@
40
40
  "lint:fix": "oxfmt && oxlint --fix --silent || oxlint --fix --silent || oxlint --fix"
41
41
  },
42
42
  "peerDependencies": {
43
- "@amxts/core": "^0.1.0"
43
+ "@amxts/core": "^0.2.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@e18e/eslint-plugin": "^0.8.1",
Binary file
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "format": 1,
3
3
  "module": "@amxts/resemiclip",
4
- "version": "0.1.0",
4
+ "version": "0.1.1",
5
5
  "from": {
6
6
  "@amxts/core": {
7
- "version": "0.1.0",
8
- "hash": "e3b12482fd1df1dcadee7e27a12ba915d97bf859"
7
+ "version": "0.2.0",
8
+ "hash": "86146344f98b3f7285b3307a254d359d7080ae7c"
9
9
  },
10
10
  "@amxts/resemiclip": {
11
- "version": "0.1.0",
12
- "hash": "788f84dd4fd47d0a1f7a96a5f4ad804a8f895045"
11
+ "version": "0.1.1",
12
+ "hash": "a1d17a605015e6566c550aff3796ab8fef8c0fd1"
13
13
  }
14
14
  },
15
15
  "options": {
@@ -22,8 +22,11 @@
22
22
  "entities.ts",
23
23
  "events.ts",
24
24
  "facade.ts",
25
+ "fetch.ts",
25
26
  "flags.ts",
27
+ "hlds.ts",
26
28
  "hooks.ts",
29
+ "kit.ts",
27
30
  "modules/resemiclip.ts",
28
31
  "natives.ts",
29
32
  "promise.ts",
@@ -39,13 +42,18 @@
39
42
  "systems": {
40
43
  "windows": {
41
44
  "file": "prebuilt/windows/resemiclip.aot",
42
- "size": 456628,
43
- "sha256": "059a43c784b8efd29580300cec70128cacf59f88f2b086711ac02dc7c6ef22db"
45
+ "size": 757502,
46
+ "sha256": "68baa44290f910b7c8106482d74d315364bda163a25072156b8975de437a5d55"
44
47
  },
45
48
  "linux": {
46
49
  "file": "prebuilt/linux/resemiclip.aot",
47
- "size": 463288,
48
- "sha256": "cbe969c8057a8f04b1b57a67548826b34d6c5bcf45d98523f8e049266a3cbbe1"
50
+ "size": 768642,
51
+ "sha256": "7267b8eae9880c2bf0bf02af8d06903706bb24fd9b54bb796bf132557cba2525"
49
52
  }
53
+ },
54
+ "surface": {
55
+ "proxy": "// GENERATED by scripts/shared-modules.ts: ~/modules/resemiclip in a plugin that does not own it.\n// Each function runs in resemiclip.aot, the one instance on the server.\nimport { Reader as __Reader, Writer as __Writer, beginCallback as __beginCallback, callBack as __callBack, receiveFunction as __receiveFunction, remoteTarget as __remoteTarget, sendFunction as __sendFunction, Service as __Service } from \"~/remote\";\nimport { Player as __Player } from \"~/facade\";\nimport { Player } from \"~/facade\";\n\nexport type SemiclipRule = (player: Player, target: Player) => boolean;\n\n/** Semiclip in resemiclip's plugin: each field is read and written there, each method runs there. */\nexport class Semiclip {\n\tconstructor(public __handle: i32) {}\n\n\tget rule(): ((a0: __Player, a1: __Player) => bool) | null {\n\t\tconst w = __service.begin(0);\n\t\tw.i32(this.__handle);\n\t\treturn __r0(__service.call(w));\n\t}\n\tset rule(value: ((a0: __Player, a1: __Player) => bool) | null) {\n\t\tconst w = __service.begin(1);\n\t\tw.i32(this.__handle);\n\t\t__w0(w, value);\n\t\t__service.call(w);\n\t}\n\n\tupdate(player?: Player): void {\n\t\tconst __w = __service.begin(2);\n\t\t__w.i32(this.__handle);\n\t\t__w2(__w, player);\n\t\tconst __r = __service.call(__w);\n\t}\n\n\tpassesThrough(player: Player): Array<__Player> {\n\t\tconst __w = __service.begin(3);\n\t\t__w.i32(this.__handle);\n\t\t__w3(__w, player);\n\t\tconst __r = __service.call(__w);\n\t\treturn __r4(__r);\n\t}\n}\n\nexport const semiclip = new Semiclip(1);\n\nconst __service = new __Service(\"resemiclip\", -273317570);\n\nfunction __w1(w: __Writer, v: (a0: __Player, a1: __Player) => bool): void { w.i32(__sendFunction(changetype<usize>(v), 0, __invoke)); }\n\nfunction __r1(r: __Reader): (a0: __Player, a1: __Player) => bool { return changetype<(a0: __Player, a1: __Player) => bool>(__receiveFunction(r, changetype<usize>(__stub0))); }\n\nfunction __w0(w: __Writer, v: ((a0: __Player, a1: __Player) => bool) | null): void {\n\tif (v == null) {\n\t\tw.bool(false);\n\t\treturn;\n\t}\n\tw.bool(true);\n\t__w1(w, v!);\n}\n\nfunction __r0(r: __Reader): ((a0: __Player, a1: __Player) => bool) | null {\n\tif (!r.bool()) return null;\n\treturn __r1(r);\n}\n\nfunction __w3(w: __Writer, v: __Player): void { w.i32(<i32>v.id); }\n\nfunction __r3(r: __Reader): __Player { return new __Player(r.i32()); }\n\nfunction __w2(w: __Writer, v: __Player | null): void {\n\tif (v == null) {\n\t\tw.bool(false);\n\t\treturn;\n\t}\n\tw.bool(true);\n\t__w3(w, v!);\n}\n\nfunction __r2(r: __Reader): __Player | null {\n\tif (!r.bool()) return null;\n\treturn __r3(r);\n}\n\nfunction __w4(w: __Writer, v: Array<__Player>): void {\n\tw.i32(v.length);\n\tfor (let i: i32 = 0; i < v.length; i++) __w3(w, v[i]);\n}\n\nfunction __r4(r: __Reader): Array<__Player> {\n\tconst count = r.i32();\n\tconst list = new Array<__Player>();\n\tfor (let i: i32 = 0; i < count; i++) list.push(__r3(r));\n\treturn list;\n}\n\nfunction __w5(w: __Writer, v: bool): void { w.bool(v); }\n\nfunction __r5(r: __Reader): bool { return r.bool(); }\n\nfunction __stub0(a0: __Player, a1: __Player): bool {\n\tconst target = __remoteTarget();\n\tconst w = __beginCallback(target);\n\t__w3(w, a0);\n\t__w3(w, a1);\n\tconst r = __callBack(target, w);\n\treturn __r5(r);\n}\n\nfunction __invoke(fn: usize, sig: i32, r: __Reader, w: __Writer): void {\n\tswitch (sig) {\n\t\tcase 0: {\n\t\t\tconst a0 = __r3(r);\n\t\t\tconst a1 = __r3(r);\n\t\t\tconst f = changetype<(a0: __Player, a1: __Player) => bool>(fn);\n\t\t\tconst result = f(a0, a1);\n\t\t\t__w5(w, result);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n",
56
+ "serve": "// GENERATED by scripts/shared-modules.ts: ~/modules/resemiclip, run by this plugin for every other.\nimport { Reader as __Reader, Writer as __Writer, beginCallback as __beginCallback, callBack as __callBack, receiveFunction as __receiveFunction, remoteTarget as __remoteTarget, sendFunction as __sendFunction, Handles as __Handles, serve as __serve } from \"~/remote\";\nimport * as __m from \"~/modules/resemiclip\";\nimport { Player as __Player } from \"~/facade\";\nimport { Semiclip as __M_Semiclip } from \"~/modules/resemiclip\";\n\nconst __handles = new __Handles();\n// The exported objects are handles 1, 2, ... - the numbers the proxies have.\n__handles.id(changetype<usize>(__m.semiclip));\n\nfunction __dispatch(op: i32, r: __Reader, w: __Writer): void {\n\tswitch (op) {\n\t\tcase 0: {\n\t\t\tconst o = __r0(r);\n\t\t\t__w1(w, o.rule);\n\t\t\tbreak;\n\t\t}\n\t\tcase 1: {\n\t\t\tconst o = __r0(r);\n\t\t\to.rule = __r1(r);\n\t\t\tbreak;\n\t\t}\n\t\tcase 2: {\n\t\t\tconst o = __r0(r);\n\t\t\tconst a0 = __r3(r);\n\t\t\to.update(a0);\n\t\t\tbreak;\n\t\t}\n\t\tcase 3: {\n\t\t\tconst o = __r0(r);\n\t\t\tconst a0 = __r4(r);\n\t\t\tconst result = o.passesThrough(a0);\n\t\t\t__w5(w, result);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nfunction __stub0(a0: __Player, a1: __Player): bool {\n\tconst target = __remoteTarget();\n\tconst w = __beginCallback(target);\n\t__w4(w, a0);\n\t__w4(w, a1);\n\tconst r = __callBack(target, w);\n\treturn __r6(r);\n}\n\nfunction __invoke(fn: usize, sig: i32, r: __Reader, w: __Writer): void {\n\tswitch (sig) {\n\t\tcase 0: {\n\t\t\tconst a0 = __r4(r);\n\t\t\tconst a1 = __r4(r);\n\t\t\tconst f = changetype<(a0: __Player, a1: __Player) => bool>(fn);\n\t\t\tconst result = f(a0, a1);\n\t\t\t__w6(w, result);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nfunction __w0(w: __Writer, v: __M_Semiclip): void { w.i32(__handles.id(changetype<usize>(v))); }\n\nfunction __r0(r: __Reader): __M_Semiclip { return changetype<__M_Semiclip>(__handles.at(r.i32())); }\n\nfunction __w2(w: __Writer, v: (a0: __Player, a1: __Player) => bool): void { w.i32(__sendFunction(changetype<usize>(v), 0, __invoke)); }\n\nfunction __r2(r: __Reader): (a0: __Player, a1: __Player) => bool { return changetype<(a0: __Player, a1: __Player) => bool>(__receiveFunction(r, changetype<usize>(__stub0))); }\n\nfunction __w1(w: __Writer, v: ((a0: __Player, a1: __Player) => bool) | null): void {\n\tif (v == null) {\n\t\tw.bool(false);\n\t\treturn;\n\t}\n\tw.bool(true);\n\t__w2(w, v!);\n}\n\nfunction __r1(r: __Reader): ((a0: __Player, a1: __Player) => bool) | null {\n\tif (!r.bool()) return null;\n\treturn __r2(r);\n}\n\nfunction __w4(w: __Writer, v: __Player): void { w.i32(<i32>v.id); }\n\nfunction __r4(r: __Reader): __Player { return new __Player(r.i32()); }\n\nfunction __w3(w: __Writer, v: __Player | null): void {\n\tif (v == null) {\n\t\tw.bool(false);\n\t\treturn;\n\t}\n\tw.bool(true);\n\t__w4(w, v!);\n}\n\nfunction __r3(r: __Reader): __Player | null {\n\tif (!r.bool()) return null;\n\treturn __r4(r);\n}\n\nfunction __w5(w: __Writer, v: Array<__Player>): void {\n\tw.i32(v.length);\n\tfor (let i: i32 = 0; i < v.length; i++) __w4(w, v[i]);\n}\n\nfunction __r5(r: __Reader): Array<__Player> {\n\tconst count = r.i32();\n\tconst list = new Array<__Player>();\n\tfor (let i: i32 = 0; i < count; i++) list.push(__r4(r));\n\treturn list;\n}\n\nfunction __w6(w: __Writer, v: bool): void { w.bool(v); }\n\nfunction __r6(r: __Reader): bool { return r.bool(); }\n\n__serve(\"resemiclip\", -273317570, __dispatch);\n",
57
+ "callbacks": true
50
58
  }
51
59
  }
Binary file
package/src/index.ts CHANGED
@@ -5,20 +5,22 @@
5
5
  * rule reads may have changed. How to use it: README.md.
6
6
  */
7
7
  import { ClientPutinserverEvent, Player, TeamInfoMessage, game, server } from "@amxts/core";
8
- import { LibType_Library } from "~/constants";
9
- import { LibraryExists, resemiclip_get_user_mask, resemiclip_set_user_mask, resemiclip_take_control } from "~/natives";
8
+ import { LibType_Library } from "@amxts/core/constants";
9
+ import { callingPlugin, onPluginStop } from "@amxts/core/kit";
10
+ import { LibraryExists, resemiclip_get_user_mask, resemiclip_set_user_mask, resemiclip_take_control } from "@amxts/core/natives";
10
11
 
11
12
  export default defineModule({
12
13
  meta: { name: "resemiclip" },
13
14
  imports: [{ from: "@amxts/resemiclip", name: "semiclip" }],
14
15
  setup() {
15
16
  server.addEventListener("init", start);
16
- server.addEventListener("putinserver", joined);
17
+ server.addEventListener("putInServer", joined);
17
18
  server.addEventListener("disconnected", event => left(event.player));
18
- server.addEventListener("message:TeamInfo", teamChanged);
19
- server.addEventListener("playerchange", event => changed(event.player));
19
+ server.addMessageListener("team", teamChanged);
20
+ server.addEventListener("playerChange", event => changed(event.player));
20
21
  game.addEventListener("spawn", event => changed(event.player), true);
21
22
  game.addEventListener("killed", event => changed(event.player), true);
23
+ onPluginStop(stopped);
22
24
  },
23
25
  });
24
26
 
@@ -29,6 +31,8 @@ export default defineModule({
29
31
  export type SemiclipRule = (player: Player, target: Player) => boolean;
30
32
 
31
33
  let current: SemiclipRule | null = null;
34
+ /** The plugin that set the rule, as `callingPlugin()` numbers it. */
35
+ let currentFrom = 0;
32
36
 
33
37
  /** The server is up. A rule set while the plugins are still loading waits for it. */
34
38
  let started = false;
@@ -73,6 +77,7 @@ export class Semiclip {
73
77
  set rule(rule: SemiclipRule | null) {
74
78
  if (rule != null && current != null && rule != current) console.warn("[ReSemiclip] a rule was set over another one: the last one set is used");
75
79
  current = rule;
80
+ currentFrom = callingPlugin();
76
81
  if (started) apply();
77
82
  }
78
83
 
@@ -95,13 +100,20 @@ export class Semiclip {
95
100
  */
96
101
  passesThrough(player: Player) {
97
102
  const mask = loaded() ? resemiclip_get_user_mask(player.id) : 0;
98
- return Player.all().filter(other => other.id != player.id && (mask & bitOf(other)) != 0);
103
+ return server.players.filter(other => other.id != player.id && (mask & bitOf(other)) != 0);
99
104
  }
100
105
  }
101
106
 
102
107
  /** Who walks through whom: the rule, the pairs worked out again, and what ReSemiclip has. */
103
108
  export const semiclip = new Semiclip();
104
109
 
110
+ /** The plugin that set the rule stopped: its rule goes, and ReSemiclip has the rules back until a rule is set again. */
111
+ function stopped(plugin: number) {
112
+ if (current == null || currentFrom != plugin) return;
113
+ current = null;
114
+ if (started) apply();
115
+ }
116
+
105
117
  function start() {
106
118
  started = true;
107
119
  apply();
@@ -142,18 +154,18 @@ function changed(player: Player) {
142
154
  function left(player: Player) {
143
155
  masks.delete(player.id);
144
156
  if (activeRule() == null) return;
145
- for (const other of Player.all()) {
157
+ for (const other of server.players) {
146
158
  if (other.id != player.id) tell(other, withBit(maskOf(other), player, false));
147
159
  }
148
160
  }
149
161
 
150
162
  function updateAll(rule: SemiclipRule) {
151
- const players = Player.all();
163
+ const players = server.players;
152
164
  for (const player of players) tell(player, maskFor(players.filter(other => other.id != player.id && rule(player, other))));
153
165
  }
154
166
 
155
167
  function updatePlayer(player: Player, rule: SemiclipRule) {
156
- const others = Player.all().filter(other => other.id != player.id);
168
+ const others = server.players.filter(other => other.id != player.id);
157
169
  tell(player, maskFor(others.filter(other => rule(player, other))));
158
170
  for (const other of others) tell(other, withBit(maskOf(other), player, rule(other, player)));
159
171
  }