builtin/voxelworld, games/digger: Way more robust startup sequence

master
Perttu Ahola 2014-10-28 00:20:52 +02:00
parent c0d87faab0
commit 261864ff42
4 changed files with 70 additions and 41 deletions

View File

@ -47,8 +47,7 @@ M.section_size_voxels = nil
-- be triggered to reflect this value
M.camera_far_clip = 1000
-- voxelworld is ready once the init and voxel_registry packets (and in the
-- future possibly some other ones) have been received)
-- client-side voxelworld is ready once the server tells it is
local is_ready = false
local on_ready_callbacks = {}
@ -71,7 +70,36 @@ function on_ready()
on_ready_callbacks = nil
end
local function sub_events()
buildat.sub_packet("voxelworld:init", function(data)
local values = cereal.binary_input(data, {"object",
{"chunk_size_voxels", {"object",
{"x", "int16_t"},
{"y", "int16_t"},
{"z", "int16_t"},
}},
{"section_size_chunks", {"object",
{"x", "int16_t"},
{"y", "int16_t"},
{"z", "int16_t"},
}},
})
log:info("voxelworld:init: "..dump(values))
M.chunk_size_voxels = buildat.Vector3(values.chunk_size_voxels)
M.section_size_chunks = buildat.Vector3(values.section_size_chunks)
M.section_size_voxels =
M.chunk_size_voxels:mul_components(M.section_size_chunks)
end)
buildat.sub_packet("voxelworld:voxel_registry", function(data)
voxel_reg:deserialize(data)
end)
buildat.sub_packet("voxelworld:ready", function(data)
sub_events()
on_ready()
end)
function sub_events()
local node_update_queue = buildat.SpatialUpdateQueue()
local function queue_initial_node_update(node)
@ -104,31 +132,6 @@ local function sub_events()
})
end
buildat.sub_packet("voxelworld:init", function(data)
local values = cereal.binary_input(data, {"object",
{"chunk_size_voxels", {"object",
{"x", "int16_t"},
{"y", "int16_t"},
{"z", "int16_t"},
}},
{"section_size_chunks", {"object",
{"x", "int16_t"},
{"y", "int16_t"},
{"z", "int16_t"},
}},
})
log:info("voxelworld:init: "..dump(values))
M.chunk_size_voxels = buildat.Vector3(values.chunk_size_voxels)
M.section_size_chunks = buildat.Vector3(values.section_size_chunks)
M.section_size_voxels =
M.chunk_size_voxels:mul_components(M.section_size_chunks)
end)
buildat.sub_packet("voxelworld:voxel_registry", function(data)
voxel_reg:deserialize(data)
on_ready() -- This is the last packet
end)
buildat.sub_packet("voxelworld:node_volume_updated", function(data)
local values = cereal.binary_input(data, {"object",
{"node_id", "int32_t"},
@ -520,7 +523,5 @@ function send_get_section(p)
buildat.send_packet("voxelworld:get_section", data)
end
sub_events()
return M
-- vim: set noet ts=4 sw=4:

View File

@ -244,6 +244,9 @@ struct Module: public interface::Module, public voxelworld::Interface
// (as a sorted array in descending node_id order)
std::vector<QueuedNodePhysicsUpdate> m_nodes_needing_physics_update;
// Clients that are ready to receive things (by peer id)
set_<int> m_clients_initialized;
Module(interface::Server *server):
interface::Module(MODULE),
m_server(server)
@ -394,6 +397,7 @@ struct Module: public interface::Module, public voxelworld::Interface
void on_client_disconnected(const network::OldClient &old_client)
{
m_clients_initialized.erase(old_client.info.id);
}
void on_tick(const interface::TickEvent &event)
@ -431,6 +435,12 @@ struct Module: public interface::Module, public voxelworld::Interface
// Unload stuff if needed
maintain_maximum_buffer_limit();
// Send updated voxel registry if needed
send_voxel_registry_if_dirty();
}
void send_voxel_registry_if_dirty()
{
// Send updated voxel registry if needed
// NOTE: This probably really only supports additions
if(m_voxel_reg->is_dirty()){
@ -442,6 +452,8 @@ struct Module: public interface::Module, public voxelworld::Interface
network::access(m_server, [&](network::Interface *inetwork){
sv_<network::PeerInfo::Id> peers = inetwork->list_peers();
for(auto &peer: peers){
if(!m_clients_initialized.count(peer))
continue;
inetwork->send(peer, "voxelworld:voxel_registry",
voxel_reg_data);
}
@ -452,12 +464,12 @@ struct Module: public interface::Module, public voxelworld::Interface
void on_files_transmitted(const client_file::FilesTransmitted &event)
{
int peer = event.recipient;
// Load the client-side module
network::access(m_server, [&](network::Interface *inetwork){
// Load the module by calling require() on it so that it can start
// receiving data
inetwork->send(peer, "core:run_script",
"require(\"buildat/module/voxelworld\")");
});
// Send initialization data and tell the client that it is now ready
std::ostringstream os(std::ios::binary);
{
cereal::PortableBinaryOutputArchive ar(os);
@ -468,7 +480,9 @@ struct Module: public interface::Module, public voxelworld::Interface
inetwork->send(peer, "voxelworld:init", os.str());
inetwork->send(peer, "voxelworld:voxel_registry",
m_voxel_reg->serialize());
inetwork->send(peer, "voxelworld:ready", "");
});
m_clients_initialized.insert(peer);
}
// TODO: How should nodes be filtered for replication?
@ -971,9 +985,11 @@ struct Module: public interface::Module, public voxelworld::Interface
run_commit_hooks_in_scene(chunk_p, n);
});
// Tell replicate to emit events once it has done its job
// TODO: Have some way of invoking replication directly for this node;
// this is too slow
// First send updated voxel registry to clients so that they are ready
// to generate stuff from the voxels
send_voxel_registry_if_dirty();
// Then synchronize node and notify clients about it
sv_<replicate::PeerId> peers;
replicate::access(m_server, [&](replicate::Interface *ireplicate){
ireplicate->sync_node_immediate(node_id);
@ -986,6 +1002,8 @@ struct Module: public interface::Module, public voxelworld::Interface
}
network::access(m_server, [&](network::Interface *inetwork){
for(auto &peer_id: peers){
if(!m_clients_initialized.count(peer_id))
continue;
inetwork->send(peer_id, "voxelworld:node_volume_updated",
os.str());
}

View File

@ -73,6 +73,7 @@ struct Module: public interface::Module
{
m_server->sub_event(this, Event::t("core:start"));
m_server->sub_event(this, Event::t("core:continue"));
m_server->sub_event(this, Event::t("worldgen:voxels_defined"));
m_server->sub_event(this, Event::t("core:tick"));
m_server->sub_event(this, Event::t("client_file:files_transmitted"));
m_server->sub_event(this, Event::t(
@ -85,6 +86,7 @@ struct Module: public interface::Module
{
EVENT_VOIDN("core:start", on_start)
EVENT_VOIDN("core:continue", on_continue)
EVENT_VOIDN("worldgen:voxels_defined", on_voxels_defined)
EVENT_TYPEN("core:tick", on_tick, interface::TickEvent)
EVENT_TYPEN("client_file:files_transmitted",
on_files_transmitted, client_file::FilesTransmitted)
@ -95,6 +97,14 @@ struct Module: public interface::Module
}
void on_start()
{
}
void on_continue()
{
}
void on_voxels_defined()
{
voxelworld::access(m_server, [&](voxelworld::Interface *ivoxelworld)
{
@ -148,10 +158,6 @@ struct Module: public interface::Module
});
}
void on_continue()
{
}
void update_scene()
{
}
@ -171,8 +177,10 @@ struct Module: public interface::Module
{
Scene *scene = imc->get_scene();
Node *n = scene->GetChild("Testbox");
n->SetRotation(Quaternion(30, 60, 90));
n->SetPosition(Vector3(30.0f, 30.0f, 40.0f));
if(n){
n->SetRotation(Quaternion(30, 60, 90));
n->SetPosition(Vector3(30.0f, 30.0f, 40.0f));
}
});
}
}

View File

@ -207,6 +207,8 @@ struct Module: public interface::Module
voxel_reg->add_voxel(vdef); // id 6
}
});
m_server->emit_event(Event("worldgen:voxels_defined"));
}
void on_continue()