Файлы
@amxts/core/fs читает и пишет файлы так же, как fs в Node:
import * as fs from "@amxts/core/fs";
const rulesFile = `${server.configsDir}/myplugin/rules.txt`;
server.addCommand("/rules", ({ player }) => showRules(player));
function showRules(player: Player) {
const text = fs.readFileSync(rulesFile);
if (text == null) return; // файла нет
for (const line of text.split("\n")) console.log(line);
fs.appendFileSync(`${server.dataDir}/myplugin-rules.log`, `${player.name} прочитал правила\n`);
}
У каждой функции есть синхронная форма и форма с промисом, для await:
| Синхронная | С промисом | Что делает |
|---|---|---|
readFileSync(path) → string | null | readFile(path) → Promise<string> | читает весь файл как текст |
writeFileSync(path, text) → boolean | writeFile(path, text) → Promise<void> | записывает файл, заменяя то, что там было |
appendFileSync(path, text) → boolean | appendFile(path, text) → Promise<void> | дописывает в конец, при необходимости создаёт файл |
existsSync(path) → boolean | exists(path) → Promise<boolean> | есть ли такой файл или папка |
readdirSync(path) → string[] | null | readdir(path) → Promise<string[]> | имена в папке, без . и .. |
mkdirSync(path, options?) → boolean | mkdir(path, options?) → Promise<void> | создаёт папку; { recursive: true } создаёт и недостающие папки выше |
import * as fs from "@amxts/core/fs";
async function saveMap() {
await fs.mkdir(`${server.dataDir}/myplugin`, { recursive: true });
await fs.writeFile(`${server.dataDir}/myplugin/last-map.txt`, server.map);
}
fs.readFile("missing.txt").catch((error) => console.log(error.message));
// ENOENT: no such file or directory, open 'missing.txt'
Пути
Путь задаётся относительно папки игры, cstrike/, как у любого плагина
AMX Mod X. server.configsDir — папка конфигов (addons/amxmodx/configs),
server.dataDir — папка данных (addons/amxmodx/data), где бы сервер их ни
держал. Храните файлы плагина в своей папке или под своим именем:
configs/myplugin/, data/myplugin-stats.txt.
Текст
Файлы читаются и пишутся как текст в UTF-8. Файл читается целиком, какого бы размера он ни был. Метка порядка байтов (BOM) в начале файла сохраняется, как в Node.
JSON
JSON читает и пишет текст JSON, как в JavaScript. JSON.parse говорят, что
он читает, — JSON.parse<Stats>(text) или тип, куда уходит значение, — и он
строит этот объект вместе с его массивами, Record и полями:
import * as fs from "@amxts/core/fs";
interface Stats {
kills: number;
deaths: number;
lastMap?: string;
}
const statsFile = `${server.dataDir}/myplugin/stats.json`;
function loadStats(): Stats {
const text = fs.readFileSync(statsFile);
if (text == null) return { kills: 0, deaths: 0 };
return JSON.parse(text);
}
function saveStats(stats: Stats) {
fs.writeFileSync(statsFile, JSON.stringify(stats, null, 2));
}
Текст, который не JSON, — это SyntaxError; значение не того рода, что
говорит тип, — текст там, где число, поле, которое должно быть и которого
нет, — это TypeError с именем поля. Ловите их через try/catch.
JSON.stringify пропускает поле, которое undefined, пишет Date как её
текст ISO, а объект с toJSON() — как то, что он отдаёт.
Настройки, которые правит владелец сервера, типизированный конфиг config-core читает одинаково из YAML, JSON и INI.
Когда не получилось
Синхронная функция сообщает об ошибке результатом: null у readFileSync и
readdirSync, false у writeFileSync, appendFileSync и mkdirSync —
например, если нет папки. Функция с промисом отклоняется с Error, чьё
сообщение начинается с ENOENT, как в Node (у mkdir — с EEXIST or ENOENT).
В обоих случаях работа делается сразу: к моменту, когда функция с промисом вернулась, промис уже завершён.
Операционная система
import { EOL, platform } from "@amxts/core/os";
if (platform() == "linux") console.log("сервер на Linux");
const lines = ["first", "second"].join(EOL); // "\r\n" в Windows, "\n" в Linux
platform() — это "win32" или "linux", а EOL — перевод строки этой
системы.
В тесте фейковый сервер держит папку игры в памяти: server.writeFile(path, text) — до того, как плагин читает, server.file(path) — после того, как
он записал (Тесты).
Хранилище
Storage хранит текст по ключу, как Map<string, string>, только на диске: то, что плагин сохранил, переживает смену карты и перезапуск сервера. Это место для накопленных очков игрока, его последнего визита, настройки.
HTTP
Плагин обращается к веб-сервисам через две функции, обе глобальные — без строки импорта: