Notify plugins about game being loaded or unloaded.

As a test, make seadwatch deactivate on these events.
develop
Alexander Gavrilov 2011-12-30 18:12:15 +04:00
parent 298e2fe92d
commit 53346328e8
5 changed files with 77 additions and 1 deletions

@ -51,6 +51,9 @@ using namespace DFHack;
#include "dfhack/SDL_fakes/events.h"
#include "dfhack/df/world.h"
#include "dfhack/df/world_data.h"
#include <stdio.h>
#include <iomanip>
#include <stdlib.h>
@ -439,6 +442,7 @@ Core::Core()
HotkeyMutex = 0;
HotkeyCond = 0;
misc_data_mutex=0;
last_world_data_ptr = NULL;
};
void Core::fatal (std::string output, bool deactivate)
@ -631,8 +635,23 @@ int Core::Update()
if(errorstate)
return -1;
// detect if the game was loaded or unloaded in the meantime
void *new_wdata = NULL;
if (df::global::world) {
df::world_data *wdata = df::global::world->world_data;
// when the game is unloaded, world_data isn't deleted, but its contents are
if (wdata && !wdata->sites.empty())
new_wdata = wdata;
}
if (new_wdata != last_world_data_ptr) {
last_world_data_ptr = new_wdata;
plug_mgr->OnStateChange(new_wdata ? SC_GAME_LOADED : SC_GAME_UNLOADED);
}
// notify all the plugins that a game tick is finished
plug_mgr->OnUpdate();
// wake waiting tools
// do not allow more tools to join in while we process stuff here
StackMutex->lock();

@ -135,6 +135,7 @@ Plugin::Plugin(Core * core, const std::string & filepath, const std::string & _f
plugin_shutdown = 0;
plugin_status = 0;
plugin_onupdate = 0;
plugin_onstatechange = 0;
state = PS_UNLOADED;
access = new RefLock();
}
@ -192,6 +193,7 @@ bool Plugin::load()
plugin_status = (command_result (*)(Core *, std::string &)) LookupPlugin(plug, "plugin_status");
plugin_onupdate = (command_result (*)(Core *)) LookupPlugin(plug, "plugin_onupdate");
plugin_shutdown = (command_result (*)(Core *)) LookupPlugin(plug, "plugin_shutdown");
plugin_onstatechange = (command_result (*)(Core *, state_change_event)) LookupPlugin(plug, "plugin_onstatechange");
//name = _PlugName();
plugin_lib = plug;
if(plugin_init(&c,commands) == CR_OK)
@ -299,6 +301,19 @@ command_result Plugin::on_update()
return cr;
}
command_result Plugin::on_state_change(state_change_event event)
{
Core & c = Core::getInstance();
command_result cr = CR_NOT_IMPLEMENTED;
access->lock_add();
if(state == PS_LOADED && plugin_onstatechange)
{
cr = plugin_onstatechange(&c, event);
}
access->lock_sub();
return cr;
}
Plugin::plugin_state Plugin::getState() const
{
return state;
@ -370,6 +385,15 @@ void PluginManager::OnUpdate( void )
all_plugins[i]->on_update();
}
}
void PluginManager::OnStateChange( state_change_event event )
{
for(int i = 0; i < all_plugins.size(); i++)
{
all_plugins[i]->on_state_change(event);
}
}
// FIXME: doesn't check name collisions!
void PluginManager::registerCommands( Plugin * p )
{

@ -134,6 +134,8 @@ namespace DFHack
/// returns a named pointer.
void *GetData(std::string key);
bool isWorldLoaded() { return (last_world_data_ptr != NULL); }
DFHack::Process * p;
DFHack::VersionInfo * vinfo;
DFHack::Console con;
@ -184,6 +186,7 @@ namespace DFHack
bool hotkey_set;
tthread::mutex * HotkeyMutex;
tthread::condition_variable * HotkeyCond;
void *last_world_data_ptr; // for state change tracking
// Very important!
bool started;

@ -46,6 +46,11 @@ namespace DFHack
CR_FAILURE = 0,
CR_OK = 1
};
enum state_change_event
{
SC_GAME_LOADED,
SC_GAME_UNLOADED
};
struct PluginCommand
{
/// create a command with a name, description, function pointer to its code
@ -87,6 +92,7 @@ namespace DFHack
Plugin(DFHack::Core* core, const std::string& filepath, const std::string& filename, PluginManager * pm);
~Plugin();
command_result on_update();
command_result on_state_change(state_change_event event);
public:
bool load();
bool unload();
@ -117,6 +123,7 @@ namespace DFHack
command_result (*plugin_status)(Core *, std::string &);
command_result (*plugin_shutdown)(Core *);
command_result (*plugin_onupdate)(Core *);
command_result (*plugin_onstatechange)(Core *, state_change_event);
};
class DFHACK_EXPORT PluginManager
{
@ -126,6 +133,7 @@ namespace DFHack
PluginManager(Core * core);
~PluginManager();
void OnUpdate( void );
void OnStateChange( state_change_event event );
void registerCommands( Plugin * p );
void unregisterCommands( Plugin * p );
// PUBLIC METHODS

@ -288,10 +288,32 @@ DFhackCExport DFHack::command_result plugin_init(DFHack::Core* pCore, std::vecto
return DFHack::CR_OK;
}
DFhackCExport DFHack::command_result plugin_onstatechange(DFHack::Core* pCore, DFHack::state_change_event event)
{
switch (event) {
case DFHack::SC_GAME_LOADED:
case DFHack::SC_GAME_UNLOADED:
if (running)
pCore->con.printerr("seedwatch deactivated due to game load/unload\n");
running = false;
break;
default:
break;
}
return DFHack::CR_OK;
}
DFhackCExport DFHack::command_result plugin_onupdate(DFHack::Core* pCore)
{
if(running)
if (running)
{
// reduce processing rate
static int counter = 0;
if (++counter < 500)
return DFHack::CR_OK;
counter = 0;
DFHack::Core& core = *pCore;
DFHack::World *w = core.getWorld();
DFHack::t_gamemodes gm;