From b83c9bb75c863910f0b5b0ca8f3813b17e99c477 Mon Sep 17 00:00:00 2001 From: min Date: Tue, 9 Jun 2026 20:38:49 +0300 Subject: [PATCH] =?UTF-8?q?fix(g20):=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20api.setNpcLocalRef?= =?UTF-8?q?=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20=D0=BF=D1=80=D1=8F?= =?UTF-8?q?=D0=BC=D0=BE=D0=B3=D0=BE=20access?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lua-runtime FATAL: 'Cannot access api before initialization' — я обращался к api._localToRealNpc на 1852 до const api = на 2027. Фикс: - _localToRealNpc объявил как const до api (доступен в closures) - api.setNpcLocalRef(localRef, realRef) — публичный метод - GameRuntime: sb.api.setNpcLocalRef?.(ref, 'npc:'+npcId) - В fireGlobalEvent npcDeath используем _localToRealNpc напрямую --- src/editor/engine/GameRuntime.js | 2 +- src/editor/engine/lua/RobloxShim.js | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/editor/engine/GameRuntime.js b/src/editor/engine/GameRuntime.js index b58be19..fb01928 100644 --- a/src/editor/engine/GameRuntime.js +++ b/src/editor/engine/GameRuntime.js @@ -2153,7 +2153,7 @@ export class GameRuntime { // npc.onDeath по локальному ref находил npcId. for (const sb of this.sandboxes) { if (sb.api?._localToRealNpc) { - try { sb.api._localToRealNpc.set(payload.ref, 'npc:' + npcId); } catch (_) {} + try { sb.api.setNpcLocalRef?.(payload.ref, 'npc:' + npcId); } catch (_) {} } } } diff --git a/src/editor/engine/lua/RobloxShim.js b/src/editor/engine/lua/RobloxShim.js index cd86def..7a52f66 100644 --- a/src/editor/engine/lua/RobloxShim.js +++ b/src/editor/engine/lua/RobloxShim.js @@ -1849,7 +1849,7 @@ export function registerRobloxShim(lua, opts) { // Возвращает локальный ref (строку 'npc_lua_N'), который можно передавать // в __rbxl_npc_say(ref, text, duration). let _nextNpcRef = 0; - api._localToRealNpc = new Map(); + const _localToRealNpc = new Map(); global.set('__rbxl_spawn_npc', (modelType, x, y, z, name, hp, speed) => { const ref = 'npc_lua_' + (_nextNpcRef++); send('npc.spawn', { @@ -1895,7 +1895,6 @@ export function registerRobloxShim(lua, opts) { global.set('__rbxl_npc_on_death', (ref, fn) => { if (typeof fn === 'function') _npcDeathCbs.set(String(ref || ''), fn); }); - api._npcDeathCbs = _npcDeathCbs; // Инвентарь invUI — паритет с JS game.inventory.add(itemId, count). // Сначала определяем итем (один раз), потом добавляем. const _localInventory = new Map(); @@ -2026,6 +2025,11 @@ export function registerRobloxShim(lua, opts) { // вроде __rbxl_player_pos и updatePlayerPos могли его видеть. const api = { _realPlayerPos: null, + // GameRuntime зовёт после npc.spawn-резолва: маппинг локального + // ref ('npc_lua_N') на реальный ('npc:'). Нужно для npcDeath. + setNpcLocalRef(localRef, realRef) { + _localToRealNpc.set(String(localRef), String(realRef)); + }, onSceneSnapshot(snap) { try { const prims = snap?.primitives || []; @@ -2247,10 +2251,8 @@ export function registerRobloxShim(lua, opts) { const realRef = 'npc:' + p.npcId; // Ищем локальный ref по реальному let localRef = null; - if (api._localToRealNpc) { - for (const [k, v] of api._localToRealNpc.entries()) { - if (v === realRef) { localRef = k; break; } - } + for (const [k, v] of _localToRealNpc.entries()) { + if (v === realRef) { localRef = k; break; } } // Вызываем все cb с подходящим ref if (_npcDeathCbs.size > 0) {