Experimental API for associating tile bitmasks with persistent data.

Use block_square_event_world_constructionst objects with the same
bogus negative id as the matching historical figure object.
develop
Alexander Gavrilov 2012-10-11 17:34:34 +04:00
parent 5206236b01
commit 2865e1373a
7 changed files with 189 additions and 6 deletions

@ -932,6 +932,21 @@ Returns <em>entry, did_create_new</em></p>
and automatically stored in the save game, these save and retrieval
functions can just copy values in memory without doing any actual I/O.
However, currently every entry has a 180+-byte dead-weight overhead.</p>
<p>It is also possible to associate one bit per map tile with an entry,
using these two methods:</p>
<ul>
<li><p class="first"><tt class="docutils literal">entry:getTilemask(block[, create])</tt></p>
<p>Retrieves the tile bitmask associated with this entry in the given map
block. If <tt class="docutils literal">create</tt> is <em>true</em>, an empty mask is created if none exists;
otherwise the function returns <em>nil</em>, which must be assumed to be the same
as an all-zero mask.</p>
</li>
<li><p class="first"><tt class="docutils literal">entry:deleteTilemask(block)</tt></p>
<p>Deletes the associated tile mask from the given map block.</p>
</li>
</ul>
<p>Note that these masks are only saved in fortress mode, and also that deleting
the persistent entry will <strong>NOT</strong> delete the associated masks.</p>
</div>
<div class="section" id="material-info-lookup">
<h3><a class="toc-backref" href="#id17">Material info lookup</a></h3>
@ -1286,6 +1301,18 @@ tools like liquids or tiletypes are used. It also cannot possibly
take into account anything that depends on the actual units, like
burrows, or the presence of invaders.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.maps.hasTileAssignment(tilemask)</tt></p>
<p>Checks if the tile_bitmask object is not <em>nil</em> and contains any set bits; returns <em>true</em> or <em>false</em>.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.maps.getTileAssignment(tilemask,x,y)</tt></p>
<p>Checks if the tile_bitmask object is not <em>nil</em> and has the relevant bit set; returns <em>true</em> or <em>false</em>.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.maps.setTileAssignment(tilemask,x,y,enable)</tt></p>
<p>Sets the relevant bit in the tile_bitmask object to the <em>enable</em> argument.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.maps.resetTileAssignment(tilemask[,enable])</span></tt></p>
<p>Sets all bits in the mask to the <em>enable</em> argument.</p>
</li>
</ul>
</div>
<div class="section" id="burrows-module">

@ -646,6 +646,24 @@ and automatically stored in the save game, these save and retrieval
functions can just copy values in memory without doing any actual I/O.
However, currently every entry has a 180+-byte dead-weight overhead.
It is also possible to associate one bit per map tile with an entry,
using these two methods:
* ``entry:getTilemask(block[, create])``
Retrieves the tile bitmask associated with this entry in the given map
block. If ``create`` is *true*, an empty mask is created if none exists;
otherwise the function returns *nil*, which must be assumed to be the same
as an all-zero mask.
* ``entry:deleteTilemask(block)``
Deletes the associated tile mask from the given map block.
Note that these masks are only saved in fortress mode, and also that deleting
the persistent entry will **NOT** delete the associated masks.
Material info lookup
--------------------
@ -1079,6 +1097,22 @@ Maps module
take into account anything that depends on the actual units, like
burrows, or the presence of invaders.
* ``dfhack.maps.hasTileAssignment(tilemask)``
Checks if the tile_bitmask object is not *nil* and contains any set bits; returns *true* or *false*.
* ``dfhack.maps.getTileAssignment(tilemask,x,y)``
Checks if the tile_bitmask object is not *nil* and has the relevant bit set; returns *true* or *false*.
* ``dfhack.maps.setTileAssignment(tilemask,x,y,enable)``
Sets the relevant bit in the tile_bitmask object to the *enable* argument.
* ``dfhack.maps.resetTileAssignment(tilemask[,enable])``
Sets all bits in the mask to the *enable* argument.
Burrows module
--------------

@ -30,6 +30,7 @@ distribution.
#include "MemAccess.h"
#include "Core.h"
#include "Error.h"
#include "VersionInfo.h"
#include "tinythread.h"
// must be last due to MS stupidity
@ -311,12 +312,12 @@ static PersistentDataItem get_persistent(lua_State *state)
if (lua_istable(state, 1))
{
Lua::StackUnwinder frame(state);
if (!lua_getmetatable(state, 1) ||
!lua_rawequal(state, -1, lua_upvalueindex(1)))
luaL_argerror(state, 1, "invalid table type");
lua_settop(state, 1);
return persistent_by_struct(state, 1);
}
else
@ -446,11 +447,38 @@ static int dfhack_persistent_save(lua_State *state)
return 2;
}
static int dfhack_persistent_getTilemask(lua_State *state)
{
CoreSuspender suspend;
lua_settop(state, 3);
auto ref = get_persistent(state);
auto block = Lua::CheckDFObject<df::map_block>(state, 2);
bool create = lua_toboolean(state, 3);
Lua::PushDFObject(state, World::getPersistentTilemask(ref, block, create));
return 1;
}
static int dfhack_persistent_deleteTilemask(lua_State *state)
{
CoreSuspender suspend;
lua_settop(state, 2);
auto ref = get_persistent(state);
auto block = Lua::CheckDFObject<df::map_block>(state, 2);
lua_pushboolean(state, World::deletePersistentTilemask(ref, block));
return 1;
}
static const luaL_Reg dfhack_persistent_funcs[] = {
{ "get", dfhack_persistent_get },
{ "delete", dfhack_persistent_delete },
{ "get_all", dfhack_persistent_get_all },
{ "save", dfhack_persistent_save },
{ "getTilemask", dfhack_persistent_getTilemask },
{ "deleteTilemask", dfhack_persistent_deleteTilemask },
{ NULL, NULL }
};
@ -937,6 +965,22 @@ static const luaL_Reg dfhack_items_funcs[] = {
/***** Maps module *****/
static bool hasTileAssignment(df::tile_bitmask *bm) {
return bm && bm->has_assignments();
}
static bool getTileAssignment(df::tile_bitmask *bm, int x, int y) {
return bm && bm->getassignment(x,y);
}
static void setTileAssignment(df::tile_bitmask *bm, int x, int y, bool val) {
CHECK_NULL_POINTER(bm);
bm->setassignment(x,y,val);
}
static void resetTileAssignment(df::tile_bitmask *bm, bool val) {
CHECK_NULL_POINTER(bm);
if (val) bm->set_all();
else bm->clear();
}
static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
WRAPN(getBlock, (df::map_block* (*)(int32_t,int32_t,int32_t))Maps::getBlock),
WRAPM(Maps, enableBlockUpdates),
@ -944,6 +988,10 @@ static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
WRAPM(Maps, getLocalInitFeature),
WRAPM(Maps, canWalkBetween),
WRAPM(Maps, spawnFlow),
WRAPN(hasTileAssignment, hasTileAssignment),
WRAPN(getTileAssignment, getTileAssignment),
WRAPN(setTileAssignment, setTileAssignment),
WRAPN(resetTileAssignment, resetTileAssignment),
{ NULL, NULL }
};

@ -16,7 +16,7 @@ inline bool getassignment( const df::coord2d &xy )
}
inline bool getassignment( int x, int y )
{
return (bits[y] & (1 << x));
return (bits[(y&15)] & (1 << (x&15)));
}
inline void setassignment( const df::coord2d &xy, bool bit )
{
@ -25,9 +25,9 @@ inline void setassignment( const df::coord2d &xy, bool bit )
inline void setassignment( int x, int y, bool bit )
{
if(bit)
bits[y] |= (1 << x);
bits[(y&15)] |= (1 << (x&15));
else
bits[y] &= ~(1 << x);
bits[(y&15)] &= ~(1 << (x&15));
}
bool has_assignments()
{

@ -37,6 +37,12 @@ distribution.
#include "DataDefs.h"
namespace df
{
struct tile_bitmask;
struct map_block;
}
namespace DFHack
{
typedef df::game_mode GameMode;
@ -120,6 +126,9 @@ namespace DFHack
DFHACK_EXPORT bool DeletePersistentData(const PersistentDataItem &item);
DFHACK_EXPORT void ClearPersistentCache();
DFHACK_EXPORT df::tile_bitmask *getPersistentTilemask(const PersistentDataItem &item, df::map_block *block, bool create = false);
DFHACK_EXPORT bool deletePersistentTilemask(const PersistentDataItem &item, df::map_block *block);
}
}
#endif

@ -38,13 +38,18 @@ using namespace std;
#include "ModuleFactory.h"
#include "Core.h"
#include "modules/Maps.h"
#include "MiscUtils.h"
#include "DataDefs.h"
#include "df/world.h"
#include "df/historical_figure.h"
#include "df/map_block.h"
#include "df/block_square_event_world_constructionst.h"
using namespace DFHack;
using namespace df::enums;
using df::global::world;
@ -312,3 +317,63 @@ bool World::DeletePersistentData(const PersistentDataItem &item)
return false;
}
df::tile_bitmask *World::getPersistentTilemask(const PersistentDataItem &item, df::map_block *block, bool create)
{
if (!block)
return NULL;
int id = item.raw_id();
if (id > -100)
return NULL;
for (size_t i = 0; i < block->block_events.size(); i++)
{
auto ev = block->block_events[i];
if (ev->getType() != block_square_event_type::world_construction)
continue;
auto wcsev = strict_virtual_cast<df::block_square_event_world_constructionst>(ev);
if (!wcsev || wcsev->construction_id != id)
continue;
return &wcsev->tile_bitmask;
}
if (!create)
return NULL;
auto ev = df::allocate<df::block_square_event_world_constructionst>();
if (!ev)
return NULL;
ev->construction_id = id;
ev->tile_bitmask.clear();
vector_insert_at(block->block_events, 0, (df::block_square_event*)ev);
return &ev->tile_bitmask;
}
bool World::deletePersistentTilemask(const PersistentDataItem &item, df::map_block *block)
{
if (!block)
return false;
int id = item.raw_id();
if (id > -100)
return false;
bool found = false;
for (int i = block->block_events.size()-1; i >= 0; i--)
{
auto ev = block->block_events[i];
if (ev->getType() != block_square_event_type::world_construction)
continue;
auto wcsev = strict_virtual_cast<df::block_square_event_world_constructionst>(ev);
if (!wcsev || wcsev->construction_id != id)
continue;
delete wcsev;
vector_erase_at(block->block_events, i);
found = true;
}
return found;
}

@ -1 +1 @@
Subproject commit 20c6d9c743f1c5a20bb288f427b101e9b2a138d7
Subproject commit aec106cdc32083bbcc6d6dd27d9e069f5525ea92