Add godot-cpp submodule metadata

This commit is contained in:
saarsena@gmail.com 2026-04-24 22:09:12 -04:00
parent ac521356cc
commit 85bfb30b29
12 changed files with 516 additions and 121 deletions

116
.gitignore vendored
View file

@ -1,108 +1,26 @@
# ----------------- #
# Godot 4+ specific #
# ----------------- #
# This is the most important folder to ignore. It contains the project's cache,
# imported asset data, and other generated files. It will be regenerated
# automatically by the editor. Committing it will bloat the repository and
# cause constant merge conflicts.
# Godot/editor cache
.godot/
.claude
.vscode
backup
.godot-home/
demo/.godot/
# Ignore user-specific editor settings.
# These files save the state of your editor (window layout, last open scenes, etc.)
# and should not be shared with the team.
.godot/editor/
editor_layout.cfg
command_system_guide.md
*.md
# SCons and native build output
.sconsign.dblite
*.os
*.o
*.a
*.so
*.dll
*.dylib
*.framework/
demo/addons/onebit_lua/bin/
godot-cpp/bin/
godot-cpp/gen/
# ------------- #
# C# / .NET #
# ------------- #
# Ignore the .mono directory, which contains Mono-related build files and cache for Godot 3.x.
# For Godot 4.x with .NET 6+, these files are typically inside .godot/mono
.mono/
# Ignore generated build artifacts from dotnet/MSBuild.
bin/
obj/
# Ignore user-specific C# project files created by IDEs like Visual Studio or Rider.
*.csproj.user
*.sln.DotSettings.user
# -------------------------- #
# Exported Builds & Templates #
# -------------------------- #
# Ignore directories where you might store exported builds of your game.
builds/
export/
exports/
# Ignore the actual exported game files, regardless of where they are.
*.pck
*.exe
*.AppImage
*.html
*.wasm
*.apk
*.aab
# Ignore export templates, which are large and can be downloaded by any developer.
# You typically don't want these in your repository.
export_templates/
templates/
*.zip
*.tpz
# ----------------------------------- #
# IDE / Text Editor Specific Settings #
# ----------------------------------- #
# Visual Studio Code
# Editor/OS noise
.vscode/
# JetBrains Rider / IntelliJ
.idea/
# Visual Studio
.vs/
# ---------------- #
# OS Specific #
# ---------------- #
# macOS
.DS_Store
.AppleDouble
.LSOverride
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
# ---------------- #
# Other Common #
# ---------------- #
# Log files
debug_log.txt
# Logs
*.log
turn_system_plan.md
# Asset pack archives (you should unpack them and commit the assets, not the zip)
*.rar
*.7z
.CLAUDE.md

4
.gitmodules vendored Normal file
View file

@ -0,0 +1,4 @@
[submodule "godot-cpp"]
path = godot-cpp
url = https://github.com/godotengine/godot-cpp.git
branch = master

Binary file not shown.

102
README.md Normal file
View file

@ -0,0 +1,102 @@
# OneBit Lua Runtime
Native GDExtension prototype for the 1BitRL v2 Lua runtime contract.
## Current Scope
This runtime is intentionally small and breaking:
- `api_version = 2` scripts only.
- No `game` table.
- Explicit `ctx` and `state` handler arguments.
- Lua emits commands and logs; it does not mutate the Godot world directly.
- Queries cross a Godot-owned query host boundary.
- Instruction budget is enabled for handler calls.
Initial Lua API:
```lua
sense.is_walkable(x, y)
sense.find_nearest(group)
move.step(dx, dy)
log.say(message, duration)
```
## Requirements
- Godot 4.6.
- `godot-cpp` master, targeting `api_version=4.6`.
- SCons.
- A Lua development package with `pkg-config`.
This machine currently uses Lua 5.1:
```sh
pkg-config lua-5.1 --cflags --libs
```
Lua 5.1 is explicit for now because it is the installed system package. If the project moves to Lua 5.4, install a Lua 5.4 development package and build with the matching pkg-config name, for example:
```sh
scons platform=linux target=template_debug api_version=4.6 lua_pkg=lua5.4
```
Script semantics differ between Lua 5.1 and 5.4, so do not change the runtime version silently.
## Build
Clone `godot-cpp` as a submodule or checkout at `godot-cpp/`, then run:
```sh
scons platform=linux target=template_debug api_version=4.6 -j4
```
The demo extension library is written to:
```text
demo/addons/onebit_lua/bin/
```
## Smoke Test
Run the demo project headlessly:
```sh
godot --headless --path demo
```
Expected behavior:
- Loads `OneBitLuaRuntime`.
- Loads a tiny `api_version = 2` script.
- Calls `on_update(ctx, state)`.
- Mutates `state.count`.
- Emits one `move` command.
- Emits one log entry.
- Calls the GDScript query host for `sense.is_walkable` and `sense.find_nearest`.
## Safe Lua Libraries
The runtime opens only selected Lua libraries:
- base
- math
- string
- table
It does not open:
- `io`
- `os`
- `package`
- `debug`
After opening the base library, the runtime removes dangerous dynamic-loading globals:
- `dofile`
- `load`
- `loadfile`
- `loadstring`
- `module`
- `require`
- `collectgarbage`

View file

@ -3,7 +3,8 @@
env = SConscript("godot-cpp/SConstruct")
env.Append(CPPPATH=["src"])
env.ParseConfig("pkg-config lua-5.1 --cflags --libs")
lua_pkg = ARGUMENTS.get("lua_pkg", "lua-5.1")
env.ParseConfig("pkg-config {} --cflags --libs".format(lua_pkg))
sources = Glob("src/*.cpp")

View file

@ -36,10 +36,12 @@ return {
on_update = function(ctx, state)
state.count = (state.count or 0) + 1
state.world_x = ctx.self.world.x
state.tint_r = ctx.self.tint.r
if not ctx.self.is_moving and sense.is_walkable(2, 3) then
local nearest = sense.find_nearest("players")
move.step(1, 0)
log.say("tick", 1.0)
log.say("tick " .. tostring(state.count) .. " target " .. tostring(nearest.entity_id), 1.0)
end
end
}
@ -52,6 +54,8 @@ return {
var ctx := {
"self": {
"is_moving": false,
"world": Vector2(2.0, 3.0),
"tint": Color(0.25, 0.5, 0.75, 1.0),
},
}
var state := {}
@ -61,10 +65,78 @@ return {
get_tree().quit(1)
return
if result.commands.size() != 1 or result.logs.size() != 1 or result.state.get("count", 0) != 1:
if result.commands.size() != 1 or result.logs.size() != 1 or result.state.get("count", 0) != 1 or result.state.get("world_x", 0) != 2 or result.state.get("tint_r", 0) != 0.25 or result.logs[0].message != "tick 1 target 7":
push_error("unexpected result: " + str(result))
get_tree().quit(1)
return
if not _expect_runtime_error("""
return {
api_version = 2,
on_update = function(ctx, state)
sense.is_walkable = function() return true end
end
}
""", "read-only"):
get_tree().quit(1)
return
if not _expect_runtime_error("""
return {
api_version = 2,
on_update = function(ctx, state)
sense = nil
end
}
""", "globals are read-only"):
get_tree().quit(1)
return
var mem_rt := OneBitLuaRuntime.new()
mem_rt.set_entity_id(42)
mem_rt.set_query_host(query_host)
mem_rt.set_instruction_budget(1000000)
mem_rt.set_memory_budget(1024 * 1024)
var mem_loaded := mem_rt.load_string("""
return {
api_version = 2,
on_update = function(ctx, state)
local chunks = {}
for i = 1, 10000 do
chunks[i] = string.rep("x", 4000) .. tostring(i)
end
state.done = true
end
}
""")
if not mem_loaded.ok:
push_error("memory test failed to load: " + str(mem_loaded.error))
get_tree().quit(1)
return
var mem_result := mem_rt.call_event("on_update", ctx, {}, [])
if mem_result.ok or not str(mem_result.error).contains("memory budget"):
push_error("memory budget test did not fail as expected: " + str(mem_result))
get_tree().quit(1)
return
print("OneBitLuaRuntime smoke test passed: ", result)
get_tree().quit(0)
func _expect_runtime_error(source: String, expected_error: String) -> bool:
var rt := OneBitLuaRuntime.new()
rt.set_entity_id(42)
rt.set_query_host(query_host)
var loaded := rt.load_string(source)
if not loaded.ok:
push_error("expected load success, got: " + str(loaded.error))
return false
var result := rt.call_event("on_update", {"self": {"is_moving": false}}, {}, [])
if result.ok:
push_error("expected runtime error, got success: " + str(result))
return false
if not str(result.error).contains(expected_error) or not str(result.error).contains("[string \"<string>\"]"):
push_error("unexpected runtime error: " + str(result.error))
return false
return true

View file

@ -3,8 +3,13 @@
#include <godot_cpp/classes/file_access.hpp>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/core/object.hpp>
#include <godot_cpp/variant/color.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
#include <godot_cpp/variant/vector2.hpp>
#include <godot_cpp/variant/vector2i.hpp>
#include <godot_cpp/variant/vector3.hpp>
#include <cstdlib>
extern "C" {
#include <lauxlib.h>
@ -15,6 +20,8 @@ extern "C" {
#define LUA_OK 0
#endif
static const char *ONEBIT_RUNTIME_REGISTRY_KEY = "onebit_lua_runtime";
using namespace godot;
void OneBitLuaRuntime::_bind_methods() {
@ -24,6 +31,7 @@ void OneBitLuaRuntime::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_entity_id", "entity_id"), &OneBitLuaRuntime::set_entity_id);
ClassDB::bind_method(D_METHOD("set_query_host", "host"), &OneBitLuaRuntime::set_query_host);
ClassDB::bind_method(D_METHOD("set_instruction_budget", "budget"), &OneBitLuaRuntime::set_instruction_budget);
ClassDB::bind_method(D_METHOD("set_memory_budget", "bytes"), &OneBitLuaRuntime::set_memory_budget);
}
OneBitLuaRuntime::OneBitLuaRuntime() {
@ -31,21 +39,69 @@ OneBitLuaRuntime::OneBitLuaRuntime() {
}
OneBitLuaRuntime::~OneBitLuaRuntime() {
_reset_lua();
_close_lua();
}
void OneBitLuaRuntime::_reset_lua() {
void OneBitLuaRuntime::_close_lua() {
if (lua) {
_clear_handlers();
lua_close(lua);
lua = nullptr;
}
}
lua = luaL_newstate();
void OneBitLuaRuntime::_reset_lua() {
_close_lua();
memory_used_bytes = 0;
instruction_budget_exceeded = false;
memory_budget_exceeded = false;
lua = lua_newstate(&OneBitLuaRuntime::_lua_allocator, this);
if (!lua) {
memory_budget_exceeded = true;
return;
}
_open_safe_libraries();
_install_api();
}
void OneBitLuaRuntime::_open_safe_libraries() {
struct SafeLib {
const char *name;
lua_CFunction open;
};
const SafeLib safe_libs[] = {
{ "", luaopen_base },
{ LUA_MATHLIBNAME, luaopen_math },
{ LUA_STRLIBNAME, luaopen_string },
{ LUA_TABLIBNAME, luaopen_table },
{ nullptr, nullptr },
};
for (const SafeLib *lib = safe_libs; lib->open; lib++) {
lua_pushcfunction(lua, lib->open);
lua_pushstring(lua, lib->name);
lua_call(lua, 1, 0);
}
const char *blocked_globals[] = {
"dofile",
"load",
"loadfile",
"loadstring",
"module",
"require",
"collectgarbage",
nullptr,
};
for (const char **name = blocked_globals; *name; name++) {
lua_pushnil(lua);
lua_setglobal(lua, *name);
}
}
void OneBitLuaRuntime::_clear_handlers() {
if (!lua) {
handlers.clear();
@ -60,7 +116,7 @@ void OneBitLuaRuntime::_clear_handlers() {
void OneBitLuaRuntime::_install_api() {
lua_pushlightuserdata(lua, this);
lua_setglobal(lua, "__onebit_runtime");
lua_setfield(lua, LUA_REGISTRYINDEX, ONEBIT_RUNTIME_REGISTRY_KEY);
lua_newtable(lua);
lua_pushlightuserdata(lua, this);
@ -69,19 +125,52 @@ void OneBitLuaRuntime::_install_api() {
lua_pushlightuserdata(lua, this);
lua_pushcclosure(lua, &OneBitLuaRuntime::_lua_sense_find_nearest, 1);
lua_setfield(lua, -2, "find_nearest");
lua_setglobal(lua, "sense");
_set_readonly_global("sense");
lua_newtable(lua);
lua_pushlightuserdata(lua, this);
lua_pushcclosure(lua, &OneBitLuaRuntime::_lua_move_step, 1);
lua_setfield(lua, -2, "step");
lua_setglobal(lua, "move");
_set_readonly_global("move");
lua_newtable(lua);
lua_pushlightuserdata(lua, this);
lua_pushcclosure(lua, &OneBitLuaRuntime::_lua_log_say, 1);
lua_setfield(lua, -2, "say");
lua_setglobal(lua, "log");
_set_readonly_global("log");
}
void OneBitLuaRuntime::_set_readonly_global(const char *name) {
int api_table = lua_gettop(lua);
lua_newtable(lua);
int proxy_table = lua_gettop(lua);
lua_newtable(lua);
lua_pushvalue(lua, api_table);
lua_setfield(lua, -2, "__index");
lua_pushcfunction(lua, &OneBitLuaRuntime::_lua_readonly_error);
lua_setfield(lua, -2, "__newindex");
lua_pushboolean(lua, 0);
lua_setfield(lua, -2, "__metatable");
lua_setmetatable(lua, proxy_table);
lua_setglobal(lua, name);
lua_pop(lua, 1);
}
void OneBitLuaRuntime::_push_script_environment() {
lua_newtable(lua);
int env_table = lua_gettop(lua);
lua_newtable(lua);
lua_pushvalue(lua, LUA_GLOBALSINDEX);
lua_setfield(lua, -2, "__index");
lua_pushcfunction(lua, &OneBitLuaRuntime::_lua_global_write_error);
lua_setfield(lua, -2, "__newindex");
lua_pushboolean(lua, 0);
lua_setfield(lua, -2, "__metatable");
lua_setmetatable(lua, env_table);
}
Dictionary OneBitLuaRuntime::_base_result(bool ok, const String &error) const {
@ -99,23 +188,51 @@ Dictionary OneBitLuaRuntime::_error_result(const String &error) const {
return _base_result(false, error);
}
String OneBitLuaRuntime::_pop_lua_error() {
String error;
if (lua && lua_gettop(lua) > 0 && lua_isstring(lua, -1)) {
error = String(lua_tostring(lua, -1));
} else {
error = "Unknown Lua error";
}
if (lua && lua_gettop(lua) > 0) {
lua_pop(lua, 1);
}
return error;
}
Dictionary OneBitLuaRuntime::load_string(const String &source) {
return _load_source(source, "<string>");
}
Dictionary OneBitLuaRuntime::_load_source(const String &source, const String &source_name) {
_reset_lua();
commands.clear();
logs.clear();
CharString utf8 = source.utf8();
if (luaL_loadstring(lua, utf8.get_data()) != LUA_OK) {
String error = String(lua_tostring(lua, -1));
lua_pop(lua, 1);
return _error_result(error);
if (!lua) {
return _error_result("Failed to create Lua state");
}
if (lua_pcall(lua, 0, 1, 0) != LUA_OK) {
String error = String(lua_tostring(lua, -1));
lua_pop(lua, 1);
CharString utf8 = source.utf8();
CharString source_name_utf8 = source_name.utf8();
if (luaL_loadbuffer(lua, utf8.get_data(), utf8.length(), source_name_utf8.get_data()) != LUA_OK) {
return _error_result(_pop_lua_error());
}
_push_script_environment();
lua_setfenv(lua, -2);
lua_pushcfunction(lua, &OneBitLuaRuntime::_traceback_handler);
lua_insert(lua, -2);
int error_handler = lua_gettop(lua) - 1;
if (lua_pcall(lua, 0, 1, error_handler) != LUA_OK) {
String error = _pop_lua_error();
lua_remove(lua, error_handler);
return _error_result(error);
}
lua_remove(lua, error_handler);
if (!lua_istable(lua, -1)) {
lua_pop(lua, 1);
@ -134,7 +251,7 @@ Dictionary OneBitLuaRuntime::load_script(const String &path) {
}
String source = file->get_as_text();
return load_string(source);
return _load_source(source, path);
}
Dictionary OneBitLuaRuntime::_extract_handlers(int table_index, const String &source_name) {
@ -191,16 +308,27 @@ Dictionary OneBitLuaRuntime::call_event(const String &event_name, const Dictiona
_push_variant(args[i]);
}
int function_index = lua_gettop(lua) - (2 + int(args.size()));
lua_pushcfunction(lua, &OneBitLuaRuntime::_traceback_handler);
lua_insert(lua, function_index);
int error_handler = function_index;
lua_sethook(lua, &OneBitLuaRuntime::_instruction_hook, LUA_MASKCOUNT, int(instruction_budget));
int status = lua_pcall(lua, 2 + int(args.size()), 0, 0);
lua_sethook(lua, nullptr, 0, 0);
if (status != LUA_OK) {
String error = instruction_budget_exceeded ? String("Lua instruction budget exceeded") : String(lua_tostring(lua, -1));
lua_pop(lua, 1);
String error = _pop_lua_error();
if (instruction_budget_exceeded) {
error = "Lua instruction budget exceeded\n" + error;
} else if (memory_budget_exceeded) {
error = "Lua memory budget exceeded\n" + error;
}
lua_remove(lua, error_handler);
luaL_unref(lua, LUA_REGISTRYINDEX, state_ref);
return _error_result(error);
}
lua_remove(lua, error_handler);
lua_rawgeti(lua, LUA_REGISTRYINDEX, state_ref);
Variant updated_state = _read_lua_value(-1);
@ -226,10 +354,74 @@ void OneBitLuaRuntime::set_instruction_budget(int64_t p_budget) {
instruction_budget = p_budget > 0 ? p_budget : 1;
}
void OneBitLuaRuntime::set_memory_budget(int64_t p_bytes) {
memory_budget_bytes = p_bytes > 0 ? p_bytes : 1;
}
void *OneBitLuaRuntime::_lua_allocator(void *ud, void *ptr, size_t osize, size_t nsize) {
(void)osize;
OneBitLuaRuntime *runtime = static_cast<OneBitLuaRuntime *>(ud);
const size_t header_size = sizeof(size_t);
if (nsize == 0) {
if (runtime) {
if (ptr) {
void *base_ptr = static_cast<char *>(ptr) - header_size;
size_t old_size = *static_cast<size_t *>(base_ptr);
runtime->memory_used_bytes -= int64_t(old_size);
std::free(base_ptr);
}
if (runtime->memory_used_bytes < 0) {
runtime->memory_used_bytes = 0;
}
} else if (ptr) {
std::free(static_cast<char *>(ptr) - header_size);
}
return nullptr;
}
if (!runtime) {
void *base_ptr = ptr ? static_cast<char *>(ptr) - header_size : nullptr;
void *new_base = std::realloc(base_ptr, nsize + header_size);
if (!new_base) {
return nullptr;
}
*static_cast<size_t *>(new_base) = nsize;
return static_cast<char *>(new_base) + header_size;
}
size_t old_raw_size = 0;
void *base_ptr = nullptr;
if (ptr) {
base_ptr = static_cast<char *>(ptr) - header_size;
old_raw_size = *static_cast<size_t *>(base_ptr);
}
int64_t old_size = int64_t(old_raw_size);
int64_t new_size = int64_t(nsize);
int64_t delta = new_size - old_size;
if (delta > 0 && runtime->memory_used_bytes + delta > runtime->memory_budget_bytes) {
runtime->memory_budget_exceeded = true;
return nullptr;
}
void *new_base = std::realloc(base_ptr, nsize + header_size);
if (!new_base) {
return nullptr;
}
*static_cast<size_t *>(new_base) = nsize;
runtime->memory_used_bytes += delta;
if (runtime->memory_used_bytes < 0) {
runtime->memory_used_bytes = 0;
}
return static_cast<char *>(new_base) + header_size;
}
void OneBitLuaRuntime::_instruction_hook(lua_State *L, lua_Debug *debug) {
(void)debug;
OneBitLuaRuntime *runtime = nullptr;
lua_getglobal(L, "__onebit_runtime");
lua_getfield(L, LUA_REGISTRYINDEX, ONEBIT_RUNTIME_REGISTRY_KEY);
if (lua_islightuserdata(L, -1)) {
runtime = static_cast<OneBitLuaRuntime *>(lua_touserdata(L, -1));
}
@ -241,6 +433,51 @@ void OneBitLuaRuntime::_instruction_hook(lua_State *L, lua_Debug *debug) {
luaL_error(L, "Lua instruction budget exceeded");
}
int OneBitLuaRuntime::_lua_readonly_error(lua_State *L) {
const char *key = lua_tostring(L, 2);
if (!key) {
key = "<non-string key>";
}
return luaL_error(L, "Lua API tables are read-only: cannot assign '%s'", key);
}
int OneBitLuaRuntime::_lua_global_write_error(lua_State *L) {
const char *key = lua_tostring(L, 2);
if (!key) {
key = "<non-string key>";
}
return luaL_error(L, "Lua globals are read-only: attempted to assign '%s'", key);
}
int OneBitLuaRuntime::_traceback_handler(lua_State *L) {
const char *message = lua_tostring(L, 1);
if (!message) {
message = "Unknown Lua error";
}
luaL_Buffer buffer;
luaL_buffinit(L, &buffer);
luaL_addstring(&buffer, message);
luaL_addstring(&buffer, "\nstack traceback:");
lua_Debug ar;
int level = 1;
while (lua_getstack(L, level, &ar)) {
lua_getinfo(L, "Sln", &ar);
luaL_addstring(&buffer, "\n ");
luaL_addstring(&buffer, ar.short_src ? ar.short_src : "<unknown>");
luaL_addstring(&buffer, ":");
CharString line = String::num_int64(ar.currentline).utf8();
luaL_addstring(&buffer, line.get_data());
luaL_addstring(&buffer, ": in ");
luaL_addstring(&buffer, ar.name ? ar.name : "?");
level++;
}
luaL_pushresult(&buffer);
return 1;
}
Variant OneBitLuaRuntime::_query(const String &query_name, const Dictionary &params) {
if (query_host_id == 0) {
return Variant();
@ -329,6 +566,15 @@ bool OneBitLuaRuntime::_push_variant(const Variant &value) {
lua_pushstring(lua, utf8.get_data());
return true;
}
case Variant::VECTOR2: {
Vector2 vector = value;
lua_newtable(lua);
lua_pushnumber(lua, vector.x);
lua_setfield(lua, -2, "x");
lua_pushnumber(lua, vector.y);
lua_setfield(lua, -2, "y");
return true;
}
case Variant::VECTOR2I: {
Vector2i vector = value;
lua_newtable(lua);
@ -338,6 +584,30 @@ bool OneBitLuaRuntime::_push_variant(const Variant &value) {
lua_setfield(lua, -2, "y");
return true;
}
case Variant::VECTOR3: {
Vector3 vector = value;
lua_newtable(lua);
lua_pushnumber(lua, vector.x);
lua_setfield(lua, -2, "x");
lua_pushnumber(lua, vector.y);
lua_setfield(lua, -2, "y");
lua_pushnumber(lua, vector.z);
lua_setfield(lua, -2, "z");
return true;
}
case Variant::COLOR: {
Color color = value;
lua_newtable(lua);
lua_pushnumber(lua, color.r);
lua_setfield(lua, -2, "r");
lua_pushnumber(lua, color.g);
lua_setfield(lua, -2, "g");
lua_pushnumber(lua, color.b);
lua_setfield(lua, -2, "b");
lua_pushnumber(lua, color.a);
lua_setfield(lua, -2, "a");
return true;
}
case Variant::DICTIONARY: {
Dictionary dict = value;
lua_newtable(lua);

View file

@ -27,7 +27,10 @@ private:
int64_t entity_id = 0;
uint64_t query_host_id = 0;
int64_t instruction_budget = 100000;
int64_t memory_budget_bytes = 16 * 1024 * 1024;
int64_t memory_used_bytes = 0;
bool instruction_budget_exceeded = false;
bool memory_budget_exceeded = false;
static void _bind_methods();
@ -35,11 +38,21 @@ private:
static int _lua_log_say(lua_State *L);
static int _lua_sense_is_walkable(lua_State *L);
static int _lua_sense_find_nearest(lua_State *L);
static int _lua_readonly_error(lua_State *L);
static int _lua_global_write_error(lua_State *L);
static int _traceback_handler(lua_State *L);
static void _instruction_hook(lua_State *L, lua_Debug *debug);
static void *_lua_allocator(void *ud, void *ptr, size_t osize, size_t nsize);
void _close_lua();
void _reset_lua();
void _open_safe_libraries();
void _install_api();
void _set_readonly_global(const char *name);
void _push_script_environment();
void _clear_handlers();
Dictionary _load_source(const String &source, const String &source_name);
String _pop_lua_error();
Dictionary _base_result(bool ok, const String &error = "") const;
Dictionary _error_result(const String &error) const;
Variant _query(const String &query_name, const Dictionary &params);
@ -60,6 +73,7 @@ public:
void set_entity_id(int64_t p_entity_id);
void set_query_host(Object *p_host);
void set_instruction_budget(int64_t p_budget);
void set_memory_budget(int64_t p_bytes);
};
#endif

Binary file not shown.

View file

@ -30,6 +30,7 @@ GDExtensionBool GDE_EXPORT onebit_lua_library_init(
godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
init_obj.register_initializer(initialize_onebit_lua_module);
init_obj.register_terminator(uninitialize_onebit_lua_module);
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);

Binary file not shown.

13
src/samq2.code-workspace Normal file
View file

@ -0,0 +1,13 @@
{
"folders": [
{
"path": "../../samq2"
},
{
"path": ".."
}
],
"settings": {
"git.ignoreLimitWarning": true
}
}