@amxts/core 0.1.0 → 0.2.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.
Files changed (74) hide show
  1. package/README.md +18 -23
  2. package/README.ru.md +19 -22
  3. package/as/amxts.d.ts +63 -3
  4. package/as/constants.ts +684 -116
  5. package/as/entities.ts +1905 -1364
  6. package/as/events.ts +1694 -905
  7. package/as/facade.ts +1240 -220
  8. package/as/fetch.ts +1519 -0
  9. package/as/flags.ts +159 -145
  10. package/as/hlds.ts +1071 -0
  11. package/as/hooks.ts +5226 -5379
  12. package/as/kit.ts +15 -5
  13. package/as/lib/check.ts +1 -1
  14. package/as/natives.ts +2658 -2499
  15. package/as/remote.ts +39 -15
  16. package/as/tsconfig.json +6 -2
  17. package/as/vector.ts +12 -9
  18. package/includes/order.txt +22 -29
  19. package/includes/sources.json +0 -8
  20. package/node_modules/assemblyscript/std/assembly/index.d.ts +20 -11
  21. package/package.json +29 -7
  22. package/runtime/deps/assemblyscript/dist/asc.js +86 -16
  23. package/runtime/deps/assemblyscript/dist/assemblyscript.js +29 -29
  24. package/runtime/licenses/MPL-2.0.txt +373 -0
  25. package/runtime/licenses/README.md +5 -1
  26. package/runtime/licenses/curl-COPYING +22 -0
  27. package/runtime/licenses/libssh2-COPYING +43 -0
  28. package/runtime/licenses/mbedTLS-LICENSE +553 -0
  29. package/runtime/natives.txt +108 -105
  30. package/runtime/patches/assemblyscript-0.28.20-amxts.patch +752 -296
  31. package/runtime/patches/wamr-2.4.5-amxts.patch +148 -0
  32. package/scripts/apply-docs.ts +2 -2
  33. package/scripts/auto-imports.ts +2 -2
  34. package/scripts/build-identity.ts +115 -0
  35. package/scripts/build-wasm.ts +101 -50
  36. package/scripts/check.ts +17 -3
  37. package/scripts/client-messages.ts +246 -0
  38. package/scripts/compile-pool.ts +128 -0
  39. package/scripts/compile-worker.ts +23 -0
  40. package/scripts/compile.ts +156 -59
  41. package/scripts/docker-server.ts +13 -3
  42. package/scripts/docs/as/amxts.ts +86 -0
  43. package/scripts/docs/as/facade.ts +688 -188
  44. package/scripts/docs/as/fetch.ts +805 -0
  45. package/scripts/docs/entities.ts +43 -144
  46. package/scripts/docs/events.ts +15 -26
  47. package/scripts/docs/game.ts +68 -22
  48. package/scripts/docs/messages.ts +330 -16
  49. package/scripts/editor-api.ts +101 -0
  50. package/scripts/hlds-events.ts +370 -0
  51. package/scripts/includes.ts +12 -10
  52. package/scripts/player-fields.ts +16 -15
  53. package/scripts/prebuilt.ts +65 -23
  54. package/scripts/prepare.ts +39 -28
  55. package/scripts/project.ts +120 -20
  56. package/scripts/reapi-events.ts +98 -0
  57. package/scripts/shared-modules.ts +85 -23
  58. package/scripts/source-map.ts +242 -0
  59. package/scripts/system.ts +1 -1
  60. package/scripts/typed-commands.ts +263 -0
  61. package/scripts/typed-configs.ts +23 -12
  62. package/scripts/ui.ts +3 -1
  63. package/scripts/upgrade-menus.ts +274 -0
  64. package/scripts/upgrade-names.ts +384 -0
  65. package/scripts/upgrade.ts +830 -0
  66. package/src/cli-api.mjs +37 -4
  67. package/src/system.mjs +74 -3
  68. package/src/testing/compile.ts +8 -5
  69. package/src/testing/natives.ts +199 -5
  70. package/src/testing/network.ts +531 -0
  71. package/src/testing/server.ts +565 -47
  72. package/src/testing/tables.ts +25 -0
  73. package/as/modules/http.ts +0 -184
  74. package/scripts/docs/as/modules/http.ts +0 -66
@@ -102,7 +102,7 @@ export default {
102
102
  unique within the plugin. \`fallback\` is the answer when the handler returns
103
103
  nothing: \`0\` for most natives, \`1\` where the native expects the event handled.
104
104
 
105
- Register from the \`"cfg"\` event, not at the top of the file: a console
105
+ Register from the \`"pluginsLoaded"\` event, not at the top of the file: a console
106
106
  command registered that early (\`register_concmd\`, \`register_srvcmd\`) crashes
107
107
  the server when typed.
108
108
  `,
@@ -121,7 +121,7 @@ export default {
121
121
  имя, уникальное в пределах плагина. \`fallback\` — ответ, если обработчик
122
122
  ничего не вернул: \`0\` почти везде, \`1\` там, где натив ждёт обработанное событие.
123
123
 
124
- Регистрируйте из события \`"cfg"\`, а не с верхнего уровня файла: консольная
124
+ Регистрируйте из события \`"pluginsLoaded"\`, а не с верхнего уровня файла: консольная
125
125
  команда, зарегистрированная так рано (\`register_concmd\`, \`register_srvcmd\`),
126
126
  роняет сервер, когда её вводят.
127
127
  `,
@@ -375,8 +375,8 @@ export default {
375
375
  ru: `Читает строковый аргумент, который широкий обработчик получил числом.`,
376
376
  },
377
377
  'cellsToString': {
378
- en: `Reads the text a raw native from \`~/natives\` wrote into a cell array. \`stringToCells\` is the other way.`,
379
- ru: `Читает текст, который сырой натив из \`~/natives\` записал в массив ячеек. Обратно — \`stringToCells\`.`,
378
+ en: `Reads the text a raw native from \`@amxts/core/natives\` wrote into a cell array. \`stringToCells\` is the other way.`,
379
+ ru: `Читает текст, который сырой натив из \`@amxts/core/natives\` записал в массив ячеек. Обратно — \`stringToCells\`.`,
380
380
  },
381
381
  'stringToCells': {
382
382
  en: `Writes text into a cell array as a Pawn string, for a raw native.`,
@@ -384,7 +384,7 @@ export default {
384
384
  },
385
385
  'cells': {
386
386
  en: `
387
- Passes a string to a raw native from \`~/natives\` without declaring a
387
+ Passes a string to a raw native from \`@amxts/core/natives\` without declaring a
388
388
  buffer for it:
389
389
 
390
390
  cfg_set_base_dir(cells("myplugin"));
@@ -393,7 +393,7 @@ export default {
393
393
  arguments going in: a native that writes text back needs \`out()\`.
394
394
  `,
395
395
  ru: `
396
- Передаёт строку сырому нативу из \`~/natives\` без объявления буфера под неё:
396
+ Передаёт строку сырому нативу из \`@amxts/core/natives\` без объявления буфера под неё:
397
397
 
398
398
  cfg_set_base_dir(cells("myplugin"));
399
399
 
@@ -522,6 +522,10 @@ export default {
522
522
  en: `A Counter-Strike team, by the name the game gives it: one of \`"TERRORIST"\`, \`"CT"\`, \`"SPECTATOR"\`, \`"UNASSIGNED"\`.`,
523
523
  ru: `Команда Counter-Strike под именем, которое даёт ей игра: одно из \`"TERRORIST"\`, \`"CT"\`, \`"SPECTATOR"\`, \`"UNASSIGNED"\`.`,
524
524
  },
525
+ 'AuthType': {
526
+ en: `The way a player's game proves who he is, as Reunion tells it, e.g. \`"steam"\` or \`"revEmu"\`; \`"unknown"\` on a server without Reunion.`,
527
+ ru: `Способ, которым игра игрока подтверждает, кто он, по словам Reunion, например \`"steam"\` или \`"revEmu"\`; \`"unknown"\` на сервере без Reunion.`,
528
+ },
525
529
  'WeaponName': {
526
530
  en: `A weapon a player can hold, by its class name, e.g. \`"weapon_ak47"\` or \`"weapon_knife"\`.`,
527
531
  ru: `Оружие, которое может держать игрок, по имени класса, например \`"weapon_ak47"\` или \`"weapon_knife"\`.`,
@@ -530,36 +534,6 @@ export default {
530
534
  en: `An item \`player.give\` hands over: a weapon, armour (\`"item_kevlar"\`, \`"item_assaultsuit"\`) or the defuse kit (\`"item_thighpack"\`).`,
531
535
  ru: `Предмет, который выдаёт \`player.give\`: оружие, броня (\`"item_kevlar"\`, \`"item_assaultsuit"\`) или набор сапёра (\`"item_thighpack"\`).`,
532
536
  },
533
- 'PlayerFilter': {
534
- en: `
535
- The filter of \`Player.all\`; every field is optional, e.g.
536
- \`Player.all({ alive: true, team: "CT" })\`.
537
- `,
538
- ru: `
539
- Фильтр \`Player.all\`; все поля необязательны, например
540
- \`Player.all({ alive: true, team: "CT" })\`.
541
- `,
542
- },
543
- 'PlayerFilter.alive': {
544
- en: `Only living players.`,
545
- ru: `Только живые игроки.`,
546
- },
547
- 'PlayerFilter.dead': {
548
- en: `Only dead players.`,
549
- ru: `Только мёртвые игроки.`,
550
- },
551
- 'PlayerFilter.team': {
552
- en: `Only players of this team, e.g. \`"CT"\`.`,
553
- ru: `Только игроки этой команды, например \`"CT"\`.`,
554
- },
555
- 'PlayerFilter.bots': {
556
- en: `Only bots.`,
557
- ru: `Только боты.`,
558
- },
559
- 'PlayerFilter.humans': {
560
- en: `Only people, no bots.`,
561
- ru: `Только люди, без ботов.`,
562
- },
563
537
  'ModuleName': {
564
538
  en: `An AMX Mod X module a plugin can check for, one of \`"reapi"\`, \`"cstrike"\`, \`"fun"\`, \`"hamsandwich"\`, \`"engine"\`, \`"fakemeta"\`.`,
565
539
  ru: `Модуль AMX Mod X, наличие которого плагин может проверить, — одно из \`"reapi"\`, \`"cstrike"\`, \`"fun"\`, \`"hamsandwich"\`, \`"engine"\`, \`"fakemeta"\`.`,
@@ -586,25 +560,59 @@ export default {
586
560
  en: `Keeps the player's frags: no penalty for the suicide.`,
587
561
  ru: `Фраги игрока не меняются: штрафа за самоубийство нет.`,
588
562
  },
563
+ 'MoveOptions': {
564
+ en: `
565
+ One move of a bot, \`bot.move({ ... })\`: the speeds are units a second, as
566
+ a player's keys give them - \`250\` runs with a knife, \`-250\` backs away.
567
+ `,
568
+ ru: `
569
+ Один шаг бота, \`bot.move({ ... })\`: скорости — в единицах в секунду, как их
570
+ дают клавиши игрока: \`250\` — бег с ножом, \`-250\` — назад.
571
+ `,
572
+ },
573
+ 'MoveOptions.forward': {
574
+ en: `Forward, or back when negative.`,
575
+ ru: `Вперёд, или назад, если число отрицательное.`,
576
+ },
577
+ 'MoveOptions.side': {
578
+ en: `To the right, or to the left when negative.`,
579
+ ru: `Вправо, или влево, если число отрицательное.`,
580
+ },
581
+ 'MoveOptions.up': {
582
+ en: `Up, or down when negative: swimming and climbing a ladder.`,
583
+ ru: `Вверх, или вниз, если число отрицательное: в воде и на лестнице.`,
584
+ },
585
+ 'MoveOptions.buttons': {
586
+ en: `The buttons held during the move: \`["jump", "duck"]\`.`,
587
+ ru: `Кнопки, зажатые на время шага: \`["jump", "duck"]\`.`,
588
+ },
589
+ 'MoveOptions.angles': {
590
+ en: `The direction the bot looks in, \`[pitch, yaw, roll]\` or a Vector; where it looks now when left out.`,
591
+ ru: `Направление взгляда бота, \`[pitch, yaw, roll]\` или Vector; если не задано — куда он смотрит сейчас.`,
592
+ },
593
+ 'MoveOptions.msec': {
594
+ en: `The move's length in milliseconds, \`1\` to \`255\`; the server frame's time when left out.`,
595
+ ru: `Длительность шага в миллисекундах, от \`1\` до \`255\`; если не задано — время кадра сервера.`,
596
+ },
589
597
  'Client': {
590
598
  en: `
591
- A connecting player, in \`"connect"\`, \`"authorized"\` and \`"putinserver"\`: name,
599
+ A connecting player, in \`"connect"\`, \`"authorized"\` and \`"putInServer"\`: name,
592
600
  address, SteamID and team, but no health or weapons yet. Every Player is a
593
601
  Client too.
594
602
 
595
603
  \`\`\`ts
596
- server.addEventListener("putinserver", (event) => {
604
+ server.addEventListener("putInServer", (event) => {
597
605
  print(event.player, \`Welcome, \${event.player.name}!\`);
598
606
  });
599
607
  \`\`\`
600
608
  `,
601
609
  ru: `
602
- Подключающийся игрок — в \`"connect"\`, \`"authorized"\` и \`"putinserver"\`: имя,
610
+ Подключающийся игрок — в \`"connect"\`, \`"authorized"\` и \`"putInServer"\`: имя,
603
611
  адрес, SteamID и команда, но ещё без здоровья и оружия. Любой Player — тоже
604
612
  Client.
605
613
 
606
614
  \`\`\`ts
607
- server.addEventListener("putinserver", (event) => {
615
+ server.addEventListener("putInServer", (event) => {
608
616
  print(event.player, \`Welcome, \${event.player.name}!\`);
609
617
  });
610
618
  \`\`\`
@@ -622,9 +630,21 @@ export default {
622
630
  en: `The player's IP address without the port, e.g. \`"192.168.0.10"\`.`,
623
631
  ru: `IP-адрес игрока без порта, например \`"192.168.0.10"\`.`,
624
632
  },
625
- 'Client.authid': {
626
- en: `The player's SteamID, e.g. \`"STEAM_0:1:12345"\`. A bot has \`"BOT"\`, HLTV has \`"HLTV"\`; until Steam confirms the player it is \`"STEAM_ID_PENDING"\` (wait for the \`"authorized"\` event), and on a LAN server \`"STEAM_ID_LAN"\`.`,
627
- ru: `SteamID игрока, например \`"STEAM_0:1:12345"\`. У бота — \`"BOT"\`, у HLTV — \`"HLTV"\`; пока Steam не подтвердил игрока — \`"STEAM_ID_PENDING"\` (дождитесь события \`"authorized"\`), на LAN-сервере — \`"STEAM_ID_LAN"\`.`,
633
+ 'Client.steamId': {
634
+ en: `The player's SteamID, e.g. \`"STEAM_0:1:12345"\`. A bot has \`"BOT"\`, HLTV has \`"HLTV"\`; until Steam confirms the player it is \`"STEAM_ID_PENDING"\` (wait for the \`"authorized"\` event), and on a LAN server \`"STEAM_ID_LAN"\`. With Reunion a game without Steam gets one made from its key (\`authKey\`): \`"STEAM_..."\` or \`"VALVE_..."\`, as the server's Reunion settings say.`,
635
+ ru: `SteamID игрока, например \`"STEAM_0:1:12345"\`. У бота — \`"BOT"\`, у HLTV — \`"HLTV"\`; пока Steam не подтвердил игрока — \`"STEAM_ID_PENDING"\` (дождитесь события \`"authorized"\`), на LAN-сервере — \`"STEAM_ID_LAN"\`. С Reunion игра без Steam получает SteamID, сделанный из её ключа (\`authKey\`): \`"STEAM_..."\` или \`"VALVE_..."\`, как скажут настройки Reunion на сервере.`,
636
+ },
637
+ 'Client.authType': {
638
+ en: `The way the player's game proved who he is, as Reunion tells it: one of \`"steam"\` (a Steam game), \`"steamEmu"\`, \`"revEmu"\`, \`"revEmu2013"\`, \`"oldRevEmu"\`, \`"sc2009"\`, \`"avsmp"\`, \`"sxei"\`, \`"sse3"\` (a game without Steam, by the emulator it proved itself with), \`"dproto"\`, \`"hltv"\`, or \`"unknown"\` on a server without Reunion.`,
639
+ ru: `Способ, которым игра игрока подтвердила, кто он, по словам Reunion: одно из \`"steam"\` (игра из Steam), \`"steamEmu"\`, \`"revEmu"\`, \`"revEmu2013"\`, \`"oldRevEmu"\`, \`"sc2009"\`, \`"avsmp"\`, \`"sxei"\`, \`"sse3"\` (игра без Steam — по эмулятору, которым она подтвердила себя), \`"dproto"\`, \`"hltv"\` или \`"unknown"\` на сервере без Reunion.`,
640
+ },
641
+ 'Client.protocol': {
642
+ en: `The network protocol of the player's game: \`48\` for today's game, \`47\` for an old one Reunion lets in. \`0\` on a server without Reunion.`,
643
+ ru: `Сетевой протокол игры игрока: \`48\` у нынешней игры, \`47\` у старой, которую пускает Reunion. \`0\` на сервере без Reunion.`,
644
+ },
645
+ 'Client.authKey': {
646
+ en: `The key the player's game proved itself with, as Reunion read it: what his SteamID is made from. \`""\` on a server without Reunion.`,
647
+ ru: `Ключ, которым игра игрока подтвердила себя, как его прочитал Reunion: из него сделан SteamID игрока. \`""\` на сервере без Reunion.`,
628
648
  },
629
649
  'Client.isBot': {
630
650
  en: `\`true\` for a bot.`,
@@ -635,8 +655,8 @@ export default {
635
655
  ru: `\`true\`, пока игрок на сервере.`,
636
656
  },
637
657
  'Client.access': {
638
- en: `The player's admin rights, from the letters in \`users.ini\`: \`client.access.includes("Cvar")\`.`,
639
- ru: `Права админа у игрока — по буквам из \`users.ini\`: \`client.access.includes("Cvar")\`.`,
658
+ en: `The player's admin rights, from the letters in \`users.ini\`: \`client.access.includes("cvar")\`.`,
659
+ ru: `Права админа у игрока — по буквам из \`users.ini\`: \`client.access.includes("cvar")\`.`,
640
660
  },
641
661
  'Client.team': {
642
662
  en: `The player's team, one of \`"TERRORIST"\`, \`"CT"\`, \`"SPECTATOR"\` or \`"UNASSIGNED"\` (until the player joins a team). Setting it moves the player, as \`player.team\` does.`,
@@ -679,36 +699,17 @@ export default {
679
699
  A player in the game: everything a Client has, plus health, armor, frags,
680
700
  weapons and the screen.
681
701
 
682
- An event about a player gives one as \`event.player\`; \`Player.all()\`
702
+ An event about a player gives one as \`event.player\`; \`server.players\`
683
703
  lists everyone on the server.
684
704
  `,
685
705
  ru: `
686
706
  Игрок в игре: всё, что есть у Client, а также здоровье, броня, фраги,
687
707
  оружие и экран.
688
708
 
689
- Событие об игроке передаёт его как \`event.player\`; \`Player.all()\`
709
+ Событие об игроке передаёт его как \`event.player\`; \`server.players\`
690
710
  возвращает всех на сервере.
691
711
  `,
692
712
  },
693
- 'Player.all': {
694
- en: `
695
- The players on the server: \`Player.all({ alive: true })\`.
696
-
697
- Every field narrows: \`{ bots: true }\` is bots only, \`{ humans: true }\`
698
- people only. Without a filter, everyone connected, never an HLTV proxy.
699
-
700
- Pawn: \`get_players\`
701
- `,
702
- ru: `
703
- Игроки на сервере: \`Player.all({ alive: true })\`.
704
-
705
- Каждое поле сужает выборку: \`{ bots: true }\` — только боты,
706
- \`{ humans: true }\` — только люди. Без фильтра — все подключённые, кроме
707
- HLTV-прокси.
708
-
709
- Pawn: \`get_players\`
710
- `,
711
- },
712
713
  'Player.name': {
713
714
  en: `
714
715
  The player's name.
@@ -796,18 +797,54 @@ export default {
796
797
  Pawn: \`get_user_ip\`
797
798
  `,
798
799
  },
799
- 'Player.authid': {
800
+ 'Player.steamId': {
800
801
  en: `
801
- The player's SteamID, e.g. \`"STEAM_0:1:12345"\`. A bot has \`"BOT"\`, HLTV has \`"HLTV"\`; until Steam confirms the player it is \`"STEAM_ID_PENDING"\` (wait for the \`"authorized"\` event), and on a LAN server \`"STEAM_ID_LAN"\`.
802
+ The player's SteamID, e.g. \`"STEAM_0:1:12345"\`. A bot has \`"BOT"\`, HLTV has \`"HLTV"\`; until Steam confirms the player it is \`"STEAM_ID_PENDING"\` (wait for the \`"authorized"\` event), and on a LAN server \`"STEAM_ID_LAN"\`. With Reunion a game without Steam gets one made from its key (\`authKey\`): \`"STEAM_..."\` or \`"VALVE_..."\`, as the server's Reunion settings say.
802
803
 
803
804
  Pawn: \`get_user_authid\`
804
805
  `,
805
806
  ru: `
806
- SteamID игрока, например \`"STEAM_0:1:12345"\`. У бота — \`"BOT"\`, у HLTV — \`"HLTV"\`; пока Steam не подтвердил игрока — \`"STEAM_ID_PENDING"\` (дождитесь события \`"authorized"\`), на LAN-сервере — \`"STEAM_ID_LAN"\`.
807
+ SteamID игрока, например \`"STEAM_0:1:12345"\`. У бота — \`"BOT"\`, у HLTV — \`"HLTV"\`; пока Steam не подтвердил игрока — \`"STEAM_ID_PENDING"\` (дождитесь события \`"authorized"\`), на LAN-сервере — \`"STEAM_ID_LAN"\`. С Reunion игра без Steam получает SteamID, сделанный из её ключа (\`authKey\`): \`"STEAM_..."\` или \`"VALVE_..."\`, как скажут настройки Reunion на сервере.
807
808
 
808
809
  Pawn: \`get_user_authid\`
809
810
  `,
810
811
  },
812
+ 'Player.authType': {
813
+ en: `
814
+ The way the player's game proved who he is, as Reunion tells it: one of \`"steam"\` (a Steam game), \`"steamEmu"\`, \`"revEmu"\`, \`"revEmu2013"\`, \`"oldRevEmu"\`, \`"sc2009"\`, \`"avsmp"\`, \`"sxei"\`, \`"sse3"\` (a game without Steam, by the emulator it proved itself with), \`"dproto"\`, \`"hltv"\`, or \`"unknown"\` on a server without Reunion.
815
+
816
+ Pawn: \`REU_GetAuthtype\`
817
+ `,
818
+ ru: `
819
+ Способ, которым игра игрока подтвердила, кто он, по словам Reunion: одно из \`"steam"\` (игра из Steam), \`"steamEmu"\`, \`"revEmu"\`, \`"revEmu2013"\`, \`"oldRevEmu"\`, \`"sc2009"\`, \`"avsmp"\`, \`"sxei"\`, \`"sse3"\` (игра без Steam — по эмулятору, которым она подтвердила себя), \`"dproto"\`, \`"hltv"\` или \`"unknown"\` на сервере без Reunion.
820
+
821
+ Pawn: \`REU_GetAuthtype\`
822
+ `,
823
+ },
824
+ 'Player.protocol': {
825
+ en: `
826
+ The network protocol of the player's game: \`48\` for today's game, \`47\` for an old one Reunion lets in. \`0\` on a server without Reunion.
827
+
828
+ Pawn: \`REU_GetProtocol\`
829
+ `,
830
+ ru: `
831
+ Сетевой протокол игры игрока: \`48\` у нынешней игры, \`47\` у старой, которую пускает Reunion. \`0\` на сервере без Reunion.
832
+
833
+ Pawn: \`REU_GetProtocol\`
834
+ `,
835
+ },
836
+ 'Player.authKey': {
837
+ en: `
838
+ The key the player's game proved itself with, as Reunion read it: what his SteamID is made from. \`""\` on a server without Reunion.
839
+
840
+ Pawn: \`REU_GetAuthKey\`
841
+ `,
842
+ ru: `
843
+ Ключ, которым игра игрока подтвердила себя, как его прочитал Reunion: из него сделан SteamID игрока. \`""\` на сервере без Reunion.
844
+
845
+ Pawn: \`REU_GetAuthKey\`
846
+ `,
847
+ },
811
848
  'Player.isAlive': {
812
849
  en: `
813
850
  \`true\` while the player is alive.
@@ -888,7 +925,8 @@ export default {
888
925
  Joins a side the way the game joins a player who picks it in the team
889
926
  menu, appearance picked for him: \`player.joinTeam("CT")\`. A player who
890
927
  has just arrived is in the game after it and can spawn, which
891
- \`player.team = ...\` does not do for him. \`false\` if the game refused.
928
+ \`player.team = ...\` does not do for him. A living player sent to the
929
+ spectators dies quietly: no death, no frag. \`false\` if the game refused.
892
930
 
893
931
  Pawn: \`rg_join_team\`
894
932
  `,
@@ -896,7 +934,8 @@ export default {
896
934
  Вводит игрока в сторону так, как игра вводит того, кто выбрал её в меню
897
935
  команд, а внешность выбирается за него: \`player.joinTeam("CT")\`. Только
898
936
  что пришедший игрок после этого в игре и может появиться, чего
899
- \`player.team = ...\` для него не делает. \`false\`, если игра отказала.
937
+ \`player.team = ...\` для него не делает. Живой игрок, отправленный в
938
+ зрители, тихо умирает: без смерти и без фрага. \`false\`, если игра отказала.
900
939
 
901
940
  Pawn: \`rg_join_team\`
902
941
  `,
@@ -1086,13 +1125,13 @@ export default {
1086
1125
  'Player.access': {
1087
1126
  en: `
1088
1127
  The player's admin rights, from the letters in \`users.ini\`:
1089
- \`player.access.includes("Cvar")\`.
1128
+ \`player.access.includes("cvar")\`.
1090
1129
 
1091
1130
  Pawn: \`get_user_flags\`
1092
1131
  `,
1093
1132
  ru: `
1094
1133
  Права админа у игрока — по буквам из \`users.ini\`:
1095
- \`player.access.includes("Cvar")\`.
1134
+ \`player.access.includes("cvar")\`.
1096
1135
 
1097
1136
  Pawn: \`get_user_flags\`
1098
1137
  `,
@@ -1160,23 +1199,19 @@ export default {
1160
1199
  'playerIds': {
1161
1200
  en: `
1162
1201
  The ids of the players on the server, as an array. \`flags\`: \`"a"\` living,
1163
- \`"b"\` dead, \`"c"\` no bots, \`"h"\` no HLTV, \`"e"\` only \`team\`. \`Player.all\` does the
1164
- same with readable options.
1202
+ \`"b"\` dead, \`"c"\` no bots, \`"h"\` no HLTV, \`"e"\` only \`team\`. \`server.players\` is
1203
+ everyone, as players, to filter as an array.
1165
1204
 
1166
1205
  Pawn: \`get_players\`
1167
1206
  `,
1168
1207
  ru: `
1169
1208
  \`id\` игроков на сервере в виде массива. \`flags\`: \`"a"\` живые, \`"b"\` мёртвые,
1170
- \`"c"\` без ботов, \`"h"\` без HLTV, \`"e"\` только \`team\`. \`Player.all\` делает то
1171
- же с понятными полями.
1209
+ \`"c"\` без ботов, \`"h"\` без HLTV, \`"e"\` только \`team\`. \`server.players\` — все,
1210
+ как игроки, их фильтруют как массив.
1172
1211
 
1173
1212
  Pawn: \`get_players\`
1174
1213
  `,
1175
1214
  },
1176
- 'CommandHandler': {
1177
- en: `A command's handler: gets the player who typed it and the words after the command's name.`,
1178
- ru: `Обработчик команды: получает игрока, который её набрал, и слова после имени команды.`,
1179
- },
1180
1215
  'CommandOptions': {
1181
1216
  en: `The options of a command: who may use it and its description in a listing.`,
1182
1217
  ru: `Параметры команды: кому она доступна и её описание в списке.`,
@@ -1186,27 +1221,23 @@ export default {
1186
1221
  ru: `Право админа, которое нужно игроку для команды; если не указано, команда доступна всем.`,
1187
1222
  },
1188
1223
  'CommandOptions.description': {
1189
- en: `The command's description, shown by \`amx_help\` and the like.`,
1190
- ru: `Описание команды, которое показывают \`amx_help\` и подобные.`,
1224
+ en: `The command's description, shown by \`amx_help\` and in \`server.commands\`.`,
1225
+ ru: `Описание команды, которое показывают \`amx_help\` и \`server.commands\`.`,
1191
1226
  },
1192
1227
  'accessOf': {
1193
1228
  en: `
1194
1229
  Converts \`users.ini\` letters to rights: \`accessOf("abc")\` is
1195
- [\`"Immunity"\`, \`"Reservation"\`, \`"Kick"\`]. An unknown letter is skipped.
1230
+ [\`"immunity"\`, \`"reservation"\`, \`"kick"\`]. An unknown letter is skipped.
1196
1231
 
1197
1232
  Pawn: \`read_flags\`
1198
1233
  `,
1199
1234
  ru: `
1200
1235
  Переводит буквы из \`users.ini\` в права: \`accessOf("abc")\` —
1201
- [\`"Immunity"\`, \`"Reservation"\`, \`"Kick"\`]. Неизвестные буквы пропускаются.
1236
+ [\`"immunity"\`, \`"reservation"\`, \`"kick"\`]. Неизвестные буквы пропускаются.
1202
1237
 
1203
1238
  Pawn: \`read_flags\`
1204
1239
  `,
1205
1240
  },
1206
- 'ServerCommandHandler': {
1207
- en: `A server command's handler: gets the words after the command's name.`,
1208
- ru: `Обработчик серверной команды: получает слова после имени команды.`,
1209
- },
1210
1241
  'HudOptions': {
1211
1242
  en: `
1212
1243
  The look of a HUD message. Every field has a default, so
@@ -1356,8 +1387,8 @@ export default {
1356
1387
  or a text, as the message wrote it.
1357
1388
 
1358
1389
  \`\`\`ts
1359
- server.addEventListener("message:TeamScore", (event) => {
1360
- console.log(\`\${event.args.text(0)} \${event.args.number(1)}\`);
1390
+ server.addMessageListener("botProgress", (event) => {
1391
+ console.log(\`\${event.args.length} \${event.args.number(0)}\`);
1361
1392
  });
1362
1393
  \`\`\`
1363
1394
 
@@ -1368,8 +1399,8 @@ export default {
1368
1399
  записало сообщение.
1369
1400
 
1370
1401
  \`\`\`ts
1371
- server.addEventListener("message:TeamScore", (event) => {
1372
- console.log(\`\${event.args.text(0)} \${event.args.number(1)}\`);
1402
+ server.addMessageListener("botProgress", (event) => {
1403
+ console.log(\`\${event.args.length} \${event.args.number(0)}\`);
1373
1404
  });
1374
1405
  \`\`\`
1375
1406
 
@@ -1406,14 +1437,15 @@ export default {
1406
1437
  HUD icon - heard on its way, before it leaves:
1407
1438
 
1408
1439
  \`\`\`ts
1409
- server.addEventListener("message:TextMsg", (event) => {
1440
+ server.addMessageListener("text", (event) => {
1410
1441
  if (event.text == "#Round_Draw") event.preventDefault();
1411
1442
  });
1412
1443
  \`\`\`
1413
1444
 
1414
- A message the editor knows has typed fields (\`event.text\`); every one has
1415
- its arguments in \`event.args\`. Writing a field changes what the client
1416
- gets.
1445
+ A message whose layout is known has a typed field for each argument
1446
+ (\`event.text\`), and writing one changes what the client gets; a message
1447
+ without a known layout is read by place, through \`event.args\`, which
1448
+ every message has.
1417
1449
 
1418
1450
  Pawn: \`register_message\`
1419
1451
  `,
@@ -1422,21 +1454,22 @@ export default {
1422
1454
  HUD, — услышанное по пути, до того как оно ушло:
1423
1455
 
1424
1456
  \`\`\`ts
1425
- server.addEventListener("message:TextMsg", (event) => {
1457
+ server.addMessageListener("text", (event) => {
1426
1458
  if (event.text == "#Round_Draw") event.preventDefault();
1427
1459
  });
1428
1460
  \`\`\`
1429
1461
 
1430
- У сообщения, которое знает редактор, есть типизированные поля
1431
- (\`event.text\`); аргументы любого — в \`event.args\`. Запись поля меняет то,
1432
- что получит клиент.
1462
+ У сообщения с известной раскладкой на каждый аргумент есть типизированное
1463
+ поле (\`event.text\`), и запись в него меняет то, что получит клиент;
1464
+ сообщение без известной раскладки читается по месту, через \`event.args\`,
1465
+ которые есть у любого сообщения.
1433
1466
 
1434
1467
  Pawn: \`register_message\`
1435
1468
  `,
1436
1469
  },
1437
1470
  'ClientMessage.name': {
1438
- en: `The message's name, e.g. \`"TextMsg"\`.`,
1439
- ru: `Имя сообщения, например \`"TextMsg"\`.`,
1471
+ en: `The game's name of the message, e.g. \`"TextMsg"\` for \`text\`.`,
1472
+ ru: `Имя сообщения у игры, например \`"TextMsg"\` у \`text\`.`,
1440
1473
  },
1441
1474
  'ClientMessage.player': {
1442
1475
  en: `The player the message goes to; \`null\` for a message to everyone.`,
@@ -1542,6 +1575,14 @@ export default {
1542
1575
  en: `The shake's frequency, in jolts a second; \`5\` by default.`,
1543
1576
  ru: `Частота тряски — толчков в секунду; по умолчанию \`5\`.`,
1544
1577
  },
1578
+ 'ProgressBarOptions': {
1579
+ en: `The options of \`player.screen.progressBar\`.`,
1580
+ ru: `Параметры \`player.screen.progressBar\`.`,
1581
+ },
1582
+ 'ProgressBarOptions.startPercent': {
1583
+ en: `The bar's fill at the start, in percent; \`0\`, empty, by default.`,
1584
+ ru: `Заполненность полосы в начале, в процентах; по умолчанию \`0\` — пустая.`,
1585
+ },
1545
1586
  'StatusIconState': {
1546
1587
  en: `A status icon's state, one of \`"hide"\`, \`"show"\` (lit) or \`"flash"\`.`,
1547
1588
  ru: `Состояние иконки статуса, одно из: \`"hide"\` — убрана, \`"show"\` — горит, \`"flash"\` — мигает.`,
@@ -1557,7 +1598,8 @@ export default {
1557
1598
  player.screen.statusIcon("dmg_cold", "show", [0, 160, 255]);
1558
1599
  \`\`\`
1559
1600
 
1560
- Times are in seconds.
1601
+ Times are in seconds. A message listener hears what the screen sends, as
1602
+ it hears the game's: \`"progressBar"\` hears \`progressBar(seconds)\`.
1561
1603
 
1562
1604
  Pawn: \`ScreenFade\`, \`ScreenShake\`, \`StatusIcon\`, ...
1563
1605
  `,
@@ -1571,7 +1613,8 @@ export default {
1571
1613
  player.screen.statusIcon("dmg_cold", "show", [0, 160, 255]);
1572
1614
  \`\`\`
1573
1615
 
1574
- Время — в секундах.
1616
+ Время — в секундах. Обработчик сообщений слышит то, что шлёт экран, как
1617
+ слышит сообщения игры: \`"progressBar"\` слышит \`progressBar(seconds)\`.
1575
1618
 
1576
1619
  Pawn: \`ScreenFade\`, \`ScreenShake\`, \`StatusIcon\`, ...
1577
1620
  `,
@@ -1673,15 +1716,25 @@ export default {
1673
1716
  'Screen.progressBar': {
1674
1717
  en: `
1675
1718
  Shows the progress bar in the middle of the player's screen, filling up
1676
- over \`seconds\`; \`0\` hides it.
1719
+ over \`seconds\`; \`0\` hides it. With \`startPercent\` it starts part of the
1720
+ way full and fills the rest of \`seconds\`:
1677
1721
 
1678
- Pawn: \`BarTime\`, \`rg_send_bartime\`
1722
+ \`\`\`ts
1723
+ player.screen.progressBar(4, { startPercent: 50 }); // half full, full in 2 seconds
1724
+ \`\`\`
1725
+
1726
+ Pawn: \`BarTime\`, \`BarTime2\`, \`rg_send_bartime\`, \`rg_send_bartime2\`
1679
1727
  `,
1680
1728
  ru: `
1681
1729
  Показывает полосу прогресса посреди экрана игрока, которая заполняется за
1682
- \`seconds\` секунд; \`0\` её убирает.
1730
+ \`seconds\` секунд; \`0\` её убирает. С \`startPercent\` она начинается уже
1731
+ частично заполненной и заполняет остаток \`seconds\`:
1732
+
1733
+ \`\`\`ts
1734
+ player.screen.progressBar(4, { startPercent: 50 }); // наполовину полна, заполнится за 2 секунды
1735
+ \`\`\`
1683
1736
 
1684
- Pawn: \`BarTime\`, \`rg_send_bartime\`
1737
+ Pawn: \`BarTime\`, \`BarTime2\`, \`rg_send_bartime\`, \`rg_send_bartime2\`
1685
1738
  `,
1686
1739
  },
1687
1740
  'PlayerChangeEvent': {
@@ -1690,7 +1743,7 @@ export default {
1690
1743
  plugin, TypeScript or Pawn:
1691
1744
 
1692
1745
  \`\`\`ts
1693
- server.addEventListener("playerchange", (event) => {
1746
+ server.addEventListener("playerChange", (event) => {
1694
1747
  print(event.player, event.value ? "You are protected" : "Your spawn protection is over");
1695
1748
  }, { field: "spawnProtected" });
1696
1749
  \`\`\`
@@ -1704,7 +1757,7 @@ export default {
1704
1757
  записал любой плагин, на TypeScript или Pawn:
1705
1758
 
1706
1759
  \`\`\`ts
1707
- server.addEventListener("playerchange", (event) => {
1760
+ server.addEventListener("playerChange", (event) => {
1708
1761
  print(event.player, event.value ? "You are protected" : "Your spawn protection is over");
1709
1762
  }, { field: "spawnProtected" });
1710
1763
  \`\`\`
@@ -1728,12 +1781,12 @@ export default {
1728
1781
  },
1729
1782
  'ServerListenerOptions.field': {
1730
1783
  en: `
1731
- For \`"playerchange"\`: the field listened for, e.g. \`"spawnProtected"\`, or
1784
+ For \`"playerChange"\`: the field listened for, e.g. \`"spawnProtected"\`, or
1732
1785
  an object field's member, \`"glow.enabled"\`; an object field's name
1733
1786
  hears each of its members. Left out, every field.
1734
1787
  `,
1735
1788
  ru: `
1736
- Для \`"playerchange"\`: поле, которое слушают, например \`"spawnProtected"\`,
1789
+ Для \`"playerChange"\`: поле, которое слушают, например \`"spawnProtected"\`,
1737
1790
  или член поля-объекта, \`"glow.enabled"\`; имя поля-объекта слышит
1738
1791
  каждый его член. Без него — любое поле.
1739
1792
  `,
@@ -1852,7 +1905,7 @@ export default {
1852
1905
  the folders AMX Mod X keeps. Used through \`server\`:
1853
1906
 
1854
1907
  \`\`\`ts
1855
- server.addEventListener("putinserver", (event) => {
1908
+ server.addEventListener("putInServer", (event) => {
1856
1909
  print(event.player, "Welcome!"); // event is a PutinserverEvent
1857
1910
  });
1858
1911
  server.map; // "de_dust2"
@@ -1869,7 +1922,7 @@ export default {
1869
1922
  AMX Mod X. Используется через \`server\`:
1870
1923
 
1871
1924
  \`\`\`ts
1872
- server.addEventListener("putinserver", (event) => {
1925
+ server.addEventListener("putInServer", (event) => {
1873
1926
  print(event.player, "Welcome!"); // event — это PutinserverEvent
1874
1927
  });
1875
1928
  server.map; // "de_dust2"
@@ -1884,20 +1937,60 @@ export default {
1884
1937
  },
1885
1938
  'Server.addEventListener': {
1886
1939
  en: `
1887
- Calls \`listener\` every time the server raises the event \`type\` - or,
1888
- for \`"message:<Name>"\`, every time it sends that message to a client.
1889
- \`"playerchange"\` takes the field it is for: \`{ field: "spawnProtected" }\`.
1940
+ Calls \`listener\` every time the server raises the event \`type\`.
1941
+ \`"playerChange"\` takes the field it is for: \`{ field: "spawnProtected" }\`.
1890
1942
  `,
1891
1943
  ru: `
1892
- Вызывает \`listener\` каждый раз, когда сервер поднимает событие \`type\`, —
1893
- или, для \`"message:<Name>"\`, каждый раз, когда он шлёт это сообщение клиенту.
1894
- \`"playerchange"\` принимает поле, для которого он: \`{ field: "spawnProtected" }\`.
1944
+ Вызывает \`listener\` каждый раз, когда сервер поднимает событие \`type\`.
1945
+ \`"playerChange"\` принимает поле, для которого он: \`{ field: "spawnProtected" }\`.
1895
1946
  `,
1896
1947
  },
1897
1948
  'Server.removeEventListener': {
1898
1949
  en: `Stops calling a listener added with \`addEventListener\` - the same function and the same options.`,
1899
1950
  ru: `Перестаёт вызывать обработчик, добавленный через \`addEventListener\`, — ту же функцию с теми же настройками.`,
1900
1951
  },
1952
+ 'Server.addMessageListener': {
1953
+ en: `
1954
+ Calls \`listener\` every time the server sends the message \`name\` to a
1955
+ client, before it leaves: the listener reads its fields, changes them, or
1956
+ stops it with \`preventDefault()\`.
1957
+
1958
+ \`\`\`ts
1959
+ server.addMessageListener("death", (event) => {
1960
+ if (event.headshot) console.log(\`\${event.killer?.name} - headshot - \${event.victim?.name}\`);
1961
+ });
1962
+ \`\`\`
1963
+
1964
+ The editor lists the names, each with the game's own one in its words:
1965
+ \`death\` is the game's \`DeathMsg\`. A name may hear a few of the game's
1966
+ messages that are one thing: \`progressBar\` is \`BarTime\` and
1967
+ \`BarTime2\`, and \`event.name\` says which one came.
1968
+
1969
+ Pawn: \`register_message\`
1970
+ `,
1971
+ ru: `
1972
+ Вызывает \`listener\` каждый раз, когда сервер шлёт клиенту сообщение
1973
+ \`name\`, до того как оно ушло: обработчик читает его поля, меняет их или
1974
+ останавливает его через \`preventDefault()\`.
1975
+
1976
+ \`\`\`ts
1977
+ server.addMessageListener("death", (event) => {
1978
+ if (event.headshot) console.log(\`\${event.killer?.name} - headshot - \${event.victim?.name}\`);
1979
+ });
1980
+ \`\`\`
1981
+
1982
+ Редактор подсказывает имена, и в описании каждого — собственное имя у игры:
1983
+ \`death\` — это \`DeathMsg\` игры. Одно имя может слышать несколько
1984
+ сообщений игры, которые означают одно и то же: \`progressBar\` — это
1985
+ \`BarTime\` и \`BarTime2\`, а \`event.name\` говорит, какое из них пришло.
1986
+
1987
+ Pawn: \`register_message\`
1988
+ `,
1989
+ },
1990
+ 'Server.removeMessageListener': {
1991
+ en: `Stops calling a listener added with \`addMessageListener\` - the same name and the same function.`,
1992
+ ru: `Перестаёт вызывать обработчик, добавленный через \`addMessageListener\`, — то же имя и ту же функцию.`,
1993
+ },
1901
1994
  'Server.map': {
1902
1995
  en: `
1903
1996
  The current map's name, e.g. \`"de_dust2"\`.
@@ -1922,6 +2015,60 @@ export default {
1922
2015
  Pawn: \`get_maxplayers\`
1923
2016
  `,
1924
2017
  },
2018
+ 'Server.players': {
2019
+ en: `
2020
+ The players on the server, every one connected - never an HLTV proxy -
2021
+ read anew each time. Narrow them with the array's \`filter\`:
2022
+
2023
+ \`\`\`ts
2024
+ const alive = server.players.filter(player => player.isAlive);
2025
+ const cts = server.players.filter(player => player.team === "CT" && !player.isBot);
2026
+ \`\`\`
2027
+
2028
+ Pawn: \`get_players\`
2029
+ `,
2030
+ ru: `
2031
+ Игроки на сервере, все подключённые, кроме HLTV-прокси; читается заново
2032
+ при каждом обращении. Выборку сужает \`filter\` массива:
2033
+
2034
+ \`\`\`ts
2035
+ const alive = server.players.filter(player => player.isAlive);
2036
+ const cts = server.players.filter(player => player.team === "CT" && !player.isBot);
2037
+ \`\`\`
2038
+
2039
+ Pawn: \`get_players\`
2040
+ `,
2041
+ },
2042
+ 'Server.addBot': {
2043
+ en: `
2044
+ Adds a bot under \`name\`: a player the server runs, with no game behind
2045
+ it and no mind of its own - it stands where it spawns until a plugin
2046
+ moves it with \`bot.move()\`. \`null\` when no slot is free. \`"putInServer"\`
2047
+ fires for it as for anyone, \`bot.isBot\` is \`true\` and \`bot.kick()\`
2048
+ removes it.
2049
+
2050
+ \`\`\`ts
2051
+ const bot = server.addBot("Dummy");
2052
+ bot?.joinTeam("CT");
2053
+ \`\`\`
2054
+
2055
+ Pawn: \`engfunc(EngFunc_CreateFakeClient)\`, \`dllfunc(DLLFunc_ClientConnect)\`, \`dllfunc(DLLFunc_ClientPutInServer)\`
2056
+ `,
2057
+ ru: `
2058
+ Добавляет бота с именем \`name\`: игрока, которого ведёт сервер, — без игры за
2059
+ ним и без своего разума: он стоит, где появился, пока плагин не двинет его
2060
+ через \`bot.move()\`. \`null\`, если свободного слота нет. \`"putInServer"\`
2061
+ срабатывает для него, как для любого, \`bot.isBot\` равно \`true\`, а
2062
+ \`bot.kick()\` убирает его.
2063
+
2064
+ \`\`\`ts
2065
+ const bot = server.addBot("Dummy");
2066
+ bot?.joinTeam("CT");
2067
+ \`\`\`
2068
+
2069
+ Pawn: \`engfunc(EngFunc_CreateFakeClient)\`, \`dllfunc(DLLFunc_ClientConnect)\`, \`dllfunc(DLLFunc_ClientPutInServer)\`
2070
+ `,
2071
+ },
1925
2072
  'Server.configsDir': {
1926
2073
  en: `
1927
2074
  The AMX Mod X configs folder, relative to the game folder, as \`fs\` takes it:
@@ -1970,65 +2117,6 @@ export default {
1970
2117
  Pawn: \`server_cmd\`
1971
2118
  `,
1972
2119
  },
1973
- 'Server.addCommand': {
1974
- en: `
1975
- Adds a command players type, e.g. \`"/hp"\` in chat, or a name without the slash
1976
- in the console.
1977
-
1978
- \`\`\`ts
1979
- server.addCommand("/hp", (player) => print(player, \`\${player.health} HP\`));
1980
- server.addCommand("/kick", kick, { access: "Kick", description: "Kick a player" });
1981
- \`\`\`
1982
-
1983
- \`args\` are the words after the command. A chat command is not repeated in
1984
- chat, and it does not run for a player without the \`access\` right.
1985
- \`"say time"\` runs when a player writes exactly \`"time"\` in chat.
1986
-
1987
- Pawn: \`register_clcmd\`
1988
- `,
1989
- ru: `
1990
- Добавляет команду, которую набирают игроки, например \`"/hp"\` в чате или имя без
1991
- слеша — в консоли.
1992
-
1993
- \`\`\`ts
1994
- server.addCommand("/hp", (player) => print(player, \`\${player.health} HP\`));
1995
- server.addCommand("/kick", kick, { access: "Kick", description: "Kick a player" });
1996
- \`\`\`
1997
-
1998
- \`args\` — слова после команды. Чат-команда не повторяется в чате и не
1999
- срабатывает у игрока без права \`access\`. \`"say time"\` срабатывает, когда
2000
- игрок пишет в чат ровно \`"time"\`.
2001
-
2002
- Pawn: \`register_clcmd\`
2003
- `,
2004
- },
2005
- 'Server.addServerCommand': {
2006
- en: `
2007
- Adds a command of the server console - typed there, sent over rcon or run by
2008
- another plugin. Players cannot use it.
2009
-
2010
- \`\`\`ts
2011
- server.addServerCommand("myplugin_reset", (args) => reset(args.length > 0 ? args[0] : "all"));
2012
- \`\`\`
2013
-
2014
- \`args\` are the words after the command. It may be added at the top level of
2015
- the file.
2016
-
2017
- Pawn: \`register_srvcmd\`
2018
- `,
2019
- ru: `
2020
- Добавляет команду консоли сервера — набранную там, пришедшую по rcon или
2021
- вызванную другим плагином. Игроки её не набирают.
2022
-
2023
- \`\`\`ts
2024
- server.addServerCommand("myplugin_reset", (args) => reset(args.length > 0 ? args[0] : "all"));
2025
- \`\`\`
2026
-
2027
- \`args\` — слова после команды. Её можно добавлять на верхнем уровне файла.
2028
-
2029
- Pawn: \`register_srvcmd\`
2030
- `,
2031
- },
2032
2120
  'Server.showHud': {
2033
2121
  en: `Shows a HUD message to every player, with the same options as \`player.showHud\`.`,
2034
2122
  ru: `Показывает HUD-сообщение всем игрокам, с теми же настройками, что у \`player.showHud\`.`,
@@ -2069,7 +2157,7 @@ export default {
2069
2157
  if (event.player.isBot) event.preventDefault();
2070
2158
  });
2071
2159
  game.addEventListener("canPlayerHearPlayer", (event) => event.listener.team == event.sender.team);
2072
- game.addEventListener("flPlayerFallDamage", (event) => event.result / 2, true);
2160
+ game.addEventListener("fallDamage", (event) => event.result / 2, true);
2073
2161
  \`\`\`
2074
2162
 
2075
2163
  The event's type follows from its name. What a listener returns is the
@@ -2078,7 +2166,7 @@ export default {
2078
2166
  nothing leaves it to the game; \`event.preventDefault()\` blocks without an
2079
2167
  answer. A value of the wrong type is an error in the editor and in the build.
2080
2168
 
2081
- The game rules are its fields: \`game.freezePeriod\`, \`game.numCtWins\`,
2169
+ The game rules are its fields: \`game.isFreezeTime\`, \`game.ctWins\`,
2082
2170
  \`game.roundWinner\`.
2083
2171
 
2084
2172
  Pawn: \`RegisterHookChain\`, \`RegisterHam\`, \`get_member_game\`
@@ -2092,7 +2180,7 @@ export default {
2092
2180
  if (event.player.isBot) event.preventDefault();
2093
2181
  });
2094
2182
  game.addEventListener("canPlayerHearPlayer", (event) => event.listener.team == event.sender.team);
2095
- game.addEventListener("flPlayerFallDamage", (event) => event.result / 2, true);
2183
+ game.addEventListener("fallDamage", (event) => event.result / 2, true);
2096
2184
  \`\`\`
2097
2185
 
2098
2186
  Тип события следует из его имени. То, что возвращает обработчик, — ответ
@@ -2101,7 +2189,7 @@ export default {
2101
2189
  игре; \`event.preventDefault()\` блокирует без ответа. Значение не того типа —
2102
2190
  ошибка и в редакторе, и при сборке.
2103
2191
 
2104
- Правила игры — её поля: \`game.freezePeriod\`, \`game.numCtWins\`,
2192
+ Правила игры — её поля: \`game.isFreezeTime\`, \`game.ctWins\`,
2105
2193
  \`game.roundWinner\`.
2106
2194
 
2107
2195
  Pawn: \`RegisterHookChain\`, \`RegisterHam\`, \`get_member_game\`
@@ -2216,8 +2304,8 @@ export default {
2216
2304
  `,
2217
2305
  },
2218
2306
  'ActionOptions': {
2219
- en: `The options of an entity's action such as \`weapon.deploy()\` or \`entity.takeHealth(...)\`.`,
2220
- ru: `Настройки действия сущности, такого как \`weapon.deploy()\` или \`entity.takeHealth(...)\`.`,
2307
+ en: `The options of an entity's action such as \`weapon.deploy()\` or \`entity.heal(...)\`.`,
2308
+ ru: `Настройки действия сущности, такого как \`weapon.deploy()\` или \`entity.heal(...)\`.`,
2221
2309
  },
2222
2310
  'ActionOptions.hooks': {
2223
2311
  en: `
@@ -2704,7 +2792,7 @@ export default {
2704
2792
  'Call': {
2705
2793
  en: `
2706
2794
  A call of a Pawn native with a \`...\` tail, built one argument at a time -
2707
- the low-level way. A native from \`~/natives\` is an ordinary function and
2795
+ the low-level way. A native from \`@amxts/core/natives\` is an ordinary function and
2708
2796
  needs none of this.
2709
2797
 
2710
2798
  new Call(NATIVE_server_print).str("%s").str(text).run();
@@ -2722,7 +2810,7 @@ export default {
2722
2810
  `,
2723
2811
  ru: `
2724
2812
  Вызов Pawn-натива с хвостом \`...\`, собираемый по одному аргументу, —
2725
- низкоуровневый способ. Натив из \`~/natives\` — обычная функция, и ему это
2813
+ низкоуровневый способ. Натив из \`@amxts/core/natives\` — обычная функция, и ему это
2726
2814
  не нужно.
2727
2815
 
2728
2816
  new Call(NATIVE_server_print).str("%s").str(text).run();
@@ -2792,6 +2880,54 @@ export default {
2792
2880
  en: `The value the native left in the \`ref\` argument at this position, after \`run\`.`,
2793
2881
  ru: `Значение, которое натив оставил в аргументе \`ref\` на этой позиции, после \`run\`.`,
2794
2882
  },
2883
+ 'Call.count': {
2884
+ en: `The number of arguments added so far: the position the next one takes.`,
2885
+ ru: `Число уже добавленных аргументов: позиция, которую займёт следующий.`,
2886
+ },
2887
+ 'Call.textInto': {
2888
+ en: `
2889
+ Adds room for text the native writes, in a \`...\` tail, holding \`text\` to
2890
+ begin with; its length follows by address, as \`ret[], len\` wants it.
2891
+ After \`run\` the text is in \`cellsAt\` of this position.
2892
+ `,
2893
+ ru: `
2894
+ Добавляет в хвост \`...\` место для текста, который пишет натив, с \`text\`
2895
+ в начале; его длина идёт следом по адресу, как того ждёт \`ret[], len\`.
2896
+ После \`run\` текст — в \`cellsAt\` этой позиции.
2897
+ `,
2898
+ },
2899
+ 'Call.cellsAt': {
2900
+ en: `The cells at the address of the argument at this position, after \`run\`: a vector or text the native wrote.`,
2901
+ ru: `Ячейки по адресу аргумента на этой позиции, после \`run\`: вектор или текст, который записал натив.`,
2902
+ },
2903
+ 'Ref': {
2904
+ en: `
2905
+ A value a native writes back through its argument, where Pawn passes a
2906
+ variable for the native to fill: text into \`ret[], len\`, a number into
2907
+ \`&value\`. Give it where the native takes one; after the call, \`value\` is
2908
+ what the native wrote.
2909
+
2910
+ \`\`\`ts
2911
+ const reason = new Ref("");
2912
+ if (!dllfunc(DLLFunc_ClientConnect, id, "Bot", "127.0.0.1", reason)) console.log(reason.value);
2913
+ \`\`\`
2914
+ `,
2915
+ ru: `
2916
+ Значение, которое натив возвращает через свой аргумент там, где Pawn
2917
+ передаёт переменную, чтобы натив её заполнил: текст в \`ret[], len\`, число
2918
+ в \`&value\`. Передайте его туда, где натив его ждёт; после вызова \`value\` —
2919
+ то, что записал натив.
2920
+
2921
+ \`\`\`ts
2922
+ const reason = new Ref("");
2923
+ if (!dllfunc(DLLFunc_ClientConnect, id, "Bot", "127.0.0.1", reason)) console.log(reason.value);
2924
+ \`\`\`
2925
+ `,
2926
+ },
2927
+ 'Ref.value': {
2928
+ en: `The value the native wrote; before the call, the one it starts with.`,
2929
+ ru: `Значение, которое записал натив; до вызова — то, с которого он начинает.`,
2930
+ },
2795
2931
  'Call.run': {
2796
2932
  en: `Calls the native with the arguments added so far and returns its result.`,
2797
2933
  ru: `Вызывает натив с добавленными аргументами и возвращает его результат.`,
@@ -2907,6 +3043,62 @@ export default {
2907
3043
  задаёт \`amxts.config.ts\`. Глобальная; \`import { defineModule } from "@amxts/core"\` тоже работает.
2908
3044
  `,
2909
3045
  },
3046
+ 'callingPlugin': {
3047
+ en: `
3048
+ The plugin whose call the module runs now, as a number: what the module
3049
+ keeps for that plugin - a menu it made, a function it gave - is marked with
3050
+ it, and dropped when \`onPluginStop()\` gives the same number. \`0\` when no
3051
+ other plugin's call runs: the module's own plugin, its natives for Pawn
3052
+ plugins, its events and timers.
3053
+
3054
+ \`\`\`ts
3055
+ export function addRule(test: Rule) {
3056
+ rules.push({ test, from: callingPlugin() });
3057
+ }
3058
+ \`\`\`
3059
+ `,
3060
+ ru: `
3061
+ Плагин, чей вызов модуль выполняет сейчас, — числом: то, что модуль хранит
3062
+ для этого плагина, — созданное им меню, переданную им функцию, — помечается
3063
+ этим числом и убирается, когда \`onPluginStop()\` даёт то же число. \`0\`, когда
3064
+ вызова другого плагина нет: собственный плагин модуля, его нативы для
3065
+ Pawn-плагинов, его события и таймеры.
3066
+
3067
+ \`\`\`ts
3068
+ export function addRule(test: Rule) {
3069
+ rules.push({ test, from: callingPlugin() });
3070
+ }
3071
+ \`\`\`
3072
+ `,
3073
+ },
3074
+ 'onPluginStop': {
3075
+ en: `
3076
+ Calls \`listener\` when a plugin that called the module stops - unloaded,
3077
+ reloaded, or its load failed - with the number \`callingPlugin()\` gave
3078
+ during its calls. The module drops what that plugin gave it: a reloaded
3079
+ plugin is a new one, which gives everything again, and a function of the
3080
+ one that stopped answers nothing.
3081
+
3082
+ \`\`\`ts
3083
+ onPluginStop((plugin) => {
3084
+ rules = rules.filter(rule => rule.from != plugin);
3085
+ });
3086
+ \`\`\`
3087
+ `,
3088
+ ru: `
3089
+ Вызывает \`listener\`, когда останавливается плагин, вызывавший модуль, —
3090
+ выгружен, перезагружен или не загрузился, — с числом, которое давал
3091
+ \`callingPlugin()\` во время его вызовов. Модуль убирает то, что этот плагин
3092
+ ему дал: перезагруженный плагин — новый, он даёт всё заново, а функция
3093
+ остановленного ничего не отвечает.
3094
+
3095
+ \`\`\`ts
3096
+ onPluginStop((plugin) => {
3097
+ rules = rules.filter(rule => rule.from != plugin);
3098
+ });
3099
+ \`\`\`
3100
+ `,
3101
+ },
2910
3102
  'ForwardStop': {
2911
3103
  en: `
2912
3104
  The forward's stopping rule, one of: \`"never"\` - every plugin hears it, whatever it
@@ -3299,4 +3491,312 @@ export default {
3299
3491
  Pawn: \`show_menu\`, \`register_menucmd\`
3300
3492
  `,
3301
3493
  },
3494
+ 'MenuColor': {
3495
+ en: `A colour of a menu's item numbers: a menu's colour tag, \`"!y"\`, \`"!r"\`, \`"!d"\` or \`"!w"\`.`,
3496
+ ru: `Цвет номеров пунктов меню: цветовой тег меню, \`"!y"\`, \`"!r"\`, \`"!d"\` или \`"!w"\`.`,
3497
+ },
3498
+ 'MenuOptions': {
3499
+ en: `The options of a \`Menu\`: its pages and the texts of its own items.`,
3500
+ ru: `Настройки \`Menu\`: его страницы и тексты его собственных пунктов.`,
3501
+ },
3502
+ 'MenuOptions.perPage': {
3503
+ en: `
3504
+ Items on a page, \`7\` at most: Back, More and Exit go below them. \`0\`
3505
+ puts every item on one page, without Back and More - \`10\` at most.
3506
+
3507
+ Pawn: \`MPROP_PERPAGE\`
3508
+ `,
3509
+ ru: `
3510
+ Пунктов на странице, не больше \`7\`: под ними идут «Назад», «Дальше» и «Выход».
3511
+ \`0\` ставит все пункты на одну страницу, без «Назад» и «Дальше», — не больше \`10\`.
3512
+
3513
+ Pawn: \`MPROP_PERPAGE\`
3514
+ `,
3515
+ },
3516
+ 'MenuOptions.exit': {
3517
+ en: `
3518
+ Whether the menu has an Exit item; \`true\` by default.
3519
+
3520
+ Pawn: \`MPROP_EXIT\`
3521
+ `,
3522
+ ru: `
3523
+ Есть ли у меню пункт «Выход»; по умолчанию \`true\`.
3524
+
3525
+ Pawn: \`MPROP_EXIT\`
3526
+ `,
3527
+ },
3528
+ 'MenuOptions.backText': {
3529
+ en: `
3530
+ The Back item's text; AMX Mod X's \`"Back"\`, in the player's language, by default.
3531
+
3532
+ Pawn: \`MPROP_BACKNAME\`
3533
+ `,
3534
+ ru: `
3535
+ Текст пункта «Назад»; по умолчанию \`"Back"\` AMX Mod X на языке игрока.
3536
+
3537
+ Pawn: \`MPROP_BACKNAME\`
3538
+ `,
3539
+ },
3540
+ 'MenuOptions.nextText': {
3541
+ en: `
3542
+ The More item's text; AMX Mod X's \`"More"\` by default.
3543
+
3544
+ Pawn: \`MPROP_NEXTNAME\`
3545
+ `,
3546
+ ru: `
3547
+ Текст пункта «Дальше»; по умолчанию \`"More"\` AMX Mod X.
3548
+
3549
+ Pawn: \`MPROP_NEXTNAME\`
3550
+ `,
3551
+ },
3552
+ 'MenuOptions.exitText': {
3553
+ en: `
3554
+ The Exit item's text; AMX Mod X's \`"Exit"\` by default.
3555
+
3556
+ Pawn: \`MPROP_EXITNAME\`
3557
+ `,
3558
+ ru: `
3559
+ Текст пункта «Выход»; по умолчанию \`"Exit"\` AMX Mod X.
3560
+
3561
+ Pawn: \`MPROP_EXITNAME\`
3562
+ `,
3563
+ },
3564
+ 'MenuOptions.numberColor': {
3565
+ en: `
3566
+ The colour of the item numbers; \`"!r"\`, red, by default.
3567
+
3568
+ Pawn: \`MPROP_NUMBER_COLOR\`
3569
+ `,
3570
+ ru: `
3571
+ Цвет номеров пунктов; по умолчанию \`"!r"\`, красный.
3572
+
3573
+ Pawn: \`MPROP_NUMBER_COLOR\`
3574
+ `,
3575
+ },
3576
+ 'MenuContext': {
3577
+ en: `The context a menu's functions get: the player it is shown to, the menu and the data it was shown with.`,
3578
+ ru: `Контекст, который получают функции меню: игрок, которому оно показано, само меню и данные, с которыми его показали.`,
3579
+ },
3580
+ 'MenuContext.player': {
3581
+ en: `The player the menu is shown to.`,
3582
+ ru: `Игрок, которому показано меню.`,
3583
+ },
3584
+ 'MenuContext.menu': {
3585
+ en: `The menu itself: \`menu.show(player, data)\` keeps it open after a choice.`,
3586
+ ru: `Само меню: \`menu.show(player, data)\` оставляет его открытым после выбора.`,
3587
+ },
3588
+ 'MenuContext.data': {
3589
+ en: `The data \`show\` was given.`,
3590
+ ru: `Данные, которые получил \`show\`.`,
3591
+ },
3592
+ 'MenuItemOptions': {
3593
+ en: `An item of a \`Menu\`: its title, when it is shown and can be chosen, and what choosing it does.`,
3594
+ ru: `Пункт \`Menu\`: его заголовок, когда он показан и доступен и что делает его выбор.`,
3595
+ },
3596
+ 'MenuItemOptions.title': {
3597
+ en: `The item's text - or a function that gives it for the player it is shown to.`,
3598
+ ru: `Текст пункта — или функция, которая даёт его для игрока, которому он показан.`,
3599
+ },
3600
+ 'MenuItemOptions.enabled': {
3601
+ en: `Whether the player can choose it; one he cannot is drawn grey and does nothing. \`true\` by default.`,
3602
+ ru: `Может ли игрок его выбрать; недоступный рисуется серым и ничего не делает. По умолчанию \`true\`.`,
3603
+ },
3604
+ 'MenuItemOptions.visible': {
3605
+ en: `Whether it is shown at all; a hidden item takes no place. \`true\` by default.`,
3606
+ ru: `Показан ли он вообще; скрытый пункт не занимает места. По умолчанию \`true\`.`,
3607
+ },
3608
+ 'MenuItemOptions.onSelect': {
3609
+ en: `The item's action, run when the player chooses it. The menu closes, unless this shows it again.`,
3610
+ ru: `Действие пункта, которое выполняется, когда игрок его выбирает. Меню закрывается, если эта функция не покажет его снова.`,
3611
+ },
3612
+ 'Menu': {
3613
+ en: `
3614
+ A menu of AMX Mod X's own: items a player picks with the number keys, on
3615
+ pages with Back and More, and Exit. \`Data\` is what it is shown with, which
3616
+ its functions get beside the player.
3617
+
3618
+ \`\`\`ts
3619
+ interface ShopData {
3620
+ category: string;
3621
+ }
3622
+
3623
+ const shop = new Menu<ShopData>("!yShop");
3624
+ shop.addItem({
3625
+ title: "Armor - $1000",
3626
+ enabled: ({ player }) => player.armor < 100,
3627
+ onSelect: ({ player }) => {
3628
+ player.armor = 100;
3629
+ },
3630
+ });
3631
+ shop.show(player, { category: "armor" });
3632
+ \`\`\`
3633
+
3634
+ The title and each item's title, \`visible\` and \`enabled\` are asked at
3635
+ every \`show\`, for that player. Colour tags as in \`showMenu\`: \`!y\` yellow,
3636
+ \`!r\` red, \`!d\` grey, \`!w\` white, \`!R\` to the right edge.
3637
+
3638
+ Pawn: \`menu_create\`, \`menu_setprop\`
3639
+ `,
3640
+ ru: `
3641
+ Меню самого AMX Mod X: пункты, которые игрок выбирает цифровыми клавишами,
3642
+ на страницах с «Назад» и «Дальше», и «Выход». \`Data\` — то, с чем его
3643
+ показывают; это получают его функции рядом с игроком.
3644
+
3645
+ \`\`\`ts
3646
+ interface ShopData {
3647
+ category: string;
3648
+ }
3649
+
3650
+ const shop = new Menu<ShopData>("!yShop");
3651
+ shop.addItem({
3652
+ title: "Armor - $1000",
3653
+ enabled: ({ player }) => player.armor < 100,
3654
+ onSelect: ({ player }) => {
3655
+ player.armor = 100;
3656
+ },
3657
+ });
3658
+ shop.show(player, { category: "armor" });
3659
+ \`\`\`
3660
+
3661
+ Заголовок и у каждого пункта заголовок, \`visible\` и \`enabled\` вычисляются
3662
+ при каждом \`show\`, для этого игрока. Цветовые теги — как в \`showMenu\`: \`!y\`
3663
+ жёлтый, \`!r\` красный, \`!d\` серый, \`!w\` белый, \`!R\` — к правому краю.
3664
+
3665
+ Pawn: \`menu_create\`, \`menu_setprop\`
3666
+ `,
3667
+ },
3668
+ 'Menu.addItem': {
3669
+ en: `
3670
+ Adds an item: its title, when it is shown and can be chosen, and what
3671
+ choosing it does.
3672
+
3673
+ \`\`\`ts
3674
+ shop.addItem({
3675
+ title: ({ player }) => \`Heal (\${player.health} HP)\`,
3676
+ visible: ({ player }) => player.isAlive,
3677
+ enabled: ({ player }) => player.health < 100,
3678
+ onSelect: ({ player }) => {
3679
+ player.health = 100;
3680
+ },
3681
+ });
3682
+ \`\`\`
3683
+
3684
+ Pawn: \`menu_additem\`
3685
+ `,
3686
+ ru: `
3687
+ Добавляет пункт: его заголовок, когда он показан и доступен и что делает
3688
+ его выбор.
3689
+
3690
+ \`\`\`ts
3691
+ shop.addItem({
3692
+ title: ({ player }) => \`Heal (\${player.health} HP)\`,
3693
+ visible: ({ player }) => player.isAlive,
3694
+ enabled: ({ player }) => player.health < 100,
3695
+ onSelect: ({ player }) => {
3696
+ player.health = 100;
3697
+ },
3698
+ });
3699
+ \`\`\`
3700
+
3701
+ Pawn: \`menu_additem\`
3702
+ `,
3703
+ },
3704
+ 'Menu.show': {
3705
+ en: `
3706
+ Shows the menu to a player, with the data its functions get; it closes
3707
+ when he chooses an item or leaves it.
3708
+
3709
+ Pawn: \`menu_display\`
3710
+ `,
3711
+ ru: `
3712
+ Показывает меню игроку, с данными, которые получают его функции; оно
3713
+ закрывается, когда он выбирает пункт или выходит из меню.
3714
+
3715
+ Pawn: \`menu_display\`
3716
+ `,
3717
+ },
3718
+ 'Client.kick': {
3719
+ en: `Kicks the player off the server, with the reason he is shown: \`client.kick("Spam")\`.`,
3720
+ ru: `Кикает игрока с сервера с причиной, которую он видит: \`client.kick("Спам")\`.`,
3721
+ },
3722
+ 'Player.kick': {
3723
+ en: `
3724
+ Kicks the player off the server, with the reason he is shown:
3725
+ \`player.kick("Spam")\`; without one, the game's own.
3726
+
3727
+ Pawn: \`server_cmd("kick #%d")\`
3728
+ `,
3729
+ ru: `
3730
+ Кикает игрока с сервера с причиной, которую он видит:
3731
+ \`player.kick("Спам")\`; без неё — собственной причиной игры.
3732
+
3733
+ Pawn: \`server_cmd("kick #%d")\`
3734
+ `,
3735
+ },
3736
+ 'Player.move': {
3737
+ en: `
3738
+ Moves a bot \`server.addBot\` made, as a player's keys and mouse would for
3739
+ one frame: \`bot.move({ forward: 250, buttons: ["jump"] })\`. A bot does
3740
+ nothing by itself, so it is moved every frame - in the \`"frame"\` event -
3741
+ or it stands still. A player who is not a bot is refused with an error.
3742
+
3743
+ Pawn: \`engfunc(EngFunc_RunPlayerMove, ...)\`
3744
+ `,
3745
+ ru: `
3746
+ Двигает бота, созданного \`server.addBot\`, как клавиши и мышь игрока за один
3747
+ кадр: \`bot.move({ forward: 250, buttons: ["jump"] })\`. Сам бот ничего не
3748
+ делает, поэтому его двигают каждый кадр — в событии \`"frame"\`, — иначе он
3749
+ стоит на месте. Игрока, который не бот, метод отклоняет с ошибкой.
3750
+
3751
+ Pawn: \`engfunc(EngFunc_RunPlayerMove, ...)\`
3752
+ `,
3753
+ },
3754
+ 'CommandInfo': {
3755
+ en: `A command the plugin added, as \`server.commands\` lists it: what a \`/help\` shows.`,
3756
+ ru: `Команда, которую добавил плагин, как её перечисляет \`server.commands\`: то, что показывает \`/help\`.`,
3757
+ },
3758
+ 'CommandInfo.usage': {
3759
+ en: `The command's usage, as it is typed, e.g. \`"/kick <target> [reason]"\`.`,
3760
+ ru: `Использование команды, как её набирают, например \`"/kick <target> [reason]"\`.`,
3761
+ },
3762
+ 'CommandInfo.description': {
3763
+ en: `The command's description, as its \`description\` option gave it; \`""\` without one.`,
3764
+ ru: `Описание команды, как его дала настройка \`description\`; \`""\`, если описания нет.`,
3765
+ },
3766
+ 'CommandInfo.access': {
3767
+ en: `The admin right the command needs; \`null\` when everyone may use it.`,
3768
+ ru: `Право админа, которое нужно команде; \`null\`, если пользоваться ей может каждый.`,
3769
+ },
3770
+ 'CommandInfo.server': {
3771
+ en: `Whether it is a command of the server console rather than a player's.`,
3772
+ ru: `Команда ли это консоли сервера, а не игрока.`,
3773
+ },
3774
+ 'Server.commands': {
3775
+ en: `
3776
+ The commands this plugin added, players' and the server's, in the order
3777
+ they were added: each one's \`usage\`, \`description\` and \`access\` - what a
3778
+ \`/help\` prints.
3779
+
3780
+ \`\`\`ts
3781
+ server.addCommand("/help", ({ player }) => {
3782
+ for (const command of server.commands) {
3783
+ if (command.access == null || player.access.includes(command.access)) print(player, command.usage);
3784
+ }
3785
+ });
3786
+ \`\`\`
3787
+ `,
3788
+ ru: `
3789
+ Команды, которые добавил этот плагин, игроков и сервера, в порядке
3790
+ добавления: у каждой \`usage\`, \`description\` и \`access\` — то, что
3791
+ печатает \`/help\`.
3792
+
3793
+ \`\`\`ts
3794
+ server.addCommand("/help", ({ player }) => {
3795
+ for (const command of server.commands) {
3796
+ if (command.access == null || player.access.includes(command.access)) print(player, command.usage);
3797
+ }
3798
+ });
3799
+ \`\`\`
3800
+ `,
3801
+ },
3302
3802
  };