feat(rbxl): XML-������ ������ .rbxl + Day/Night + Tool/Mouse/Backpack flow #38
124
RBXL_SOURCES.md
Normal file
124
RBXL_SOURCES.md
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# Реестр источников .rbxl / .rbxlx для портирования в Рублокс
|
||||||
|
|
||||||
|
Цель: легально добыть Roblox Place-файлы (.rbxl бинарный / .rbxlx XML) по жанрам
|
||||||
|
для портирования и публикации на Рублоксе.
|
||||||
|
|
||||||
|
**Форматы:** `.rbxlx` (XML — предпочтителен, читаемый, легко парсить геометрию/CFrame)
|
||||||
|
· `.rbxl` (бинарный, конвертировать) · `.rbxm`/`.rbxmx` (модели, не целые места).
|
||||||
|
|
||||||
|
> ⚠️ **Главное про публикацию:** «uncopylocked» ≠ свободная лицензия. Для ПУБЛИКАЦИИ
|
||||||
|
> порта на Рублоксе безопасны только: репо с явной **MIT/Apache/MPL/CC0/CC-BY** +
|
||||||
|
> официальные ассеты Roblox с разрешением. Архивы чужих игр — только для
|
||||||
|
> обучения/прототипа парсера, НЕ для публикации. Lua-скрипты не портируются
|
||||||
|
> автоматом — логику переписываешь сам (это и снижает юр.риски).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ИНСТРУМЕНТЫ (распаковка/парсинг)
|
||||||
|
|
||||||
|
| Инструмент | URL | Назначение | Лицензия |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Rojo | https://github.com/rojo-rbx/rojo | place ↔ файлы | MPL-2.0 |
|
||||||
|
| rbxlx-to-rojo | https://github.com/rojo-rbx/rbxlx-to-rojo | .rbxl/.rbxlx → проект | MPL/MIT (проверить) |
|
||||||
|
| rbxfile (Go) | https://github.com/robloxapi/rbxfile | парсинг rbxl/rbxlx/rbxm | MIT (проверить) |
|
||||||
|
| remodel | https://github.com/rojo-rbx/remodel | скриптовая обработка | MPL-2.0 |
|
||||||
|
| RobloxAPI/spec | https://github.com/RobloxAPI/spec/blob/master/formats/rbxl.md | спека бинарного формата | docs |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## (А) ОФИЦИАЛЬНЫЕ — самые надёжные
|
||||||
|
|
||||||
|
### A1. Roblox/Old-Open-Source-Levels — классика от самой Roblox Corp ⭐
|
||||||
|
- https://github.com/Roblox/Old-Open-Source-Levels
|
||||||
|
- Каталог: https://github.com/Roblox/Old-Open-Source-Levels/blob/master/catalog.md
|
||||||
|
- ~30+ мест 2007-2013 (.rbxl). Жанры: Crossroads (арена/PvP), Castle Warfare,
|
||||||
|
ROBLOX Battle (бой), Sword Fight in the Dark (PvP), Haunted Mansion (хоррор),
|
||||||
|
Glass Houses, Pinball Wizards, Happy Home in Robloxia (песочница/мини).
|
||||||
|
- Лицензия: «free to manipulate however you wish» — **проверь файл LICENSE вручную** перед публикацией.
|
||||||
|
|
||||||
|
### A2. Встроенные шаблоны Roblox Studio
|
||||||
|
- Список: https://create.roblox.com/docs/resources/templates
|
||||||
|
- В Studio: открыть шаблон → File → Save to File → .rbxlx
|
||||||
|
- Baseplate, Castle, Suburban, Village, Racing, Classic Obby, Team Deathmatch/Combat,
|
||||||
|
Capture the Flag, Line Runner, Pirate Island, Modern City и др.
|
||||||
|
- Серая зона для публикации «как есть» — используй как базу/учёбу, геометрию делай своей.
|
||||||
|
|
||||||
|
### A3. creator-docs (документация Roblox, open)
|
||||||
|
- https://github.com/Roblox/creator-docs
|
||||||
|
|
||||||
|
### A4. Internet Archive — Crossroads (все версии 2007-2017)
|
||||||
|
- https://archive.org/details/roblox_crossroads
|
||||||
|
- https://archive.org/details/classic-crossroads_202408
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## (Б) РЕПОЗИТОРИИ С КОДОМ/МЕСТАМИ (URL из поиска)
|
||||||
|
|
||||||
|
### С подтверждённой свободной лицензией (можно публиковать)
|
||||||
|
| Репо | URL | Лицензия | Жанр |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Vigilant | https://github.com/IsoLogicGames/Vigilant | **MIT** ✅ | co-op horde-survival (шутер) |
|
||||||
|
| crossroads-rojo | https://github.com/Dekkonot/crossroads-rojo | наследует Crossroads | арена |
|
||||||
|
|
||||||
|
### Open-source игры (лицензию проверить у каждого — файл LICENSE)
|
||||||
|
| Репо | URL | Жанр |
|
||||||
|
|---|---|---|
|
||||||
|
| Miner's Haven | https://github.com/berezaa/minershaven | tycoon/симулятор |
|
||||||
|
| roblox-gym-tycoon | https://github.com/jason-lee88/roblox-gym-tycoon | tycoon |
|
||||||
|
| Racing-Kit-Roblox | https://github.com/Astrophsica/Racing-Kit-Roblox | гонки |
|
||||||
|
| RENTED_old_rbx | https://github.com/ReRand/RENTED_old_rbx | хоррор |
|
||||||
|
| roblox-rpg | https://github.com/mobyrblx/roblox-rpg | RPG/демо |
|
||||||
|
| RobloxGames (dwmk) | https://github.com/dwmk/RobloxGames | разное |
|
||||||
|
| recsObby | https://github.com/Nimblz/recsObby | obby |
|
||||||
|
| WavyRobloxObby | https://github.com/sammy0127/WavyRobloxObby | obby (.rbxlx) |
|
||||||
|
| Sight-Obby | https://github.com/TeoJJss/Sight-Obby | obby |
|
||||||
|
| fps (Anninzy) | https://github.com/Anninzy/fps | FPS |
|
||||||
|
| roblox-game-example | https://github.com/areshaistg/roblox-game-example | демо-каркас |
|
||||||
|
|
||||||
|
### Архивы чужих игр (ТОЛЬКО обучение/прототип, НЕ публикация — смешанные права)
|
||||||
|
| Репо | URL |
|
||||||
|
|---|---|
|
||||||
|
| uncopylocked-game-collection | https://github.com/Kitaske/uncopylocked-game-collection |
|
||||||
|
| robloxplacearchive | https://github.com/tropicalbananas/robloxplacearchive |
|
||||||
|
| RobloxRBXLArchive | https://github.com/LuaGunsX/RobloxRBXLArchive |
|
||||||
|
| Biggest Uncopylocked Library | https://github.com/KH0DIN/Biggest_Uncopylocked_Roblox_Games_Library |
|
||||||
|
| GitHub topics | https://github.com/topics/rbxlx · /rbxl · /rbxm · /rojo · /uncopylocked |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## (В) САЙТЫ ДЛЯ САМОСТОЯТЕЛЬНОГО СКАЧИВАНИЯ
|
||||||
|
|
||||||
|
### Прямое скачивание .rbxl/.rbxlx
|
||||||
|
- **GitHub code search** (вход обязателен): `extension:rbxlx`, `extension:rbxl`,
|
||||||
|
`filename:default.project.json` (корень Rojo-проекта рядом с местом)
|
||||||
|
https://github.com/search?q=extension%3Arbxlx&type=code
|
||||||
|
- **GitHub Topics:** https://github.com/topics/rbxlx · https://github.com/topics/rojo
|
||||||
|
- **Internet Archive:** https://archive.org/ — поиск «roblox place», «rbxl», «crossroads»
|
||||||
|
|
||||||
|
### CC0/CC-BY геометрия для воссоздания (юридически чистейший путь, не .rbxl но low-poly близко к Roblox)
|
||||||
|
- **Kenney** (CC0): https://kenney.nl/assets — Platformer/Nature/Car/Pirate/City/Prototype Kit, Blocky Characters
|
||||||
|
- **OpenGameArt** (CC0/CC-BY): https://opengameart.org/ — voxel/low-poly паки
|
||||||
|
- **itch.io** (фильтр assets+CC0): https://itch.io/game-assets/free/tag-low-poly
|
||||||
|
- **Poly Pizza** (CC0/CC-BY low-poly): https://poly.pizza/
|
||||||
|
- **Quaternius** (CC0 low-poly паки): https://quaternius.com/
|
||||||
|
|
||||||
|
### Сообщества с открытыми играми (часто прямые ссылки + лицензия)
|
||||||
|
- DevForum «free & open-sourced games»: https://devforum.roblox.com/t/lots-of-free-open-sourced-games/525670
|
||||||
|
- DevForum «Open Source Arena FPS»: https://devforum.roblox.com/t/open-source-arena-fps/1034576
|
||||||
|
- Uplift Games open source: https://www.uplift.games/open-source
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ЮРИДИЧЕСКИЕ ПРАВИЛА (коротко)
|
||||||
|
|
||||||
|
- ✅ Публиковать можно: **MIT / Apache-2.0 / MPL-2.0 / CC0 / CC-BY** (CC-BY — с атрибуцией).
|
||||||
|
- ❌ Нельзя: **GPL/AGPL** (заразные), **CC-BY-NC** (некоммерч.), **без лицензии** (= all rights reserved),
|
||||||
|
чужие игры через game-savers/декомпиляторы (нарушение DMCA/ToS).
|
||||||
|
- ⚠️ «Uncopylocked» = только разрешение копировать в Studio, НЕ передача прав.
|
||||||
|
- ⚠️ Официальные шаблоны Studio — учиться ОК, публиковать «как есть» — серая зона.
|
||||||
|
|
||||||
|
**Рекомендация для наполнения Рублокса легально:**
|
||||||
|
1. Геометрия под чистую публикацию → Kenney/OpenGameArt CC0.
|
||||||
|
2. Классика Roblox-стиля → Roblox/Old-Open-Source-Levels (проверить LICENSE) + Crossroads.
|
||||||
|
3. Полная игра с кодом → Vigilant (MIT).
|
||||||
|
4. Масса .rbxl для теста парсера → архивы из (Б) + GitHub topics.
|
||||||
@ -3035,13 +3035,6 @@ export class BabylonScene {
|
|||||||
// Без этого onTouch финиша/плитки не срабатывает (игрок встал).
|
// Без этого onTouch финиша/плитки не срабатывает (игрок встал).
|
||||||
const EPS = 0.25;
|
const EPS = 0.25;
|
||||||
|
|
||||||
// Диагностика раз в секунду через time-based throttle
|
|
||||||
if (!this._touchDbgT0) this._touchDbgT0 = performance.now();
|
|
||||||
const _nowDbg = performance.now();
|
|
||||||
if (_nowDbg - this._touchDbgT0 > 1000) {
|
|
||||||
this._touchDbgT0 = _nowDbg;
|
|
||||||
console.warn(`[TouchDbg] pos=(${px.toFixed(2)},${py.toFixed(2)},${pz.toFixed(2)}) scripts=${scripts.length}`);
|
|
||||||
}
|
|
||||||
// 1) Касания объектов с target-скриптами (ключ touchState = 's:'+scriptId)
|
// 1) Касания объектов с target-скриптами (ключ touchState = 's:'+scriptId)
|
||||||
let _firedThisFrame = 0;
|
let _firedThisFrame = 0;
|
||||||
for (const s of scripts) {
|
for (const s of scripts) {
|
||||||
@ -5537,7 +5530,7 @@ export class BabylonScene {
|
|||||||
};
|
};
|
||||||
clip.scripts = (this._scripts || [])
|
clip.scripts = (this._scripts || [])
|
||||||
.filter(s => matchTarget(s.target))
|
.filter(s => matchTarget(s.target))
|
||||||
.map(s => ({ code: s.code, name: s.name || null }));
|
.map(s => ({ code: s.code, name: s.name || null, language: s.language || 'js' }));
|
||||||
} catch (e) { clip.scripts = []; }
|
} catch (e) { clip.scripts = []; }
|
||||||
try { localStorage.setItem('kubikon_clipboard', JSON.stringify(clip)); }
|
try { localStorage.setItem('kubikon_clipboard', JSON.stringify(clip)); }
|
||||||
catch (e) { /* ignore — приватный режим / переполнение */ }
|
catch (e) { /* ignore — приватный режим / переполнение */ }
|
||||||
@ -7769,6 +7762,7 @@ export class BabylonScene {
|
|||||||
code: s.code,
|
code: s.code,
|
||||||
target: s.target || null,
|
target: s.target || null,
|
||||||
name: s.name || null,
|
name: s.name || null,
|
||||||
|
language: s.language === 'lua' ? 'lua' : 'js',
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
editorCamera: this.camera ? {
|
editorCamera: this.camera ? {
|
||||||
|
|||||||
@ -21,7 +21,9 @@
|
|||||||
* и вызывает Lua-side Fire по соответствующему signal'у
|
* и вызывает Lua-side Fire по соответствующему signal'у
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let _wasmoon = null;
|
// Статический импорт — Vite корректно бандлит wasmoon в worker
|
||||||
|
import { LuaFactory } from 'wasmoon';
|
||||||
|
import { registerRobloxShim } from './RobloxShim.js';
|
||||||
|
|
||||||
// Главное состояние VM (на весь life-cycle Worker'а)
|
// Главное состояние VM (на весь life-cycle Worker'а)
|
||||||
const state = {
|
const state = {
|
||||||
@ -72,23 +74,21 @@ function logToMain(level, text) {
|
|||||||
async function handleInit(payload) {
|
async function handleInit(payload) {
|
||||||
state.ipcId = payload?.ipcId || 0;
|
state.ipcId = payload?.ipcId || 0;
|
||||||
send('boot', { ipcId: state.ipcId });
|
send('boot', { ipcId: state.ipcId });
|
||||||
// Загрузить wasmoon
|
try {
|
||||||
_wasmoon = await import(/* @vite-ignore */ 'wasmoon');
|
const factory = new LuaFactory();
|
||||||
const { LuaFactory } = _wasmoon;
|
state.vm = await factory.createEngine({ openStandardLibs: true });
|
||||||
const factory = new LuaFactory();
|
state.api = registerRobloxShim(state.vm, {
|
||||||
state.vm = await factory.createEngine({ openStandardLibs: true });
|
send,
|
||||||
|
getSceneSnapshot: () => state.scenes,
|
||||||
// Регистрируем минимальный Roblox shim
|
getGuiTree: () => state.guiTree,
|
||||||
const { registerRobloxShim } = await import('./RobloxShim.js');
|
scheduleWait: (sec) => scheduleWait(sec),
|
||||||
state.api = registerRobloxShim(state.vm, {
|
});
|
||||||
send,
|
state.isReady = true;
|
||||||
getSceneSnapshot: () => state.scenes,
|
send('ready', {});
|
||||||
getGuiTree: () => state.guiTree,
|
} catch (err) {
|
||||||
scheduleWait: (sec) => scheduleWait(sec),
|
// Это самое важное — без этого юзер не видит почему ничего не работает
|
||||||
});
|
logToMain('error', `[LuaWorker init FATAL] ${err?.message || err}\nstack: ${err?.stack || '?'}`);
|
||||||
|
}
|
||||||
state.isReady = true;
|
|
||||||
send('ready', {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAddScriptsBatch(payload) {
|
function handleAddScriptsBatch(payload) {
|
||||||
|
|||||||
@ -57,13 +57,21 @@ class RbxVector3 {
|
|||||||
this.X = +x; this.Y = +y; this.Z = +z;
|
this.X = +x; this.Y = +y; this.Z = +z;
|
||||||
}
|
}
|
||||||
static new(x, y, z) { return new RbxVector3(x, y, z); }
|
static new(x, y, z) { return new RbxVector3(x, y, z); }
|
||||||
Magnitude() { return Math.hypot(this.X, this.Y, this.Z); }
|
// В Roblox Magnitude/Unit это PROPERTY (без скобок), а не методы.
|
||||||
|
get Magnitude() { return Math.hypot(this.X, this.Y, this.Z); }
|
||||||
get magnitude() { return Math.hypot(this.X, this.Y, this.Z); }
|
get magnitude() { return Math.hypot(this.X, this.Y, this.Z); }
|
||||||
Unit() {
|
get Unit() {
|
||||||
const m = this.Magnitude() || 1;
|
const m = Math.hypot(this.X, this.Y, this.Z) || 1;
|
||||||
|
return new RbxVector3(this.X / m, this.Y / m, this.Z / m);
|
||||||
|
}
|
||||||
|
get unit() {
|
||||||
|
const m = Math.hypot(this.X, this.Y, this.Z) || 1;
|
||||||
|
return new RbxVector3(this.X / m, this.Y / m, this.Z / m);
|
||||||
|
}
|
||||||
|
Normalize() {
|
||||||
|
const m = Math.hypot(this.X, this.Y, this.Z) || 1;
|
||||||
return new RbxVector3(this.X / m, this.Y / m, this.Z / m);
|
return new RbxVector3(this.X / m, this.Y / m, this.Z / m);
|
||||||
}
|
}
|
||||||
Normalize() { return this.Unit(); }
|
|
||||||
Dot(b) { return this.X * b.X + this.Y * b.Y + this.Z * b.Z; }
|
Dot(b) { return this.X * b.X + this.Y * b.Y + this.Z * b.Z; }
|
||||||
Cross(b) {
|
Cross(b) {
|
||||||
return new RbxVector3(
|
return new RbxVector3(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user