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 and automatically stored in the save game, these save and retrieval
functions can just copy values in memory without doing any actual I/O. 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> 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>
<div class="section" id="material-info-lookup"> <div class="section" id="material-info-lookup">
<h3><a class="toc-backref" href="#id17">Material info lookup</a></h3> <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 take into account anything that depends on the actual units, like
burrows, or the presence of invaders.</p> burrows, or the presence of invaders.</p>
</li> </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> </ul>
</div> </div>
<div class="section" id="burrows-module"> <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. functions can just copy values in memory without doing any actual I/O.
However, currently every entry has a 180+-byte dead-weight overhead. 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 Material info lookup
-------------------- --------------------
@ -1079,6 +1097,22 @@ Maps module
take into account anything that depends on the actual units, like take into account anything that depends on the actual units, like
burrows, or the presence of invaders. 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 Burrows module
-------------- --------------

@ -30,6 +30,7 @@ distribution.
#include "MemAccess.h" #include "MemAccess.h"
#include "Core.h" #include "Core.h"
#include "Error.h"
#include "VersionInfo.h" #include "VersionInfo.h"
#include "tinythread.h" #include "tinythread.h"
// must be last due to MS stupidity // must be last due to MS stupidity
@ -311,12 +312,12 @@ static PersistentDataItem get_persistent(lua_State *state)
if (lua_istable(state, 1)) if (lua_istable(state, 1))
{ {
Lua::StackUnwinder frame(state);
if (!lua_getmetatable(state, 1) || if (!lua_getmetatable(state, 1) ||
!lua_rawequal(state, -1, lua_upvalueindex(1))) !lua_rawequal(state, -1, lua_upvalueindex(1)))
luaL_argerror(state, 1, "invalid table type"); luaL_argerror(state, 1, "invalid table type");
lua_settop(state, 1);
return persistent_by_struct(state, 1); return persistent_by_struct(state, 1);
} }
else else
@ -446,11 +447,38 @@ static int dfhack_persistent_save(lua_State *state)
return 2; 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[] = { static const luaL_Reg dfhack_persistent_funcs[] = {
{ "get", dfhack_persistent_get }, { "get", dfhack_persistent_get },
{ "delete", dfhack_persistent_delete }, { "delete", dfhack_persistent_delete },
{ "get_all", dfhack_persistent_get_all }, { "get_all", dfhack_persistent_get_all },
{ "save", dfhack_persistent_save }, { "save", dfhack_persistent_save },
{ "getTilemask", dfhack_persistent_getTilemask },
{ "deleteTilemask", dfhack_persistent_deleteTilemask },
{ NULL, NULL } { NULL, NULL }
}; };
@ -937,6 +965,22 @@ static const luaL_Reg dfhack_items_funcs[] = {
/***** Maps module *****/ /***** 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[] = { static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
WRAPN(getBlock, (df::map_block* (*)(int32_t,int32_t,int32_t))Maps::getBlock), WRAPN(getBlock, (df::map_block* (*)(int32_t,int32_t,int32_t))Maps::getBlock),
WRAPM(Maps, enableBlockUpdates), WRAPM(Maps, enableBlockUpdates),
@ -944,6 +988,10 @@ static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
WRAPM(Maps, getLocalInitFeature), WRAPM(Maps, getLocalInitFeature),
WRAPM(Maps, canWalkBetween), WRAPM(Maps, canWalkBetween),
WRAPM(Maps, spawnFlow), WRAPM(Maps, spawnFlow),
WRAPN(hasTileAssignment, hasTileAssignment),
WRAPN(getTileAssignment, getTileAssignment),
WRAPN(setTileAssignment, setTileAssignment),
WRAPN(resetTileAssignment, resetTileAssignment),
{ NULL, NULL } { NULL, NULL }
}; };

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

@ -37,6 +37,12 @@ distribution.
#include "DataDefs.h" #include "DataDefs.h"
namespace df
{
struct tile_bitmask;
struct map_block;
}
namespace DFHack namespace DFHack
{ {
typedef df::game_mode GameMode; typedef df::game_mode GameMode;
@ -120,6 +126,9 @@ namespace DFHack
DFHACK_EXPORT bool DeletePersistentData(const PersistentDataItem &item); DFHACK_EXPORT bool DeletePersistentData(const PersistentDataItem &item);
DFHACK_EXPORT void ClearPersistentCache(); 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 #endif

@ -38,13 +38,18 @@ using namespace std;
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"
#include "modules/Maps.h"
#include "MiscUtils.h" #include "MiscUtils.h"
#include "DataDefs.h" #include "DataDefs.h"
#include "df/world.h" #include "df/world.h"
#include "df/historical_figure.h" #include "df/historical_figure.h"
#include "df/map_block.h"
#include "df/block_square_event_world_constructionst.h"
using namespace DFHack; using namespace DFHack;
using namespace df::enums;
using df::global::world; using df::global::world;
@ -312,3 +317,63 @@ bool World::DeletePersistentData(const PersistentDataItem &item)
return false; 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