doc/todo: Module tags
parent
901e0e9e82
commit
610fe94d08
|
@ -39,14 +39,14 @@ function M.init()
|
|||
end)
|
||||
|
||||
magic.SubscribeToEvent("Update", function(event_type, event_data)
|
||||
if camera_node then
|
||||
if camera_node and M.section_size_voxels then
|
||||
local p = camera_node.position
|
||||
update_counter = update_counter + 1
|
||||
if update_counter % 60 == 0 then
|
||||
local section_p = buildat.IntVector3(p):div_components(
|
||||
M.section_size_voxels):floor()
|
||||
log:info("p: "..p.x..", "..p.y..", "..p.z.." -> section_p: "..
|
||||
section_p.x..", "..section_p.y..", "..section_p.z)
|
||||
--log:info("p: "..p.x..", "..p.y..", "..p.z.." -> section_p: "..
|
||||
-- section_p.x..", "..section_p.y..", "..section_p.z)
|
||||
--[[send_get_section(section_p + buildat.IntVector3( 0, 0, 0))
|
||||
send_get_section(section_p + buildat.IntVector3(-1, 0, 0))
|
||||
send_get_section(section_p + buildat.IntVector3( 1, 0, 0))
|
||||
|
@ -59,11 +59,11 @@ function M.init()
|
|||
end)
|
||||
|
||||
local function setup_buildat_voxel_data(node)
|
||||
local data = node:GetVar("buildat_voxel_data"):GetString()
|
||||
local data = node:GetVar("buildat_voxel_data"):GetBuffer()
|
||||
local w = node:GetVar("buildat_voxel_w"):GetInt()
|
||||
local h = node:GetVar("buildat_voxel_h"):GetInt()
|
||||
local d = node:GetVar("buildat_voxel_d"):GetInt()
|
||||
log:info(dump(node:GetName()).." voxel data size: "..#data)
|
||||
log:info(dump(node:GetName()).." voxel data size: "..data:GetSize())
|
||||
buildat.set_8bit_voxel_geometry(node, w, h, d, data)
|
||||
node:SetScale(magic.Vector3(1, 1, 1))
|
||||
end
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <CollisionShape.h>
|
||||
#include <Context.h>
|
||||
#include <ResourceCache.h>
|
||||
#include <Light.h>
|
||||
#pragma GCC diagnostic pop
|
||||
#include <deque>
|
||||
|
||||
|
@ -70,21 +71,27 @@ namespace voxelworld {
|
|||
|
||||
struct Section
|
||||
{
|
||||
pv::Vector3DInt16 section_p;// Position in sections
|
||||
pv::Vector3DInt16 chunk_size;
|
||||
pv::Region contained_chunks;// Position and size in chunks
|
||||
pv::Vector3DInt16 section_p;// Position in sections
|
||||
// Static voxel nodes (each contains one chunk); Initialized to 0.
|
||||
pv::SimpleVolume<int32_t> node_ids;
|
||||
sp_<pv::SimpleVolume<int32_t>> node_ids;
|
||||
|
||||
// TODO: Specify what exactly do these mean and how they are used
|
||||
bool loaded = false;
|
||||
bool save_enabled = false;
|
||||
bool generated = false;
|
||||
|
||||
Section(pv::Vector3DInt16 chunk_size, pv::Region contained_chunks,
|
||||
pv::Vector3DInt16 section_p):
|
||||
Section(): // Needed for containers
|
||||
chunk_size(0, 0, 0)
|
||||
{}
|
||||
Section(pv::Vector3DInt16 section_p,
|
||||
pv::Vector3DInt16 chunk_size,
|
||||
pv::Region contained_chunks):
|
||||
section_p(section_p),
|
||||
chunk_size(chunk_size),
|
||||
contained_chunks(contained_chunks),
|
||||
section_p(section_p),
|
||||
node_ids(contained_chunks)
|
||||
node_ids(new pv::SimpleVolume<int32_t>(contained_chunks))
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -102,7 +109,7 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||
// The world is loaded and unloaded by sections (eg. 4x4x4)
|
||||
pv::Vector3DInt16 m_section_size_chunks = pv::Vector3DInt16(4, 4, 4);
|
||||
|
||||
// Sections (first (y,z), then x)
|
||||
// Sections (this(y,z)=sector, sector(x)=section)
|
||||
sm_<pv::Vector<2, int16_t>, sm_<int16_t, Section>> m_sections;
|
||||
// Cache of last used sections (add to end, remove from beginning)
|
||||
//std::deque<Section*> m_last_used_sections;
|
||||
|
@ -235,23 +242,31 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||
Context *context = scene->GetContext();
|
||||
ResourceCache *cache = context->GetSubsystem<ResourceCache>();
|
||||
|
||||
{
|
||||
Node *node = scene->CreateChild("DirectionalLight");
|
||||
node->SetDirection(Vector3(-0.6f, -1.0f, 0.8f));
|
||||
Light *light = node->CreateComponent<Light>();
|
||||
light->SetLightType(LIGHT_DIRECTIONAL);
|
||||
light->SetCastShadows(true);
|
||||
}
|
||||
#if 0
|
||||
{
|
||||
Node *n = scene->CreateChild("Base");
|
||||
n->SetScale(Vector3(1.0f, 1.0f, 1.0f));
|
||||
n->SetPosition(Vector3(0.0f, 0.5f, 0.0f));
|
||||
|
||||
int w = 10, h = 3, d = 10;
|
||||
int w = 10, h = 4, d = 10;
|
||||
ss_ data =
|
||||
"222222222211211111211111111111"
|
||||
"222222222211111111111111111111"
|
||||
"222222222211111111111111111111"
|
||||
"222222222211111111111111111111"
|
||||
"222222222211122111111112111111"
|
||||
"222233222211123111111112111111"
|
||||
"222233222211111111111111111111"
|
||||
"222222222211111111111111111111"
|
||||
"222222222211111111111111111111"
|
||||
"222222222211111111111111111111"
|
||||
"1131111131111111111133333333333333333333"
|
||||
"1111111111111111111122222222223333333333"
|
||||
"1111111111111111111122222222223333333333"
|
||||
"1111111111111111111122222222223333333333"
|
||||
"1112211111111211111122222222223333333333"
|
||||
"1112311111111211111122223322223333333333"
|
||||
"1111111111111111111122223322223333333333"
|
||||
"1111111111111111111122222222223333333333"
|
||||
"1111111111111111111122222222223333333333"
|
||||
"1111111111111111111122222222223333333333"
|
||||
;
|
||||
|
||||
// Convert data to the actually usable voxel type id namespace
|
||||
|
@ -278,7 +293,16 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||
CollisionShape *shape = n->CreateComponent<CollisionShape>();
|
||||
shape->SetTriangleMesh(model, 0, Vector3::ONE);
|
||||
}
|
||||
#endif
|
||||
});
|
||||
|
||||
load_or_generate_section(pv::Vector3DInt16( 0, 0, 0));
|
||||
load_or_generate_section(pv::Vector3DInt16( 1, 0, 0));
|
||||
load_or_generate_section(pv::Vector3DInt16(-1, 0, 0));
|
||||
load_or_generate_section(pv::Vector3DInt16( 0, 1, 0));
|
||||
load_or_generate_section(pv::Vector3DInt16( 0,-1, 0));
|
||||
load_or_generate_section(pv::Vector3DInt16( 0, 0, 1));
|
||||
load_or_generate_section(pv::Vector3DInt16( 0, 0,-1));
|
||||
}
|
||||
|
||||
void on_unload()
|
||||
|
@ -332,8 +356,134 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||
packet.sender, PV3I_PARAMS(section_p));
|
||||
}
|
||||
|
||||
Section& get_section(const pv::Vector3DInt16 §ion_p)
|
||||
{
|
||||
pv::Vector<2, int16_t> p_yz(section_p.getY(), section_p.getZ());
|
||||
sm_<int16_t, Section> §or = m_sections[p_yz];
|
||||
Section §ion = sector[section_p.getX()];
|
||||
if(section.chunk_size.getX() == 0){
|
||||
// Initialize newly created section properly
|
||||
pv::Region contained_chunks(
|
||||
section_p.getX() * m_section_size_chunks.getX(),
|
||||
section_p.getY() * m_section_size_chunks.getY(),
|
||||
section_p.getZ() * m_section_size_chunks.getZ(),
|
||||
(section_p.getX()+1) * m_section_size_chunks.getX() - 1,
|
||||
(section_p.getY()+1) * m_section_size_chunks.getY() - 1,
|
||||
(section_p.getZ()+1) * m_section_size_chunks.getZ() - 1
|
||||
);
|
||||
section = Section(section_p, m_chunk_size_voxels, contained_chunks);
|
||||
}
|
||||
return section;
|
||||
}
|
||||
|
||||
void create_chunk_node(Scene *scene, Section §ion, int x, int y, int z)
|
||||
{
|
||||
Context *context = scene->GetContext();
|
||||
|
||||
pv::Vector3DInt16 section_p = section.section_p;
|
||||
pv::Vector3DInt32 chunk_p(
|
||||
section_p.getX() * m_section_size_chunks.getX() + x,
|
||||
section_p.getY() * m_section_size_chunks.getY() + y,
|
||||
section_p.getZ() * m_section_size_chunks.getZ() + z
|
||||
);
|
||||
|
||||
Vector3 node_p(
|
||||
chunk_p.getX() * m_chunk_size_voxels.getX() +
|
||||
m_chunk_size_voxels.getX() / 2.0f,
|
||||
chunk_p.getY() * m_chunk_size_voxels.getY() +
|
||||
m_chunk_size_voxels.getY() / 2.0f,
|
||||
chunk_p.getZ() * m_chunk_size_voxels.getZ() +
|
||||
m_chunk_size_voxels.getZ() / 2.0f
|
||||
);
|
||||
log_t(MODULE, "create_chunk_node(): node_p=(%f, %f, %f)",
|
||||
node_p.x_, node_p.y_, node_p.z_);
|
||||
|
||||
ss_ name = "static_"+dump(section_p)+")"+
|
||||
"_("+itos(x)+","+itos(y)+","+itos(x)+")";
|
||||
Node *n = scene->CreateChild(name.c_str());
|
||||
n->SetScale(Vector3(1.0f, 1.0f, 1.0f));
|
||||
n->SetPosition(node_p);
|
||||
|
||||
int w = m_chunk_size_voxels.getX();
|
||||
int h = m_chunk_size_voxels.getY();
|
||||
int d = m_chunk_size_voxels.getZ();
|
||||
size_t data_len = w * h * d;
|
||||
ss_ data(data_len, '\0');
|
||||
|
||||
data[data_len/2] = '\x02';
|
||||
|
||||
// Crude way of dynamically defining a voxel model
|
||||
n->SetVar(StringHash("buildat_voxel_data"), Variant(
|
||||
PODVector<uint8_t>((const uint8_t*)data.c_str(), data.size())));
|
||||
n->SetVar(StringHash("buildat_voxel_w"), Variant(w));
|
||||
n->SetVar(StringHash("buildat_voxel_h"), Variant(h));
|
||||
n->SetVar(StringHash("buildat_voxel_d"), Variant(d));
|
||||
|
||||
// Load the same model in here and give it to the physics
|
||||
// subsystem so that it can be collided to
|
||||
SharedPtr<Model> model(interface::
|
||||
create_8bit_voxel_physics_model(context, w, h, d, data,
|
||||
m_voxel_reg.get()));
|
||||
|
||||
/*RigidBody *body = n->CreateComponent<RigidBody>();
|
||||
body->SetFriction(0.75f);
|
||||
CollisionShape *shape = n->CreateComponent<CollisionShape>();
|
||||
shape->SetTriangleMesh(model, 0, Vector3::ONE);*/
|
||||
}
|
||||
|
||||
void create_section(Section §ion)
|
||||
{
|
||||
m_server->access_scene([&](Scene *scene)
|
||||
{
|
||||
auto lc = section.contained_chunks.getLowerCorner();
|
||||
auto uc = section.contained_chunks.getUpperCorner();
|
||||
for(int z = lc.getZ(); z <= uc.getZ(); z++){
|
||||
for(int y = lc.getY(); y <= uc.getY(); y++){
|
||||
for(int x = lc.getX(); x <= uc.getX(); x++){
|
||||
create_chunk_node(scene, section, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Somehow get the section's static nodes and possible other nodes, either
|
||||
// by loading from disk or by creating new ones
|
||||
void load_section(Section §ion)
|
||||
{
|
||||
if(section.loaded)
|
||||
return;
|
||||
section.loaded = true;
|
||||
pv::Vector3DInt16 section_p = section.section_p;
|
||||
log_v(MODULE, "Loading section " PV3I_FORMAT, PV3I_PARAMS(section_p));
|
||||
// TODO: If found on disk, load nodes from there
|
||||
// TODO: If not found on disk, create new static nodes
|
||||
// Always create new nodes for now
|
||||
create_section(section);
|
||||
}
|
||||
|
||||
// Generate the section; requires static nodes to already exist
|
||||
void generate_section(Section §ion)
|
||||
{
|
||||
if(section.generated)
|
||||
return;
|
||||
section.generated = true;
|
||||
pv::Vector3DInt16 section_p = section.section_p;
|
||||
log_v(MODULE, "Generating section " PV3I_FORMAT, PV3I_PARAMS(section_p));
|
||||
// TODO
|
||||
}
|
||||
|
||||
// Interface
|
||||
|
||||
void load_or_generate_section(const pv::Vector3DInt16 §ion_p)
|
||||
{
|
||||
Section §ion = get_section(section_p);
|
||||
if(!section.loaded)
|
||||
load_section(section);
|
||||
if(!section.generated)
|
||||
generate_section(section);
|
||||
}
|
||||
|
||||
void* get_interface()
|
||||
{
|
||||
return dynamic_cast<Interface*>(this);
|
||||
|
|
|
@ -8,22 +8,32 @@ buildat.extension_path = __buildat_extension_path
|
|||
|
||||
buildat.safe.disconnect = __buildat_disconnect
|
||||
|
||||
function buildat.safe.set_simple_voxel_model(safe_node, w, h, d, data)
|
||||
function buildat.safe.set_simple_voxel_model(safe_node, w, h, d, safe_buffer)
|
||||
if not getmetatable(safe_node) or
|
||||
getmetatable(safe_node).type_name ~= "Node" then
|
||||
error("Node is not a sandboxed Node instance")
|
||||
error("node is not a sandboxed Node instance")
|
||||
end
|
||||
if not getmetatable(safe_buffer) or
|
||||
getmetatable(safe_buffer).type_name ~= "VectorBuffer" then
|
||||
error("safe_buffer is not a sandboxed VectorBuffer instance")
|
||||
end
|
||||
node = getmetatable(safe_node).unsafe
|
||||
__buildat_set_simple_voxel_model(node, w, h, d, data)
|
||||
buffer = getmetatable(safe_buffer).unsafe
|
||||
__buildat_set_simple_voxel_model(node, w, h, d, buffer)
|
||||
end
|
||||
|
||||
function buildat.safe.set_8bit_voxel_geometry(safe_node, w, h, d, data)
|
||||
function buildat.safe.set_8bit_voxel_geometry(safe_node, w, h, d, safe_buffer)
|
||||
if not getmetatable(safe_node) or
|
||||
getmetatable(safe_node).type_name ~= "Node" then
|
||||
error("Node is not a sandboxed Node instance")
|
||||
error("node is not a sandboxed Node instance")
|
||||
end
|
||||
if not getmetatable(safe_buffer) or
|
||||
getmetatable(safe_buffer).type_name ~= "VectorBuffer" then
|
||||
error("safe_buffer is not a sandboxed VectorBuffer instance")
|
||||
end
|
||||
node = getmetatable(safe_node).unsafe
|
||||
__buildat_set_8bit_voxel_geometry(node, w, h, d, data)
|
||||
buffer = getmetatable(safe_buffer).unsafe
|
||||
__buildat_set_8bit_voxel_geometry(node, w, h, d, buffer)
|
||||
end
|
||||
|
||||
local IntVector3_prototype = {
|
||||
|
|
|
@ -199,6 +199,10 @@ The voxel world:
|
|||
- data modification version ("buildat_voxel_mod_version")
|
||||
- The data can be raw or compresed, and it can be cached by node id and data
|
||||
modification version
|
||||
- Maybe the format could be included as the first byte in the data
|
||||
- Data uses the PODVector<uint8_t> type in Urho3D::Variant because the
|
||||
String type fails to work with zeroes. It is visible to Lua as
|
||||
VectorBuffer.
|
||||
- The client is allowed to see all voxel data for each node that gets synced
|
||||
over network.
|
||||
- Data can be hidden in local components or other storage on the server.
|
||||
|
|
|
@ -35,3 +35,5 @@ Buildat TODO
|
|||
- Allow creating and destroying arbitrary amounts of replicated scenes
|
||||
- Switch to using #define MODULE in modules, and rename Module::MODULE
|
||||
- magic.sub_sync_node_added -> replicate.sub_sync_node_added
|
||||
- Use tags for module dependencies (tags, require_tag, disallow_tag), and
|
||||
auto-tag each module at runtime with game_<current_game>
|
||||
|
|
|
@ -15,6 +15,16 @@ function M.define(dst, util)
|
|||
}
|
||||
})
|
||||
|
||||
util.wc("VectorBuffer", {
|
||||
instance = {
|
||||
GetSize = util.self_function(
|
||||
"GetSize", {"number"}, {"VectorBuffer"}),
|
||||
},
|
||||
properties = {
|
||||
size = util.simple_property("number"),
|
||||
},
|
||||
})
|
||||
|
||||
util.wc("Variant", {
|
||||
unsafe_constructor = util.wrap_function({{"Color"}},
|
||||
function(value)
|
||||
|
@ -27,6 +37,11 @@ function M.define(dst, util)
|
|||
"GetString", {"string"}, {"Variant"}),
|
||||
GetInt = util.self_function(
|
||||
"GetInt", {"number"}, {"Variant"}),
|
||||
GetBuffer = util.wrap_function({"Variant"},
|
||||
function(self)
|
||||
return util.wrap_instance("VectorBuffer", self:GetBuffer())
|
||||
end
|
||||
),
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -154,6 +169,11 @@ function M.define(dst, util)
|
|||
|
||||
util.wc("Camera", {
|
||||
inherited_from_by_wrapper = dst.Component,
|
||||
properties = {
|
||||
nearClip = util.simple_property("number"),
|
||||
farClip = util.simple_property("number"),
|
||||
fov = util.simple_property("number"),
|
||||
},
|
||||
})
|
||||
|
||||
util.wc("Model", {
|
||||
|
|
|
@ -13,8 +13,11 @@ local scene = replicate.main_scene
|
|||
|
||||
-- Add a camera so we can look at the scene
|
||||
local camera_node = scene:CreateChild("Camera")
|
||||
camera_node:CreateComponent("Camera")
|
||||
camera_node.position = magic.Vector3(7.0, 7.0, 7.0)
|
||||
local camera = camera_node:CreateComponent("Camera")
|
||||
camera.nearClip = 1.0
|
||||
camera.farClip = 500.0
|
||||
--camera_node.position = magic.Vector3(10.0, 10.0, 10.0)
|
||||
camera_node.position = magic.Vector3(100.0, 100.0, 100.0)
|
||||
camera_node:LookAt(magic.Vector3(0, 1, 0))
|
||||
|
||||
-- And this thing so the camera is shown on the screen
|
||||
|
|
|
@ -21,15 +21,30 @@ using namespace Urho3D;
|
|||
|
||||
namespace lua_bindings {
|
||||
|
||||
#define GET_TOLUA_STUFF(result_name, index, type)\
|
||||
if(!tolua_isusertype(L, index, #type, 0, &tolua_err)){\
|
||||
tolua_error(L, __PRETTY_FUNCTION__, &tolua_err);\
|
||||
return 0;\
|
||||
}\
|
||||
type *result_name = (type*)tolua_tousertype(L, index, 0);
|
||||
|
||||
// NOTE: This API is designed this way because otherwise ownership management of
|
||||
// objects sucks
|
||||
// set_simple_voxel_model(node, w, h, d, data: string)
|
||||
// set_simple_voxel_model(node, w, h, d, buffer: VectorBuffer)
|
||||
static int l_set_simple_voxel_model(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
int w = lua_tointeger(L, 2);
|
||||
int h = lua_tointeger(L, 3);
|
||||
int d = lua_tointeger(L, 4);
|
||||
ss_ data = lua_tocppstring(L, 5);
|
||||
GET_TOLUA_STUFF(buf, 5, const VectorBuffer);
|
||||
|
||||
log_d(MODULE, "set_simple_voxel_model(): buf=%p", buf);
|
||||
log_d(MODULE, "set_simple_voxel_model(): node=%p", node);
|
||||
|
||||
ss_ data((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||
|
||||
if((int)data.size() != w * h * d){
|
||||
log_e(MODULE, "set_simple_voxel_model(): Data size does not match "
|
||||
|
@ -37,17 +52,6 @@ static int l_set_simple_voxel_model(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
tolua_Error tolua_err;
|
||||
//if(!tolua_isusertype(L, 1, "const Node", 0, &tolua_err)){
|
||||
if(!tolua_isusertype(L, 1, "Node", 0, &tolua_err)){
|
||||
tolua_error(L, "Error in set_simple_voxel_model", &tolua_err);
|
||||
return 0;
|
||||
}
|
||||
log_d(MODULE, "set_simple_voxel_model(): Valid Node given");
|
||||
//const Node *node = (const Node*)tolua_tousertype(L, 1, 0);
|
||||
Node *node = (Node*)tolua_tousertype(L, 1, 0);
|
||||
log_d(MODULE, "set_simple_voxel_model(): node=%p", node);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__buildat_app");
|
||||
app::App *buildat_app = (app::App*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
@ -62,13 +66,20 @@ static int l_set_simple_voxel_model(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// set_8bit_voxel_geometry(node, w, h, d, data: string)
|
||||
// set_8bit_voxel_geometry(node, w, h, d, buffer: VectorBuffer)
|
||||
static int l_set_8bit_voxel_geometry(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
int w = lua_tointeger(L, 2);
|
||||
int h = lua_tointeger(L, 3);
|
||||
int d = lua_tointeger(L, 4);
|
||||
ss_ data = lua_tocppstring(L, 5);
|
||||
GET_TOLUA_STUFF(buf, 5, const VectorBuffer);
|
||||
log_d(MODULE, "set_simple_voxel_model(): buf=%p", buf);
|
||||
log_d(MODULE, "set_8bit_voxel_geometry(): node=%p", node);
|
||||
|
||||
ss_ data((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||
|
||||
if((int)data.size() != w * h * d){
|
||||
log_e(MODULE, "set_8bit_voxel_geometry(): Data size does not match "
|
||||
|
@ -76,17 +87,6 @@ static int l_set_8bit_voxel_geometry(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
tolua_Error tolua_err;
|
||||
//if(!tolua_isusertype(L, 1, "const Node", 0, &tolua_err)){
|
||||
if(!tolua_isusertype(L, 1, "Node", 0, &tolua_err)){
|
||||
tolua_error(L, "Error in set_8bit_voxel_geometry", &tolua_err);
|
||||
return 0;
|
||||
}
|
||||
log_d(MODULE, "set_8bit_voxel_geometry(): Valid Node given");
|
||||
//const Node *node = (const Node*)tolua_tousertype(L, 1, 0);
|
||||
Node *node = (Node*)tolua_tousertype(L, 1, 0);
|
||||
log_d(MODULE, "set_8bit_voxel_geometry(): node=%p", node);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__buildat_app");
|
||||
app::App *buildat_app = (app::App*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
|
Loading…
Reference in New Issue