client: voxelworld.get_static_voxel()
parent
3c25b40bae
commit
d2839d5cf3
|
@ -13,7 +13,8 @@ local M = {}
|
||||||
-- because each chunk will be rendered as a whole according to the zone its
|
-- because each chunk will be rendered as a whole according to the zone its
|
||||||
-- center position is in
|
-- center position is in
|
||||||
--local ideal_zone_size = 32
|
--local ideal_zone_size = 32
|
||||||
-- NOTE: Actually, when zone overrides are used, this can be lower
|
-- NOTE: Actually, when zone overrides are used, this can be lower; but it will
|
||||||
|
-- require more processing as all renderable things are in the same octree
|
||||||
local ideal_zone_size = 16
|
local ideal_zone_size = 16
|
||||||
|
|
||||||
M.sector_size = buildat.Vector2(0, 0)
|
M.sector_size = buildat.Vector2(0, 0)
|
||||||
|
|
|
@ -362,6 +362,78 @@ function M.sub_geometry_update(cb)
|
||||||
table.insert(geometry_update_cbs, cb)
|
table.insert(geometry_update_cbs, cb)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Return value: VoxelInstance (found), VoxelInstance(0) (not found)
|
||||||
|
function M.get_static_voxel(p)
|
||||||
|
p = buildat.Vector3(p):round()
|
||||||
|
log:debug("get_static_voxel(): p="..p:dump())
|
||||||
|
-- Calculate which chunk this voxel is in
|
||||||
|
local chunk_p = p:div_components(M.chunk_size_voxels):floor()
|
||||||
|
log:debug("get_static_voxel(): chunk_p="..chunk_p:dump())
|
||||||
|
-- NOTE: Chunks are positioned by their center position, and chunks are
|
||||||
|
-- aligned to a grid offset by half their size from global origin
|
||||||
|
local chunk_center_p = chunk_p:mul_components(M.chunk_size_voxels) +
|
||||||
|
M.chunk_size_voxels / 2
|
||||||
|
log:debug("get_static_voxel(): chunk_center_p="..chunk_center_p:dump())
|
||||||
|
|
||||||
|
-- Find the static node
|
||||||
|
local scene = replicate.main_scene
|
||||||
|
local octree = scene:GetComponent("Octree")
|
||||||
|
local clearance = magic.Vector3(1,1,1)
|
||||||
|
local find_lc = chunk_center_p - clearance
|
||||||
|
local find_uc = chunk_center_p + clearance
|
||||||
|
log:debug("get_static_voxel(): find_lc="..find_lc:dump())
|
||||||
|
log:debug("get_static_voxel(): find_uc="..find_uc:dump())
|
||||||
|
local result = octree:GetDrawables(magic.BoundingBox(
|
||||||
|
magic.Vector3.from_buildat(find_lc),
|
||||||
|
magic.Vector3.from_buildat(find_uc)))
|
||||||
|
log:debug("get_static_voxel(): result="..dump(result))
|
||||||
|
-- NOTE: The result will contain all kinds of global things like zones and
|
||||||
|
-- lights
|
||||||
|
-- NOTE: Static nodes can be distinguished by the user variable
|
||||||
|
-- buildat_static=true
|
||||||
|
local node = nil
|
||||||
|
for _, v in ipairs(result) do
|
||||||
|
--log:debug("get_static_voxel(): result node:GetName()="..v.node:GetName())
|
||||||
|
local buildat_static_var = v.node:GetVar("buildat_static")
|
||||||
|
if buildat_static_var:GetBool() == true then
|
||||||
|
node = v.node
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if node == nil then
|
||||||
|
log:debug("get_static_voxel(): static node not found")
|
||||||
|
for _, v in ipairs(result) do
|
||||||
|
log:debug("get_static_voxel(): * not "..v.node:GetName())
|
||||||
|
end
|
||||||
|
return buildat.VoxelInstance(0)
|
||||||
|
end
|
||||||
|
-- Calculate position inside the chunk
|
||||||
|
local in_chunk_p = p - M.chunk_size_voxels:mul_components(chunk_p)
|
||||||
|
log:debug("get_static_voxel(): in_chunk_p="..in_chunk_p:dump())
|
||||||
|
-- Get voxel from volume
|
||||||
|
local data = node:GetVar("buildat_voxel_data"):GetBuffer()
|
||||||
|
if data == nil then
|
||||||
|
log_w(MODULE, "Invalid static node does not contain buildat_voxel_data")
|
||||||
|
return buildat.VoxelInstance(0)
|
||||||
|
end
|
||||||
|
local volume = buildat.deserialize_volume(data)
|
||||||
|
log:debug("get_static_voxel(): volume="..dump(volume))
|
||||||
|
local v = volume:get_voxel_at(in_chunk_p.x, in_chunk_p.y, in_chunk_p.z)
|
||||||
|
log:debug("get_static_voxel(): v="..dump(v))
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO
|
||||||
|
-- NOTE: This does not synchronize the voxel to the server, because games have
|
||||||
|
-- to implement their own mechanisms for disallowing cheating
|
||||||
|
function M.set_static_voxel(x, y, z, v)
|
||||||
|
if type(x) == "table" then
|
||||||
|
z = x.z
|
||||||
|
y = x.y
|
||||||
|
x = x.x
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function send_get_section(p)
|
function send_get_section(p)
|
||||||
local data = cereal.binary_output({
|
local data = cereal.binary_output({
|
||||||
p = {
|
p = {
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <ResourceCache.h>
|
#include <ResourceCache.h>
|
||||||
#include <Light.h>
|
#include <Light.h>
|
||||||
#include <Geometry.h>
|
#include <Geometry.h>
|
||||||
|
#include <Zone.h>
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -533,13 +534,23 @@ struct Module: public interface::Module, public voxelworld::Interface
|
||||||
throw Exception("Can't handle static node id=0");
|
throw Exception("Can't handle static node id=0");
|
||||||
section.node_ids->setVoxelAt(chunk_p, n->GetID());
|
section.node_ids->setVoxelAt(chunk_p, n->GetID());
|
||||||
|
|
||||||
n->SetScale(Vector3(1.0f, 1.0f, 1.0f));
|
// Distinguish static voxel nodes from others
|
||||||
n->SetPosition(node_p);
|
n->SetVar(StringHash("buildat_static"), Variant(true));
|
||||||
|
|
||||||
int w = m_chunk_size_voxels.getX();
|
int w = m_chunk_size_voxels.getX();
|
||||||
int h = m_chunk_size_voxels.getY();
|
int h = m_chunk_size_voxels.getY();
|
||||||
int d = m_chunk_size_voxels.getZ();
|
int d = m_chunk_size_voxels.getZ();
|
||||||
|
|
||||||
|
// This makes sure the node will be found when searched from the octree,
|
||||||
|
// both on the server and the client
|
||||||
|
Zone *node_zone = n->CreateComponent<Zone>();
|
||||||
|
node_zone->SetPriority(-1000);
|
||||||
|
node_zone->SetBoundingBox(BoundingBox(
|
||||||
|
Vector3(-w/2, -h/2, -d/2), Vector3(w/2, h/2, d/2)));
|
||||||
|
|
||||||
|
n->SetScale(Vector3(1.0f, 1.0f, 1.0f));
|
||||||
|
n->SetPosition(node_p);
|
||||||
|
|
||||||
// NOTE: These volumes have one extra voxel at each edge in order to
|
// NOTE: These volumes have one extra voxel at each edge in order to
|
||||||
// make proper meshes without gaps
|
// make proper meshes without gaps
|
||||||
// TODO: Is this needed anymore?
|
// TODO: Is this needed anymore?
|
||||||
|
|
|
@ -20,6 +20,7 @@ buildat.safe.createAtlasRegistry = __buildat_createAtlasRegistry
|
||||||
buildat.safe.Region = __buildat_Region
|
buildat.safe.Region = __buildat_Region
|
||||||
buildat.safe.VoxelInstance = __buildat_VoxelInstance
|
buildat.safe.VoxelInstance = __buildat_VoxelInstance
|
||||||
buildat.safe.Volume = __buildat_Volume
|
buildat.safe.Volume = __buildat_Volume
|
||||||
|
buildat.safe.deserialize_volume = __buildat_deserialize_volume
|
||||||
buildat.safe.deserialize_volume_int32 = __buildat_deserialize_volume_int32
|
buildat.safe.deserialize_volume_int32 = __buildat_deserialize_volume_int32
|
||||||
buildat.safe.deserialize_volume_8bit = __buildat_deserialize_volume_8bit
|
buildat.safe.deserialize_volume_8bit = __buildat_deserialize_volume_8bit
|
||||||
|
|
||||||
|
@ -225,6 +226,10 @@ local Vector3_prototype = {
|
||||||
return buildat.safe.Vector3(
|
return buildat.safe.Vector3(
|
||||||
math.floor(a.x), math.floor(a.y), math.floor(a.z))
|
math.floor(a.x), math.floor(a.y), math.floor(a.z))
|
||||||
end,
|
end,
|
||||||
|
round = function(a)
|
||||||
|
return buildat.safe.Vector3(
|
||||||
|
math.floor(a.x+0.5), math.floor(a.y+0.5), math.floor(a.z+0.5))
|
||||||
|
end,
|
||||||
add = function(a, b)
|
add = function(a, b)
|
||||||
return buildat.safe.Vector3(
|
return buildat.safe.Vector3(
|
||||||
a.x + b.x, a.y + b.y, a.z + b.z)
|
a.x + b.x, a.y + b.y, a.z + b.z)
|
||||||
|
@ -284,6 +289,10 @@ local Vector2_prototype = {
|
||||||
return buildat.safe.Vector2(
|
return buildat.safe.Vector2(
|
||||||
math.floor(a.x), math.floor(a.y))
|
math.floor(a.x), math.floor(a.y))
|
||||||
end,
|
end,
|
||||||
|
round = function(a)
|
||||||
|
return buildat.safe.Vector2(
|
||||||
|
math.floor(a.x+0.5), math.floor(a.y+0.5))
|
||||||
|
end,
|
||||||
add = function(a, b)
|
add = function(a, b)
|
||||||
return buildat.safe.Vector2(
|
return buildat.safe.Vector2(
|
||||||
a.x + b.x, a.y + b.y)
|
a.x + b.x, a.y + b.y)
|
||||||
|
|
|
@ -61,3 +61,5 @@ Buildat TODO
|
||||||
without anyone noticing
|
without anyone noticing
|
||||||
- Altough, network is very rarely modified so it doesn't really matter
|
- Altough, network is very rarely modified so it doesn't really matter
|
||||||
- Rename VoxelInstance::getId() to VoxelInstance::get_id()
|
- Rename VoxelInstance::getId() to VoxelInstance::get_id()
|
||||||
|
- A way of figuring out which voxel is being pointed at
|
||||||
|
- Get rid of the dual module reload when saving a C++ file in Vim
|
||||||
|
|
|
@ -256,6 +256,8 @@ function M.unsafe_to_safe(unsafe_thing, valid_types)
|
||||||
if valid_type == '__nil' and unsafe_thing == nil then
|
if valid_type == '__nil' and unsafe_thing == nil then
|
||||||
return unsafe_thing
|
return unsafe_thing
|
||||||
end
|
end
|
||||||
|
-- NOTE: Do not consider tables safe until explicitly allowed, because
|
||||||
|
-- tables often are unsafe
|
||||||
if valid_type == '__safe' and (
|
if valid_type == '__safe' and (
|
||||||
unsafe_thing == nil or
|
unsafe_thing == nil or
|
||||||
(type(thing_meta) == 'table' and thing_meta.type_name) or
|
(type(thing_meta) == 'table' and thing_meta.type_name) or
|
||||||
|
|
|
@ -49,6 +49,8 @@ function M.define(dst, util)
|
||||||
"GetString", {"string"}, {"Variant"}),
|
"GetString", {"string"}, {"Variant"}),
|
||||||
GetInt = util.self_function(
|
GetInt = util.self_function(
|
||||||
"GetInt", {"number"}, {"Variant"}),
|
"GetInt", {"number"}, {"Variant"}),
|
||||||
|
GetBool = util.self_function(
|
||||||
|
"GetBool", {"boolean"}, {"Variant"}),
|
||||||
GetBuffer = util.wrap_function({"Variant"},
|
GetBuffer = util.wrap_function({"Variant"},
|
||||||
function(self)
|
function(self)
|
||||||
return util.wrap_instance("VectorBuffer", self:GetBuffer())
|
return util.wrap_instance("VectorBuffer", self:GetBuffer())
|
||||||
|
@ -136,6 +138,11 @@ function M.define(dst, util)
|
||||||
function(x, y, z)
|
function(x, y, z)
|
||||||
return util.wrap_instance("Vector3", Vector3(x, y, z))
|
return util.wrap_instance("Vector3", Vector3(x, y, z))
|
||||||
end),
|
end),
|
||||||
|
class = {
|
||||||
|
from_buildat = function(v)
|
||||||
|
return util.wrap_instance("Vector3", Vector3(v.x, v.y, v.z))
|
||||||
|
end,
|
||||||
|
},
|
||||||
instance = {
|
instance = {
|
||||||
Length = util.self_function(
|
Length = util.self_function(
|
||||||
"Length", {"number"}, {"Vector3"}),
|
"Length", {"number"}, {"Vector3"}),
|
||||||
|
@ -271,6 +278,25 @@ function M.define(dst, util)
|
||||||
|
|
||||||
util.wc("Octree", {
|
util.wc("Octree", {
|
||||||
inherited_from_by_wrapper = dst.Component,
|
inherited_from_by_wrapper = dst.Component,
|
||||||
|
instance = {
|
||||||
|
GetDrawables = util.wrap_function({"table"}, {"Octree", "BoundingBox"},
|
||||||
|
function(self, query)
|
||||||
|
local unsafe_result = self:GetDrawables(query)
|
||||||
|
--log:info(dump(result))
|
||||||
|
-- The result is a list of OctreeQueryResults; we will
|
||||||
|
-- convert it to a list of tables that contain the fields of
|
||||||
|
-- OctreeQueryResult.
|
||||||
|
local result = {}
|
||||||
|
for _, v in ipairs(unsafe_result) do
|
||||||
|
table.insert(result, {
|
||||||
|
drawable = util.wrap_instance("Drawable", v.drawable),
|
||||||
|
node = util.wrap_instance("Node", v.node),
|
||||||
|
})
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
util.wc("Drawable", {
|
util.wc("Drawable", {
|
||||||
|
|
|
@ -177,6 +177,10 @@ magic.SubscribeToEvent("KeyDown", function(event_type, event_data)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Return value: nil or buildat.Vector3
|
||||||
|
local function find_pointed_voxel()
|
||||||
|
end
|
||||||
|
|
||||||
magic.SubscribeToEvent("MouseButtonDown", function(event_type, event_data)
|
magic.SubscribeToEvent("MouseButtonDown", function(event_type, event_data)
|
||||||
local button = event_data:GetInt("Button")
|
local button = event_data:GetInt("Button")
|
||||||
log:info("MouseButtonDown: "..button)
|
log:info("MouseButtonDown: "..button)
|
||||||
|
@ -214,6 +218,12 @@ magic.SubscribeToEvent("MouseButtonDown", function(event_type, event_data)
|
||||||
})
|
})
|
||||||
buildat.send_packet("main:dig", data)
|
buildat.send_packet("main:dig", data)
|
||||||
end
|
end
|
||||||
|
if button == magic.MOUSEB_MIDDLE then
|
||||||
|
local p = player_node.position
|
||||||
|
local v = voxelworld.get_static_voxel(p)
|
||||||
|
log:info("get_static_voxel("..buildat.Vector3(p):dump()..")"..
|
||||||
|
" returned v.id="..dump(v.id))
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
magic.SubscribeToEvent("Update", function(event_type, event_data)
|
magic.SubscribeToEvent("Update", function(event_type, event_data)
|
||||||
|
|
|
@ -56,6 +56,20 @@ void voxelinstance_set_int32(VoxelInstance &v, int32_t d){
|
||||||
|
|
||||||
typedef pv::RawVolume<VoxelInstance> CommonVolume;
|
typedef pv::RawVolume<VoxelInstance> CommonVolume;
|
||||||
|
|
||||||
|
sp_<CommonVolume> deserialize_volume(
|
||||||
|
const luabind::object &buffer_o, lua_State *L)
|
||||||
|
{
|
||||||
|
TRY_GET_SANDBOX_STUFF(buf, 1, VectorBuffer);
|
||||||
|
|
||||||
|
ss_ data;
|
||||||
|
if(buf == nullptr)
|
||||||
|
data = lua_checkcppstring(L, 1);
|
||||||
|
else
|
||||||
|
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||||
|
|
||||||
|
return interface::deserialize_volume(data);
|
||||||
|
}
|
||||||
|
|
||||||
sp_<CommonVolume> deserialize_volume_int32(
|
sp_<CommonVolume> deserialize_volume_int32(
|
||||||
const luabind::object &buffer_o, lua_State *L)
|
const luabind::object &buffer_o, lua_State *L)
|
||||||
{
|
{
|
||||||
|
@ -153,6 +167,7 @@ void init_voxel_volume(lua_State *L)
|
||||||
&CommonVolume::setVoxelAt)
|
&CommonVolume::setVoxelAt)
|
||||||
.def("get_enclosing_region", &CommonVolume::getEnclosingRegion)
|
.def("get_enclosing_region", &CommonVolume::getEnclosingRegion)
|
||||||
,
|
,
|
||||||
|
LUABIND_FUNC(deserialize_volume),
|
||||||
LUABIND_FUNC(deserialize_volume_int32),
|
LUABIND_FUNC(deserialize_volume_int32),
|
||||||
LUABIND_FUNC(deserialize_volume_8bit)
|
LUABIND_FUNC(deserialize_volume_8bit)
|
||||||
];
|
];
|
||||||
|
|
Loading…
Reference in New Issue