UNPKG

rock-mod

Version:

Rock-Mod is a powerful framework designed for creating and managing mods for Grand Theft Auto (GTA) games.

75 lines (74 loc) 3.18 kB
import { ClientInternalEventName } from "../../common/events/types"; const TARGET_FPS = 60; const TICK_INTERVAL_MS = Math.floor(1000 / TARGET_FPS); /** * Достаём `setInterval` из global scope не вызывая ReferenceError. * * Под bare deno_core просто `setInterval` бросает `ReferenceError: setInterval * is not defined` ещё до того как мы можем проверить `typeof`. `globalThis` * безопасен — обращение к несуществующему свойству даёт `undefined`. */ function getSetInterval() { const fn = globalThis.setInterval; return typeof fn === "function" ? fn : null; } function getClearInterval() { const fn = globalThis.clearInterval; return typeof fn === "function" ? fn : null; } function getNativeRenderEventSource() { const maybeCcmp = globalThis.ccmp; return typeof (maybeCcmp === null || maybeCcmp === void 0 ? void 0 : maybeCcmp.on) === "function" ? maybeCcmp : null; } /** * Per-frame событие `rm::render` под CCMP. * * У RageMP клиента есть нативный raw-event `render`, на котором завязаны * декораторы `@Render` и `@Interval` в геймоде. Современный CCMP runtime * эмитит coalesced native `ccmp.on("render")` из game loop; используем его, * чтобы render не зависел от JS timer pump и не копился в очереди. * * `setInterval` остаётся только fallback'ом для старых runtime. */ export class CCMPRenderTicker { constructor() { this._emitter = null; this._handle = null; this._nativeRenderRegistered = false; } start(emitter) { var _a; this._emitter = emitter; const nativeRender = getNativeRenderEventSource(); if (nativeRender) { if (!this._nativeRenderRegistered) { this._nativeRenderRegistered = true; (_a = nativeRender.on) === null || _a === void 0 ? void 0 : _a.call(nativeRender, "render", () => { var _a; (_a = this._emitter) === null || _a === void 0 ? void 0 : _a.emitInternal(ClientInternalEventName.Render); }); } return; } if (this._handle !== null) return; const setIntervalFn = getSetInterval(); if (!setIntervalFn) { console.warn('[CCMPRenderTicker] native `ccmp.on("render")` and `setInterval` are unavailable. ' + "`rm::render` will not be emitted."); return; } this._handle = setIntervalFn(() => { var _a; (_a = this._emitter) === null || _a === void 0 ? void 0 : _a.emitInternal(ClientInternalEventName.Render); }, TICK_INTERVAL_MS); } stop() { if (this._handle !== null) { const clearIntervalFn = getClearInterval(); clearIntervalFn === null || clearIntervalFn === void 0 ? void 0 : clearIntervalFn(this._handle); this._handle = null; } this._emitter = null; } }