- Rust 99.7%
- Lua 0.3%
| assets | ||
| src | ||
| .gitignore | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
PoC2: Lua como editor → RON como runtime (console-friendly)
Objetivo
Demonstrar um pipeline de conteúdo onde Lua é ferramenta de autoria e RON é o formato
de runtime. Designers escrevem scripts .lua imperativos (set_flag, get_flag,
move_npc, open_door, close_door); em builds de desenvolvimento (feature
lua-editor, ligada por padrão), o jogo compila o .lua para um .ron declarativo
no startup e em seguida consome só o .ron. Builds "console"
(--no-default-features) não embarcam VM de Lua nenhuma — leem direto o .ron
pré-compilado. Outras pessoas podem criar quests/eventos sem mexer no Rust.
Pipeline
level_1.lua ──(lua-editor: compile no startup)──▶ level_1.ron ──▶ WorldState/ECS
▲
build console lê daqui (sem mlua)
- Compilador (
src/lua_compiler.rs, atrás da featurelua-editor): executa o.luanum sandbox com bindings de captura — cada chamada vira umCompiledActiongravado em ordem; o resultado é serializado em.ronao lado do fonte. - Runtime (
src/compiled_script.rs, sempre compilado): lê o.ron, aplicaSetFlagdireto nas flags e enfileiraMoveNpc/OpenDoor/CloseDoorcomoPendingAction— a mesma fila queaction_consumerjá drena. get_flagno compilador lê asinitial_flagsdoconfig.ron+ as flags que o próprio script setou (semântica determinística de snapshot).
Build de console (sem Lua)
cargo run -p poc2 --no-default-features
Roda o mesmo cenário de demonstração lendo apenas assets/scripts/level_1.ron
(pré-compilado e commitado), sem mlua no binário.
Como rodar
cargo run -p poc2
Aguarde ~30s para build cold (mlua + bevy compilam do zero na primeira vez).
Fluxo principal
ScriptPipelinePlugin(Startup) insereMutableStatecomo Resource- Com
lua-editor:lua_compiler::compile_lua_scriptslêlevel_1.lua, executa no sandbox capturando as chamadas, e (re)escrevelevel_1.ron compiled_script::load_compiled_scriptseeda as flags deconfig.initial_flags, lêlevel_1.rone aplica: flags direto, ações na fila dePendingActionaction_consumer::process_actions(Update) drena a fila e aplica no ECS: move NPCs, abre portas, etc.
Script de exemplo
poc2/assets/scripts/level_1.lua:
set_flag("intro_shown", true)
set_flag("npc_king_dead", true)
move_npc("guide", 10.0, 20.0)
move_npc("Guard", 120.0, 340.0)
open_door("throne_room")
Controles
Nenhum — a demo roda automaticamente no Startup.
O que aparece na tela
Visual (janela 3D aberta)
- NPC
guide— quadrado azul 40×40 px em world (0, 0). Apósmove_npc("guide", 10, 20)no Lua, vai para (10, 20). - NPC
Guard— quadrado vermelho 40×40 px em world (100, 300). Apósmove_npc("Guard", 120, 340), vai para (120, 340). - Door
throne_room— retângulo verde 60×120 px em world (200, 0). Apósopen_door("throne_room")no Lua, vira vermelho (perde a colisão via marcadorRemoveCollider). - HUD — texto
Text2dno canto superior esquerdo em world (-550, 320, 1) mostrando flags atuais + actions queue. Fonte 18pt branca. Cada flag muda de cor conforme o valor: verde quandotrue, cinza quandofalse— visível em tempo real assim que um script chamaset_flag, inclusive para chaves novas que ainda não existiam.
Inspector (devtool, F1)
- Painel lateral direito (360 px) com 6 seções colapsáveis: Camera / NPCs / Doors / HUD / Initial Flags / Scripts
- 3 botões no rodapé: Apply (despawn + respawn + reset flags), Save to RON, Reload from RON
- Pressione F1 para mostrar/ocultar
- Mouse interage com widgets (DragValue, TextEdit, Checkbox)
- Sem mouse não dá pra editar valores
Terminal (logs info!)
INFO poc2::script_loader: executing initial script: ".../poc2/assets/scripts/level_1.lua"
INFO poc2::script_loader: initial script executed successfully
INFO poc2::action_consumer: moved NPC guide to (10, 20)
INFO poc2::action_consumer: moved NPC Guard to (120, 340)
INFO poc2::action_consumer: opened door throne_room
INFO poc2::hud: PoC2 HUD is live
Arquitetura
poc2/src/main.rs— entry point, spawns NPCs (guide, Guard) e Door (throne_room) doconfig.ronpoc2/src/compiled_script.rs—CompiledAction/CompiledScript(serde), applier RON→WorldState,ScriptPipelinePluginpoc2/src/lua_compiler.rs— (featurelua-editor) sandbox + bindings de captura + compile no startuppoc2/src/world_state.rs—WorldState(HashMap<String, bool>+VecDeque<PendingAction>) eMutableState(Arc<Mutex<WorldState>>)poc2/src/action_consumer.rs— sistema Update que drena actions e aplica no ECSpoc2/assets/scripts/level_1.lua— script de autoria (fonte)poc2/assets/scripts/level_1.ron— script compilado (runtime; regenerado pelolua-editor)
Segurança
lua_compiler::install_sandbox remove funções perigosas (loadfile, dofile, collectgarbage) do ambiente Lua para evitar que scripts de autoria escapem do sandbox. Em builds de produção o problema nem existe: não há VM.
Contratos com outros PoCs
- Fornece
WorldStateResource (flag store + action queue) para poc4, poc6, poc7 - Fornece
MutableStateResource (Arc<Mutex>) para acesso concorrente - Define contrato de flags:
bridge_fixed,shop_ruined,quest_accepted,intro_shown,npc_king_dead, etc. - Define contrato de actions:
MoveNpc { id, x, y },OpenDoor { id },CloseDoor { id }
Status
✅ Roda limpo | Lua scripts executam | Actions aplicadas com sucesso | Sandbox ativo | Testes unitários em bindings, world_state, action_consumer e lua_state