Skip to content

Client JS API

Client-ресурсы используют JavaScript и глобальный объект varion. Runtime инжектит globalThis.varion (доступен также как varion без префикса) до запуска вашего client-main.

Эта страница — справочник по всему runtime-API клиента, сгруппированный по пространствам имён. Смотрите также WebView, GTA natives и краткий обзор клиента.

Терминология: client-events — локальные события внутри клиента; server-events — события, которыми клиент обменивается с сервером. На клиенте нет varion.onClient — приём событий от сервера делается через varion.onServer, а onClient существует только на стороне сервера.


Логирование

javascript
varion.log('message');    // info
varion.warn('message');   // warning
varion.error('message');  // error

varion.warn и varion.error — единственные хелперы уровней логирования (logWarning / logError не существуют).


События

Локальные client-события

javascript
const sub = varion.on('myEvent', (a, b) => varion.log(`${a} ${b}`));
varion.once('resourceStop', () => varion.log('stopping'));
varion.off('myEvent', handler);
sub.destroy();               // on/once возвращают { destroy() }

varion.emit('myEvent', 1, 2);        // локальный эмит для других client-обработчиков
varion.emitRaw('anyEvent', payload); // без фильтра зарезервированных имён (для тестов)

varion.emit блокирует зарезервированные движком имена (connection:*, stream:*, playerSpawn, entityStreamIn и т.д.) и имена с префиксом varion:. Такие события слушайте через varion.on, а эмитить их может только движок.

Server-события

javascript
varion.onServer('chat:addMessage', (author, text) => {});
varion.onceServer('welcome', (data) => {});
varion.offServer('chat:addMessage', handler);

varion.emitServer('chat:message', 'hello');
varion.emitServerUnreliable('position:update', x, y, z);

// Ненадёжный (unreliable) приём
varion.onServerUnreliable('position:update', (x, y, z) => {});
varion.offServerUnreliable('position:update', handler);
varion.onceServerUnreliable('position:update', handler);

Аргументы emitServer автоматически кодируются в типизированные MValue (см. ниже).

Интроспекция обработчиков

javascript
varion.getLocalEventListeners('myEvent');            // локальные
varion.getRemoteEventListeners('chat:addMessage');   // серверные (reliable)
varion.getUnreliableRemoteEventListeners('pos');     // серверные (unreliable)

Tick-цикл

javascript
varion.everyTick(() => { /* ~каждый game tick */ });
varion.on('everyTick', handler);   // эквивалент

ColShape-события (важно про регистр)

Клиент использует именно такой регистр имён:

СобытиеАргументы
playerEnterColShape(colShape)
playerExitColShape(colShape)
entityEnterColshape(colShape, entity)
entityLeaveColshape(colShape, entity)

Обратите внимание: playerEnter/ExitColShape пишутся с заглавной S, а entityEnter/LeaveColshape — со строчной sLeave, а не Exit).


RPC

javascript
// Вызов server-RPC и ожидание ответа (Promise)
const result = await varion.callServer('server:ping', arg);
const same   = await varion.emitRpc('server:ping', arg);   // emitRpc — алиас callServer

// Обработчик client-RPC (сервер вызывает через EmitClientRpcAsync)
varion.onRpc('client:ping', async () => ({ pong: true }));
varion.offRpc('client:ping', handler);

callServer / emitRpc возвращают Promise, который резолвится результатом с сервера или реджектится при ошибке/таймауте.


MValue

Фабрика типизированных значений varion.MValue (используется автоматически в emitServer, но доступна и явно):

javascript
varion.MValue.nil();
varion.MValue.bool(true);
varion.MValue.int(-5);
varion.MValue.uint(10);
varion.MValue.double(1.5);
varion.MValue.string('hi');
varion.MValue.list(a, b, c);
varion.MValue.dict({ k: 'v' });
varion.MValue.vector3(x, y, z);
varion.MValue.entity(entityType, id);
varion.MValue.rgba(255, 0, 0, 255);
varion.MValue.byteArray(str);
varion.MValue.from(anyValue);   // авто-детект типа
varion.MValue.to(mvalue);

Хеши и загрузка моделей

javascript
const hash = varion.hash('mp_m_freemode_01');   // joaat — алиас hash
varion.joaat('adder');

varion.loadModel('adder');
varion.isModelLoaded('adder');       // → boolean
varion.unloadModel('adder');
await varion.waitForModel('adder', 10000);   // Promise, резолвит hash

varion.requestIpl('v_janitor');
varion.removeIpl('v_janitor');

Таймеры

Тик-управляемые таймеры (обрабатываются на game tick). Доступны и как методы varion.*, и как глобальные функции.

javascript
const t = varion.setTimeout(() => {}, 500);
varion.clearTimeout(t);

const i = varion.setInterval(() => {}, 1000);
varion.clearInterval(i);

setTimeout(fn, 500);   // глобальные алиасы тоже доступны

Таймеры ресурса автоматически очищаются при остановке ресурса.


Курсор и ввод

javascript
varion.isKeyDown(varion.KeyCode.E);     // по коду или имени
varion.showCursor(true);                // показать/скрыть курсор
varion.getCursorPos(true);              // { x, y } (true = нормализованные 0–1)
varion.setCursorPos({ x, y }, true);
varion.toggleGameControls(false);       // отключить управление игрой
varion.gameControlsEnabled();           // → boolean
  • varion.KeyCode (алиас varion.Key) — карта имён клавиш в коды (AZ, F1F12, Numpad0Numpad9, Shift, Ctrl, Space, MouseLeft и т.д.).
  • varion.GamepadButton — карта кнопок геймпада (A, B, X, Y, LB, RB, DPadUp и т.д.).

Keybind

javascript
const kb = new varion.Keybind(varion.KeyCode.E, /* hold */ false);
kb.on('pressed', () => varion.log('E down'));
kb.on('released', () => varion.log('E up'));
kb.gameControlsOnly = true;   // не срабатывать при выключенном управлении
kb.enableInUi = false;        // не срабатывать при активном фокусе WebView/курсоре
kb.repeatIntervalMs = 0;      // >0 — авто-повтор при удержании
kb.isPressed;                 // текущее состояние
kb.destroy();

Сущности

BaseObjectType

javascript
varion.BaseObjectType
// { Player:0, Vehicle:1, Ped:2, Object:3, Blip:4, ColShape:7,
//   Checkpoint:8, VirtualEntity:9, Marker:22, TextLabel:23 }

Базовый Entity

javascript
varion.Entity.getByID(type, id);
varion.Entity.getByRemoteID(type, remoteId);
varion.Entity.getByScriptID(scriptId);
varion.Entity.all;

Общие геттеры экземпляра: id, remoteId, isRemote, type, scriptID, valid, isStreamedIn, streamed, isSpawned, dimension, isDead, speed, visible, alpha, nativeModel, heading, pos, rot.

Методы экземпляра:

javascript
entity.exists();
entity.destroy();
entity.setPos(x, y, z);
entity.setRot(x, y, z);
await entity.setVisible(true);
await entity.setAlpha(200, false);
await entity.resetAlpha();
entity.attachTo(target, bone, offset, rotation, useSoftPinning, collision, fixedRot);
entity.detach();
entity.setCollision(true, true);
await entity.freezePosition(true);
entity.getVariable(key);        // synced-мета
entity.hasVariable(key);
await entity.isDeadAsync();     // точное чтение с game-thread
await entity.getSpeedAsync();
await entity.existsAsync();

setPos/setRot/destroy для чужих игроков server-authoritative и вернут false.

Player

javascript
const me = varion.Player.local;
varion.Player.get(id);
varion.Player.getByID(id);
varion.Player.getByRemoteID(id);
varion.Player.getByScriptID(scriptId);
varion.Player.all;         // включая локального
varion.Player.streamedIn;  // только застримленные
varion.Player.count;
varion.getPlayers();       // = Player.all

Ключевые геттеры игрока: name (remote), model, health, armour, currentWeapon, currentAmmo, currentWeaponComponents, currentWeaponTintIndex, moveSpeed, forwardSpeed, strafeSpeed, speedVector, aimPos, headRot, entityAimingAt, vehicle, seat, netOwner, isTalking, micLevel, а также флаги состояния isAiming, isJumping, isShooting, isCrouching, isStealthy, isInRagdoll, isReloading, isEnteringVehicle, isLeavingVehicle, isOnLadder, isInMelee, isInCover, isParachuting, flashlightActive.

Player.local дополнительно: weapon, ammoInClip, interiorId, maxHealth, maxArmour, dimension, isDead, isSpawned. Методы: hasWeaponComponent(weapon, component), getWeaponTintIndex(weapon).

Vehicle, Object, Ped

javascript
varion.Vehicle.get(id);        // .all / .streamedIn / .count / .getByID /
                               // .getByRemoteID / .getByScriptID
varion.getVehicles();

varion.Object.get(id);         // тот же набор статик-методов
varion.getObjects();

varion.Ped.get(id);            // тот же набор статик-методов
varion.getPeds();

Геттеры Vehicle: model, speedVector, engineOn, engineHealth, petrolTankHealth, gear, rpm, steeringAngle, lockState, isDestroyed, handling, netOwner.

VirtualEntity

javascript
varion.VirtualEntity.get(id);          // .all / .streamedIn / .getByRemoteID
varion.VirtualEntityGroup.get(id);     // .all
varion.VirtualEntityGroup.cellKey(x, y, 100);

Выборка по измерению (dimension)

javascript
varion.getPlayersInDimension(dim);
varion.getVehiclesInDimension(dim);
varion.getObjectsInDimension(dim);
varion.getPedsInDimension(dim);
varion.getEntitiesInDimension(dim);

Метаданные сущности

javascript
entity.getMeta(key);        entity.setMeta(key, value);   // локальная мета
entity.hasMeta(key);        entity.deleteMeta(key);
entity.getSyncedMeta(key);  entity.hasSyncedMeta(key);    // синхронизированная сервером
entity.getStreamSyncedMeta(key);                          // stream-synced
entity.getMetaDataKeys();   entity.getSyncedMetaKeys();

Локальные сущности (только клиент)

Создаются и живут только на клиенте, без network ID и без синхронизации с сервером. Полезны для декоративных педов, объектов и транспорта.

javascript
const ped = new varion.LocalPed(model, { x, y, z }, { x, y, z });
const obj = new varion.LocalObject(model, { x, y, z }, { x, y, z }, /* noOffset */ false);
const veh = new varion.LocalVehicle(model, { x, y, z }, { x, y, z });

obj.pos = { x, y, z };   // pos / rot / frozen / collision / visible — get/set
obj.frozen = false;
obj.destroy();

Про scriptID: сразу после конструктора scriptID равен 0, а id отрицательный (локальный идентификатор). Как только движок закоммитит сущность в мир, scriptID становится ненулевым GTA-хендлом, и срабатывают события gameEntityCreate / baseObjectCreate. Проверяйте entity.isSpawned или ждите gameEntityCreate, прежде чем звать натив-хендлы по scriptID.

varion.WeaponObject(model, pos, rot, ammo, showWorldModel) — отдельный локальный объект-оружие с методом destroy().


Мировые объекты

Классы Blip, Marker, Checkpoint, ColShape, TextLabel — статики all, count, get(id), getByID(id), getByRemoteID(id)Blip ещё getByScriptID).

javascript
const blip = varion.Blip.get(id);
blip.sprite = 1; blip.color = 5; blip.scale = 1.2;   // get/set
blip.name = 'Shop'; blip.shortRange = true; blip.route = false;
blip.pos = { x, y, z };                              // + radius/width/height, isRadius/isArea

const mk = varion.Marker.get(id);
mk.markerType = 1; mk.scale = 2; mk.color = { r, g, b, a };

const cp = varion.Checkpoint.get(id);
cp.checkpointType = 1; cp.radius = 3; cp.height = 2; cp.color = { r, g, b, a };

const cs = varion.ColShape.get(id);       // colshapeType / radius / height /
                                          // halfExtents / points / pos / dimension

// Локальный 3D-текст:
const label = new varion.TextLabel('Hello', 0, { x, y, z }, 1, { r:255,g:255,b:255,a:255 }, true, 0);
label.destroy();

Глобальная и локальная мета

javascript
// Локальная (синтетическая, только клиент)
varion.setMeta(key, value);  varion.getMeta(key);  varion.hasMeta(key);
varion.deleteMeta(key);      varion.getMetaKeys();

// Синхронизированная сервером глобальная (read-only на клиенте)
varion.getSyncedMeta(key);   varion.hasSyncedMeta(key);   varion.getSyncedMetaKeys();

// Локальная мета игрока
varion.setLocalMeta(key, value);  varion.getLocalMeta(key);
varion.hasLocalMeta(key);         varion.deleteLocalMeta(key);  varion.getLocalMetaKeys();

// Запрос установки stream-synced меты (уходит на сервер)
varion.setStreamSyncedMeta(key, value);
varion.deleteStreamSyncedMeta(key);

Голос

javascript
varion.Voice.volume = 1;              // 0–2
varion.Voice.muteInput = true;        // заглушить свой микрофон
varion.Voice.activationLevel = 37;    // 0–100 (voice-activation)
varion.Voice.noiseSuppressionEnabled = true;
varion.Voice.inputDevice = deviceUuid;
varion.Voice.activityInputEnabled = true;
varion.Voice.toggleInput(true);       // push-to-talk вручную
varion.Voice.mutePlayer(player);      varion.Voice.unmutePlayer(player);
varion.Voice.isPlayerTalking(player); varion.Voice.isPlayerMuted(player);
varion.Voice.getPlayersInChannel(channelId);
varion.Voice.getAvailableInputDevices();
varion.Voice.clearLocallyMuted();

const ch = varion.Voice.getChannel(channelId);   // или varion.VoiceChannel.getByID(id)
ch.spatial; ch.maxDistance; ch.volume; ch.members; ch.muted; ch.filter;
ch.getPlayers(); ch.isActive();

const filter = varion.AudioFilter.create('echo');   // по имени или hash

varion.muteInput(true);
varion.toggleVoiceControls(true);
varion.clearLocallyMuted();

Аудио

javascript
const snd = varion.Audio.create(varion.assetUrl('mymode', 'sfx/click.wav'), 1);
snd.loop = false; snd.category = 'sfx';
await snd.play();  snd.pause();  snd.stop();  snd.seek(2);
snd.setVolume(0.5); snd.destroy();
snd.playing; snd.currentTime; snd.duration; snd.playbackRate;

varion.Audio.playFrontend(url, 1);      // фронтенд-звук (2D)

// 3D-звук: добавьте world-output
snd.addOutput(new varion.AudioOutputWorld({ x, y, z }, 50));

const cat = varion.AudioCategory.get('sfx');  cat.volume = 0.8;

HTTP

javascript
const res = await varion.Http.get('/server-info.json');
// { ok, status, statusCode, url, text, body, headers }
const data = await varion.Http.getJson('/data.json');   // + res.json

const r = await varion.fetch('/api', { method: 'POST', body: JSON.stringify({}) });

const client = varion.HttpClient.create();
client.setExtraHeader('X-Auth', token);
await client.get(url);   // + head/post/put/delete/patch/options/connect/trace

Запросы разрешены только на host/port из manifest-http ресурса или из его asset-pack; игровой порт 7788 заблокирован.


Ресурсы

javascript
varion.Resource.all;                    // все ресурсы
varion.Resource.current;                // текущий (в контексте выполнения)
varion.Resource.getByName('mymode');    // или varion.Resource.get('mymode')
varion.Resource.resolveAsset('mymode', 'ui/index.html');
varion.Resource.getPath('mymode', 'client/main.js');

varion.getResources();                  // = Resource.all
varion.getResourceConfig('mymode');     // объект config из манифеста
varion.getResourcePath('mymode', 'client/main.js');
varion.hasResource('mymode');

// Экспорты между ресурсами (client-local, без сервера)
varion.exports.foo = () => 42;                    // регистрируем на своём ресурсе
varion.exports = { foo, bar };                    // или пачкой
varion.getResourceExports('other').foo();         // вызываем чужой экспорт
const other = varion.require('other');            // бросит, если ресурс не найден

URL и ассеты

javascript
varion.httpUrl('cef/index.html');                 // базовый HTTP-сервер ресурса
varion.assetUrl('mymode', 'ui/index.html');       // asset-pack ресурса
varion.streamUrl('mymode', 'vehicles/adder.ytd'); // stream-ассеты ресурса
varion.streamCachePath('mymode', 'file.ytd');     // путь в локальном stream-кэше

Хранилище

javascript
varion.LocalStorage.set('token', 'value');
varion.LocalStorage.get('token');
varion.LocalStorage.has('token');
varion.LocalStorage.delete('token');   // = remove
varion.LocalStorage.clear();           // = deleteAll
varion.LocalStorage.save();            // персист на диск

LocalStorage автоматически сохраняется при resourceStop.


Файлы

javascript
await varion.File.write('cache:save.json', JSON.stringify(data));
const text = await varion.File.read('cache:save.json', 'utf8');
await varion.File.exists('cache:save.json');   // → boolean
await varion.File.delete('cache:save.json');
varion.File.resolvePath('resource:mymode/data.json');

varion.readFile(path);          // алиасы
varion.writeFile(path, data);

Камера и экран

javascript
varion.getCamPos();            // { x, y, z }
varion.getCamRot();            // { x, y, z }
varion.getCamFov();            // number
varion.getCamForwardVector();  // { x, y, z }
varion.getScreenResolution();  // { x, y }

varion.screenToWorld(0.5, 0.5, 100);              // синхронно (луч)
await varion.screenToWorldAsync(0.5, 0.5, 500);   // точный game-thread pick
await varion.worldToScreenAsync(x, y, z);         // { x, y, z } нормализ.
varion.worldToScreen(x, y, z);                    // синхронно (из кэша)

varion.copyToClipboard('text');

Статистика (stats)

javascript
await varion.getStat('MP0_CASH');           await varion.setStat('MP0_CASH', 1000);
await varion.getStatFloat('name');          await varion.setStatFloat('name', 1.5);
await varion.getStatBool('name');           await varion.setStatBool('name', true);
varion.resetStat('name');                   varion.resetAllStats(0);

varion.getPackedStat(index, 0);             varion.setPackedStat(index, value, 0);
varion.getPackedStatBool(index, 0);         varion.setPackedStatBool(index, value, 0);

getStat* / setStat* работают через game-bridge и возвращают Promise.


Разрешения и снимки экрана

javascript
varion.Permission;        // { None:0, ScreenCapture:1, WebRTC:2, Microphone:3, Clipboard:4, All:255 }
varion.PermissionState;   // { Allowed:0, Denied:1, Unspecified:2, Failed:3 }

varion.getPermissionState(varion.Permission.ScreenCapture);
varion.hasPermission(varion.Permission.Microphone);
const state = await varion.requestPermission(varion.Permission.ScreenCapture);

const base64 = await varion.takeScreenshot();          // весь экран (base64 PNG)
const gameOnly = await varion.takeScreenshotGameOnly(); // только игровой кадр

takeScreenshot при необходимости сам запросит разрешение ScreenCapture.


WebSocket и Worker

javascript
const ws = new varion.WebSocketClient('wss://example/path');
ws.on('open', () => ws.send('hi'));
ws.on('message', (data) => {});
ws.on('close', (code, reason) => {});
ws.autoReconnect = true;
ws.addSubProtocol('json');  ws.setExtraHeader('X-Auth', token);
ws.start();  ws.stop();  ws.destroy();
varion.WebSocketReadyState;   // { CONNECTING, OPEN, CLOSING, CLOSED }

const worker = new varion.Worker(varion.assetUrl('mymode', 'worker.js'));
worker.on('message', (data) => {});
worker.start();  worker.pause();  worker.resume();  worker.destroy();

Discord

javascript
varion.Discord.isReady();          // готовность
varion.Discord.currentUser;        // { id, name, discriminator, avatar } | null
varion.Discord.updateActivity({ details: 'In game', state: 'Freeroam', largeImageKey: 'logo' });
varion.Discord.getActivity();
varion.Discord.clearActivity();
await varion.Discord.requestOAuth2Token(appId);
varion.on('discord:ready', (user) => {});

Handling и MapZoom

javascript
const hd = varion.HandlingData.getForName('adder');   // или .getForHash(hash)
hd.acceleration; hd.brakeForce; hd.maxTraction; /* ... */
hd.setField('acceleration', 0.5);
await hd.applyTo(vehicle);
varion.getVehicleHandling(vehicle);
varion.HandlingData.reloadVehiclePhysics(modelHash);

const zoom = varion.MapZoomData.get('MAIN_MAP');
zoom.fZoomScale = 1.2;
varion.MapZoomData.resetAll();

Сервер, соединение и диагностика

javascript
varion.getServerHost();  varion.getServerIp();  varion.getServerPort();  varion.getServerName();
varion.getPing();
varion.isConnected();
varion.getConnectionPhase();   // 'idle' | 'ready' | ...
varion.isPaused();  varion.isMenuOpen();  varion.isRadarHidden();
varion.getFps();  varion.getTotalPacketsSent();  varion.getTotalPacketsLost();

varion.getLocale();            // varion.locale
varion.LicenseType;            // { None, Rockstar, Steam, Epic, Xbox }
varion.getLicenseType();  varion.getLicenseHash();

varion.getGxtText('key');      // текст GXT-метки

Погода и config-флаги

javascript
varion.setWeatherCycle(['CLEAR', 'RAIN'], [10, 5]);
varion.setWeatherSyncActive(true);
varion.setConfigFlag('flagName', true);
varion.getConfigFlag('flagName');
varion.loadYtyp('name');   varion.unloadYtyp('name');

Утилиты

varion.Utils — векторная математика и хелперы:

javascript
varion.Utils.distance(a, b);       varion.Utils.squaredDistance(a, b);
varion.Utils.vectorLength(v);      varion.Utils.normalize(v);
varion.Utils.dot(a, b);            varion.Utils.cross(a, b);
varion.Utils.add(a, b);            varion.Utils.sub(a, b);
varion.Utils.mul(v, s);            varion.Utils.divide(v, s);  varion.Utils.neg(v);
varion.Utils.lerp(a, b, t);        varion.Utils.clamp(v, min, max);
varion.Utils.degToRad(d);          varion.Utils.radToDeg(r);
varion.Utils.randomInt(min, max);  varion.Utils.isNaN(v);
await varion.Utils.wait(500);      // Promise-задержка
await varion.Utils.registerPedheadshotBase64(ped);   // + registerPedheadshot3Base64 / *Transparent*

const b64 = await varion.getHeadshotBase64(headshotId);

const p = new varion.Profiler();
p.timeStart('x');  const ms = p.timeEnd('x');
varion.Profiler.fps;  varion.Profiler.tickMs;  varion.Profiler.nativeCalls;

varion.getGamepads();          // массив Gamepad
varion.Gamepad.get(0);         // .connected / .axisLeftX / .isButtonPressed(btn)

UI: WebView и RmlDocument

Полный справочник по WebView — на странице WebView.

javascript
const view = varion.WebView.create({ url: varion.assetUrl('ui-pack', 'index.html'), overlay: true });
view.visible = true;
view.on('hud:ready', () => {});
view.emit('hud:setHealth', 200);

// RmlDocument — HTML/WebView-бэкенд (нативного RmlUi-рендерера нет; .html грузится
// в WebView, .rml показывает уведомление):
const doc = new varion.RmlDocument(varion.assetUrl('ui-pack', 'menu.html'));
doc.show(false, true);   doc.hide();   doc.update();

Stream-события

javascript
varion.on('stream:ready', (...mounts) => {
  // по одному аргументу на каждый примонтированный ресурс
  for (const mount of mounts) varion.log(`${mount.name} -> ${mount.streamBase}`);
});
varion.on('stream:updated', (...mounts) => {});
varion.on('stream:mounted', (stats) => {});   // { registered, existing, failed, ... }

Каждый mount — объект { name, streamBase } (IStreamResourceMount). Это не строка с именем ресурса; при полном ремаунте приходят все ресурсы сразу (для одного ресурса — один объект).


GTA Natives

javascript
// Вызов по имени (camelCase)
varion.natives.setEntityVisible(scriptId, true, false);
varion.natives.freezeEntityPosition(scriptId, true);

// Вызов по хешу
varion.natives.invoke('0x262B14F48D29DE80', pedHandle, 11, 1, 0, 0);
varion.natives.invokeFloat('0xEEF059FAD016D209', pedHandle);
varion.natives.invokeVector3('0x1EB9E7DF7E839CAF', x, y, z, heading, rx, ry, rz);

// Реальное возвращаемое значение — через async-варианты
const health = await varion.natives.invokeAsync('GET_ENTITY_HEALTH', scriptId);

varion.game — тот же bridge плюс joaat. Синхронный invoke для большинства read-нативов возвращает placeholder; за реальным значением используйте invokeAsync / invokeFloatAsync / invokeStringAsync / invokeVector3Async. Подробнее — на странице GTA natives.


Client JS нельзя считать trusted с точки зрения gameplay/security. Важные gameplay-, economy- и permission-действия проверяйте на сервере.

Source backing

Страница построена по runtime-файлам sdk/client-js-runtime/injected/core-bootstrap.js, events-bootstrap.js, entities-bootstrap.js, services-bootstrap.js, world-bootstrap.js, interaction-bootstrap.js, platform-bootstrap.js, dispatch-bootstrap.js, mvalue-bootstrap.js и client/src/stream/CStreamResourceClient.cpp.

Varion Multiplayer Platform