games/digger/worldgen: Queue generation requests so that generation progress can be measured
This commit is contained in:
parent
1ca6915fe0
commit
8d4fc82919
35
games/digger/worldgen/api.h
Normal file
35
games/digger/worldgen/api.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
// Copyright 2014 Perttu Ahola <celeron55@gmail.com>
|
||||||
|
#pragma once
|
||||||
|
#include "interface/event.h"
|
||||||
|
#include "interface/server.h"
|
||||||
|
#include "interface/module.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace worldgen
|
||||||
|
{
|
||||||
|
struct QueueModifiedEvent: public interface::Event::Private
|
||||||
|
{
|
||||||
|
size_t queue_size;
|
||||||
|
|
||||||
|
QueueModifiedEvent(size_t queue_size):
|
||||||
|
queue_size(queue_size)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Interface
|
||||||
|
{
|
||||||
|
virtual size_t get_num_sections_queued() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool access(interface::Server *server,
|
||||||
|
std::function<void(worldgen::Interface*)> cb)
|
||||||
|
{
|
||||||
|
return server->access_module("worldgen", [&](interface::Module *module){
|
||||||
|
cb((worldgen::Interface*)module->check_interface());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: set noet ts=4 sw=4:
|
||||||
|
|
@ -1,9 +1,6 @@
|
|||||||
#include "core/log.h"
|
#include "core/log.h"
|
||||||
#include "client_file/api.h"
|
|
||||||
#include "network/api.h"
|
|
||||||
#include "replicate/api.h"
|
|
||||||
#include "voxelworld/api.h"
|
#include "voxelworld/api.h"
|
||||||
#include "main_context/api.h"
|
#include "worldgen/api.h"
|
||||||
#include "interface/module.h"
|
#include "interface/module.h"
|
||||||
#include "interface/server.h"
|
#include "interface/server.h"
|
||||||
#include "interface/event.h"
|
#include "interface/event.h"
|
||||||
@ -11,19 +8,14 @@
|
|||||||
#include "interface/voxel.h"
|
#include "interface/voxel.h"
|
||||||
#include "interface/noise.h"
|
#include "interface/noise.h"
|
||||||
#include "interface/voxel_volume.h"
|
#include "interface/voxel_volume.h"
|
||||||
#include <Scene.h>
|
#include "interface/thread.h"
|
||||||
#include <RigidBody.h>
|
#include "interface/semaphore.h"
|
||||||
#include <CollisionShape.h>
|
#include "interface/os.h"
|
||||||
#include <ResourceCache.h>
|
#include <Vector2.h>
|
||||||
#include <Context.h>
|
|
||||||
#include <StaticModel.h>
|
|
||||||
#include <Model.h>
|
|
||||||
#include <Material.h>
|
|
||||||
#include <Texture2D.h>
|
|
||||||
#include <Technique.h>
|
|
||||||
#include <cereal/archives/portable_binary.hpp>
|
#include <cereal/archives/portable_binary.hpp>
|
||||||
#include <cereal/types/unordered_map.hpp>
|
#include <cereal/types/unordered_map.hpp>
|
||||||
#include <cereal/types/vector.hpp>
|
#include <cereal/types/vector.hpp>
|
||||||
|
#include <deque>
|
||||||
#define MODULE "worldgen"
|
#define MODULE "worldgen"
|
||||||
|
|
||||||
namespace magic = Urho3D;
|
namespace magic = Urho3D;
|
||||||
@ -54,20 +46,39 @@ void load(Archive &archive, pv::Vector3DInt32 &v){
|
|||||||
|
|
||||||
namespace worldgen {
|
namespace worldgen {
|
||||||
|
|
||||||
using namespace Urho3D;
|
struct Module;
|
||||||
|
|
||||||
struct Module: public interface::Module
|
struct GenerateThread: public interface::ThreadedThing
|
||||||
|
{
|
||||||
|
Module *m_module = nullptr;
|
||||||
|
|
||||||
|
GenerateThread(Module *module):
|
||||||
|
m_module(module)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void run(interface::Thread *thread);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Module: public interface::Module, public Interface
|
||||||
{
|
{
|
||||||
interface::Server *m_server;
|
interface::Server *m_server;
|
||||||
|
std::deque<pv::Vector3DInt16> m_queued_sections;
|
||||||
|
interface::Semaphore m_queued_sections_sem;
|
||||||
|
sp_<interface::Thread> m_thread;
|
||||||
|
|
||||||
Module(interface::Server *server):
|
Module(interface::Server *server):
|
||||||
interface::Module(MODULE),
|
interface::Module(MODULE),
|
||||||
m_server(server)
|
m_server(server)
|
||||||
{
|
{
|
||||||
|
m_thread.reset(interface::createThread(new GenerateThread(this)));
|
||||||
|
m_thread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
~Module()
|
~Module()
|
||||||
{}
|
{
|
||||||
|
m_thread->request_stop();
|
||||||
|
m_queued_sections_sem.post();
|
||||||
|
}
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
@ -81,6 +92,7 @@ struct Module: public interface::Module
|
|||||||
{
|
{
|
||||||
EVENT_VOIDN("core:start", on_start)
|
EVENT_VOIDN("core:start", on_start)
|
||||||
EVENT_VOIDN("core:continue", on_continue)
|
EVENT_VOIDN("core:continue", on_continue)
|
||||||
|
EVENT_TYPEN("core:tick", on_tick, interface::TickEvent)
|
||||||
EVENT_TYPEN("voxelworld:generation_request",
|
EVENT_TYPEN("voxelworld:generation_request",
|
||||||
on_generation_request, voxelworld::GenerationRequest)
|
on_generation_request, voxelworld::GenerationRequest)
|
||||||
}
|
}
|
||||||
@ -215,18 +227,38 @@ struct Module: public interface::Module
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_scene()
|
void on_tick(const interface::TickEvent &event)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_generation_request(const voxelworld::GenerationRequest &event)
|
void on_generation_request(const voxelworld::GenerationRequest &event)
|
||||||
{
|
{
|
||||||
log_v(MODULE, "on_generation_request(): section_p: (%i, %i, %i)",
|
m_queued_sections.push_back(event.section_p);
|
||||||
|
m_queued_sections_sem.post();
|
||||||
|
log_v(MODULE, "Queued section (%i, %i, %i); queue size: %zu",
|
||||||
event.section_p.getX(), event.section_p.getY(),
|
event.section_p.getX(), event.section_p.getY(),
|
||||||
event.section_p.getZ());
|
event.section_p.getZ(), m_queued_sections.size());
|
||||||
|
m_server->emit_event("worldgen:queue_modified",
|
||||||
|
new QueueModifiedEvent(m_queued_sections.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface for GenerateThread
|
||||||
|
|
||||||
|
// NOTE: on_tick() cannot be used here, because as this takes much longer
|
||||||
|
// than a tick, the ticks accumulate and result in nothing getting
|
||||||
|
// queued but instead sectors get queued in the event queue.
|
||||||
|
void generate_next_section()
|
||||||
|
{
|
||||||
|
if(m_queued_sections.empty())
|
||||||
|
return;
|
||||||
|
const pv::Vector3DInt16 section_p = m_queued_sections.front();
|
||||||
|
m_queued_sections.pop_front();
|
||||||
|
|
||||||
|
log_v(MODULE, "Generating section (%i, %i, %i); queue size: %zu",
|
||||||
|
section_p.getX(), section_p.getY(), section_p.getZ(),
|
||||||
|
m_queued_sections.size());
|
||||||
voxelworld::access(m_server, [&](voxelworld::Interface *ivoxelworld)
|
voxelworld::access(m_server, [&](voxelworld::Interface *ivoxelworld)
|
||||||
{
|
{
|
||||||
const pv::Vector3DInt16 §ion_p = event.section_p;
|
|
||||||
pv::Region region = ivoxelworld->get_section_region_voxels(
|
pv::Region region = ivoxelworld->get_section_region_voxels(
|
||||||
section_p);
|
section_p);
|
||||||
|
|
||||||
@ -328,9 +360,42 @@ struct Module: public interface::Module
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m_server->emit_event("worldgen:queue_modified",
|
||||||
|
new QueueModifiedEvent(m_queued_sections.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface
|
||||||
|
|
||||||
|
size_t get_num_sections_queued()
|
||||||
|
{
|
||||||
|
return m_queued_sections.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void* get_interface()
|
||||||
|
{
|
||||||
|
return dynamic_cast<Interface*>(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void GenerateThread::run(interface::Thread *thread)
|
||||||
|
{
|
||||||
|
for(;;){
|
||||||
|
// Give some time for accumulating the section queue
|
||||||
|
interface::os::sleep_us(5000);
|
||||||
|
m_module->m_queued_sections_sem.wait();
|
||||||
|
if(thread->stop_requested())
|
||||||
|
break;
|
||||||
|
// We can avoid implementing our own mutex locking in Module by using
|
||||||
|
// interface::Server::access_module() instead of directly accessing it.
|
||||||
|
worldgen::access(m_module->m_server,
|
||||||
|
[&](worldgen::Interface *iworldgen)
|
||||||
|
{
|
||||||
|
m_module->generate_next_section();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
BUILDAT_EXPORT void* createModule_worldgen(interface::Server *server){
|
BUILDAT_EXPORT void* createModule_worldgen(interface::Server *server){
|
||||||
return (void*)(new Module(server));
|
return (void*)(new Module(server));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user