162 lines
4.7 KiB
Lua
Raw Normal View History

-- Buildat: builtin/voxelworld/client_lua/module.lua
-- http://www.apache.org/licenses/LICENSE-2.0
-- Copyright 2014 Perttu Ahola <celeron55@gmail.com>
local log = buildat.Logger("voxelworld")
2014-10-12 10:11:36 +03:00
local magic = require("buildat/extension/urho3d")
local replicate = require("buildat/extension/replicate")
local cereal = require("buildat/extension/cereal")
local dump = buildat.dump
local M = {}
2014-10-12 10:11:36 +03:00
local camera_node = nil
2014-10-12 11:26:33 +03:00
local update_counter = -1
local camera_last_dir = magic.Vector3(0, 0, 0)
2014-10-13 01:32:58 +03:00
local camera_last_p = magic.Vector3(0, 0, 0)
2014-10-12 11:26:33 +03:00
M.chunk_size_voxels = nil
M.section_size_chunks = nil
M.section_size_voxels = nil
2014-10-12 10:11:36 +03:00
function M.init()
log:info("voxelworld.init()")
2014-10-12 10:11:36 +03:00
buildat.sub_packet("voxelworld:init", function(data)
local values = cereal.binary_input(data, {"object",
{"chunk_size_voxels", {"object",
{"x", "int32_t"},
{"y", "int32_t"},
{"z", "int32_t"},
}},
{"section_size_chunks", {"object",
{"x", "int32_t"},
{"y", "int32_t"},
{"z", "int32_t"},
}},
})
log:info(dump(values))
2014-10-12 11:26:33 +03:00
M.chunk_size_voxels = buildat.IntVector3(values.chunk_size_voxels)
M.section_size_chunks = buildat.IntVector3(values.section_size_chunks)
M.section_size_voxels =
M.chunk_size_voxels:mul_components(M.section_size_chunks)
2014-10-12 10:11:36 +03:00
end)
local function update_voxel_geometry(node)
local data = node:GetVar("buildat_voxel_data"):GetBuffer()
--local registry_name = node:GetVar("buildat_voxel_registry_name"):GetBuffer()
log:info(dump(node:GetName()).." voxel data size: "..data:GetSize())
buildat.set_voxel_geometry(node, data, registry_name)
end
local function update_voxel_physics(node)
local data = node:GetVar("buildat_voxel_data"):GetBuffer()
--local registry_name = node:GetVar("buildat_voxel_registry_name"):GetBuffer()
log:info(dump(node:GetName()).." voxel data size: "..data:GetSize())
buildat.set_voxel_physics_boxes(node, data, registry_name)
end
local node_geometry_update_queue = {}
local node_physics_update_queue = {}
local function get_closest_update(queue)
-- Find closest one
local camera_p = camera_node:GetWorldPosition()
local closest_d = nil
local closest_k = nil
for k, node in ipairs(queue) do
local d = (node:GetWorldPosition() - camera_p):Length()
if closest_d == nil or d < closest_d then
closest_d = d
closest_k = k
end
end
return table.remove(queue, closest_k)
end
2014-10-12 10:11:36 +03:00
magic.SubscribeToEvent("Update", function(event_type, event_data)
update_counter = update_counter + 1
2014-10-12 13:28:24 +03:00
if camera_node and M.section_size_voxels then
-- TODO: How should position information be sent to the server?
local p = camera_node:GetWorldPosition()
2014-10-12 10:11:36 +03:00
if update_counter % 60 == 0 then
2014-10-12 11:26:33 +03:00
local section_p = buildat.IntVector3(p):div_components(
M.section_size_voxels):floor()
2014-10-12 13:28:24 +03:00
--log:info("p: "..p.x..", "..p.y..", "..p.z.." -> section_p: "..
-- section_p.x..", "..section_p.y..", "..section_p.z)
2014-10-12 11:26:33 +03:00
--[[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))
send_get_section(section_p + buildat.IntVector3( 0, 1, 0))
send_get_section(section_p + buildat.IntVector3( 0,-1, 0))
send_get_section(section_p + buildat.IntVector3( 0, 0, 1))
send_get_section(section_p + buildat.IntVector3( 0, 0,-1))]]
2014-10-12 10:11:36 +03:00
end
end
-- Handle geometry updates one node per frame
if update_counter % 2 == 0 then
2014-10-13 01:32:58 +03:00
if #node_geometry_update_queue > 0 then
local nodes_per_frame = 1
for i = 1, nodes_per_frame do
local node = get_closest_update(node_geometry_update_queue)
if not node then
break
end
update_voxel_geometry(node)
2014-10-13 01:32:58 +03:00
end
end
else
if #node_physics_update_queue > 0 then
local nodes_per_frame = 1
2014-10-13 01:32:58 +03:00
for i = 1, nodes_per_frame do
local node = get_closest_update(node_physics_update_queue)
if not node then
break
end
update_voxel_physics(node)
2014-10-13 01:32:58 +03:00
end
end
end
if camera_node then
local camera_dir = camera_node.direction
local camera_p = camera_node:GetWorldPosition()
2014-10-13 01:32:58 +03:00
camera_last_dir = camera_dir
camera_last_p = camera_p
end
2014-10-12 10:11:36 +03:00
end)
2014-10-12 11:26:33 +03:00
replicate.sub_sync_node_added({}, function(node)
if not node:GetVar("buildat_voxel_data"):IsEmpty() then
table.insert(node_geometry_update_queue, node)
table.insert(node_physics_update_queue, node)
2014-10-12 11:26:33 +03:00
end
local name = node:GetName()
end)
2014-10-12 10:11:36 +03:00
end
function M.set_camera(new_camera_node)
camera_node = new_camera_node
end
2014-10-12 11:26:33 +03:00
function send_get_section(p)
local data = cereal.binary_output({
p = {
x = p.x,
y = p.y,
z = p.z,
},
}, {"object",
{"p", {"object",
{"x", "int32_t"},
{"y", "int32_t"},
{"z", "int32_t"},
}},
})
--log:info(dump(buildat.bytes(data)))
buildat.send_packet("voxelworld:get_section", data)
end
return M
-- vim: set noet ts=4 sw=4: