Compare commits

..

3 Commits

Author SHA1 Message Date
min
d45a55031f Merge pull request 'Team Create: ������� �������� + ����� 5 ���������' (#36) from restore/all-tasks into main
All checks were successful
CI / Lint (push) Successful in 1m8s
CI / Build (push) Successful in 1m58s
CI / Secret scan (push) Successful in 22s
CI / PR size check (push) Has been skipped
CI / Deploy to S1 + S2 (push) Successful in 3m28s
2026-06-08 03:39:29 +00:00
min
73d7ae4765 merge main (синхрон перед PR синхрона скриптов)
All checks were successful
CI / Lint (pull_request) Successful in 1m6s
CI / Build (pull_request) Successful in 1m59s
CI / Secret scan (pull_request) Successful in 28s
CI / PR size check (pull_request) Successful in 10s
CI / Deploy to S1 + S2 (pull_request) Has been skipped
2026-06-08 06:28:56 +03:00
min
58edaef2ab fix(studio): Team Create — синхрон скриптов (upsertScript/removeScript)
Раньше синхронизировались только примитивы/модели/блоки, а скрипты нет —
у соавтора было 0 скриптов. Перехватываем scene.upsertScript/removeScript,
шлём op scriptUpsert/scriptRemove; applyRemoteOp применяет их у соавтора
(список в Hierarchy обновляется штатным setInterval). Лимит соавторов 5
(MAX_COLLABORATORS в realtime StudioRoom, задеплоен на VM110).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 06:28:45 +03:00

View File

@ -161,6 +161,48 @@ export class StudioCollab {
return r;
};
}
// Скрипты — синхрон создания/редактирования (upsertScript) и удаления
// (removeScript). Скрипты живут в scene._scripts[] ({id, code, target,
// name}); UI зовёт scene.upsertScript / scene.removeScript.
const sc = this.scene;
if (sc && !sc.__collabScriptsPatched) {
sc.__collabScriptsPatched = true;
if (typeof sc.upsertScript === 'function') {
const origUpsert = sc.upsertScript.bind(sc);
sc.upsertScript = function (id, code, target, name) {
const r = origUpsert(id, code, target, name);
if (!self._applyingRemote) {
// id может быть сгенерён внутри upsertScript, если был null —
// достаём фактический из _scripts (последний с этим code).
let realId = id;
if (realId == null) {
const arr = sc._scripts || [];
realId = arr.length ? arr[arr.length - 1].id : null;
}
const rec = (sc._scripts || []).find((s) => s.id === realId);
if (rec) {
self.sendOp({
op: 'scriptUpsert',
id: rec.id,
code: rec.code,
target: rec.target ?? null,
name: rec.name ?? null,
});
}
}
return r;
};
}
if (typeof sc.removeScript === 'function') {
const origRemoveScript = sc.removeScript.bind(sc);
sc.removeScript = function (id) {
const r = origRemoveScript(id);
if (!self._applyingRemote) self.sendOp({ op: 'scriptRemove', id });
return r;
};
}
}
}
/** Снять обёртки (при выходе из коллаба восстановить оригиналы — простой флаг). */
@ -387,6 +429,17 @@ export function applyRemoteOp(scene, op) {
case 'blockRemove':
bm?.removeBlock?.(op.x, op.y, op.z);
return;
case 'scriptUpsert':
// Создание/редактирование скрипта у соавтора. _applyingRemote уже
// выставлен (см. _applyRemoteOp) → обёртка upsertScript не зашлёт
// эхо обратно. _onSceneChange внутри обновит React-панели.
scene.upsertScript?.(op.id, op.code, op.target ?? null, op.name ?? null);
scene._onCollabScriptsChange?.();
return;
case 'scriptRemove':
scene.removeScript?.(op.id);
scene._onCollabScriptsChange?.();
return;
}
switch (t) {
case 'add': {