From 0c2b78b96b0aca46988f9d1e3c94f70cdfbc8e02 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Wed, 11 Apr 2012 19:42:05 +0400 Subject: [PATCH] Add api for manipulating burrows to the core. --- LUA_API.rst | 33 +++++++ Lua API.html | 24 +++++ library/LuaApi.cpp | 61 ++++++++++-- library/include/DataFuncs.h | 8 ++ library/include/MiscUtils.h | 16 +++ .../df/custom/block_burrow.methods.inc | 19 ++++ .../block_square_event_mineralst.methods.inc | 2 +- library/include/modules/Maps.h | 31 +++++- library/include/modules/Units.h | 5 + library/lua/dfhack.lua | 6 ++ library/modules/Maps.cpp | 98 +++++++++++++++++++ library/modules/Units.cpp | 39 ++++++++ library/xml | 2 +- 13 files changed, 331 insertions(+), 13 deletions(-) create mode 100644 library/include/df/custom/block_burrow.methods.inc diff --git a/LUA_API.rst b/LUA_API.rst index 4d7e0df76..8698e1b23 100644 --- a/LUA_API.rst +++ b/LUA_API.rst @@ -687,6 +687,15 @@ Units module The unit is capable of rational action, i.e. not dead, insane or zombie. +* ``dfhack.units.isInBurrow(unit,burrow)`` + + Checks if the unit is in the burrow. + +* ``dfhack.units.setInBurrow(unit,burrow,enable)`` + + Adds or removes the unit from the burrow. + + Maps module ----------- @@ -717,3 +726,27 @@ Maps module * ``dfhack.maps.getLocalInitFeature(region_coord2d,index)`` Returns the local feature object with the given region coords and index. + +* ``dfhack.maps.findBurrowByName(name)`` + + Returns the burrow pointer or *nil*. + +* ``dfhack.maps.listBurrowBlocks(burrow)`` + + Returns a table of map block pointers. + +* ``dfhack.maps.isBurrowTile(burrow,tile_coord)`` + + Checks if the tile is in burrow. + +* ``dfhack.maps.setBurrowTile(burrow,tile_coord,enable)`` + + Adds or removes the tile from the burrow. Returns *false* if invalid coords. + +* ``dfhack.maps.isBlockBurrowTile(burrow,block,x,y)`` + + Checks if the tile within the block is in burrow. + +* ``dfhack.maps.setBlockBurrowTile(burrow,block,x,y,enable)`` + + Adds or removes the tile from the burrow. Returns *false* if invalid coords. diff --git a/Lua API.html b/Lua API.html index 0f5f18deb..0ca88966c 100644 --- a/Lua API.html +++ b/Lua API.html @@ -917,6 +917,12 @@ a lua list containing them.

  • dfhack.units.isSane(unit)

    The unit is capable of rational action, i.e. not dead, insane or zombie.

  • +
  • dfhack.units.isInBurrow(unit,burrow)

    +

    Checks if the unit is in the burrow.

    +
  • +
  • dfhack.units.setInBurrow(unit,burrow,enable)

    +

    Adds or removes the unit from the burrow.

    +
  • @@ -943,6 +949,24 @@ a lua list containing them.

  • dfhack.maps.getLocalInitFeature(region_coord2d,index)

    Returns the local feature object with the given region coords and index.

  • +
  • dfhack.maps.findBurrowByName(name)

    +

    Returns the burrow pointer or nil.

    +
  • +
  • dfhack.maps.listBurrowBlocks(burrow)

    +

    Returns a table of map block pointers.

    +
  • +
  • dfhack.maps.isBurrowTile(burrow,tile_coord)

    +

    Checks if the tile is in burrow.

    +
  • +
  • dfhack.maps.setBurrowTile(burrow,tile_coord,enable)

    +

    Adds or removes the tile from the burrow. Returns false if invalid coords.

    +
  • +
  • dfhack.maps.isBlockBurrowTile(burrow,block,x,y)

    +

    Checks if the tile within the block is in burrow.

    +
  • +
  • dfhack.maps.setBlockBurrowTile(burrow,block,x,y,enable)

    +

    Adds or removes the tile from the burrow. Returns false if invalid coords.

    +
  • diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index ba989ecf2..fb818c206 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -63,6 +63,7 @@ distribution. #include "df/inorganic_raw.h" #include "df/dfhack_material_category.h" #include "df/job_material_category.h" +#include "df/burrow.h" #include #include @@ -71,6 +72,18 @@ distribution. using namespace DFHack; using namespace DFHack::LuaWrapper; +template +void push_pointer_vector(lua_State *state, const std::vector &pvec) +{ + lua_createtable(state,pvec.size(),0); + + for (size_t i = 0; i < pvec.size(); i++) + { + Lua::PushDFObject(state, pvec[i]); + lua_rawseti(state, -2, i+1); + } +} + /************************************************** * Per-world persistent configuration storage API * **************************************************/ @@ -571,14 +584,7 @@ static int job_listNewlyCreated(lua_State *state) if (Job::listNewlyCreated(&pvec, &nxid)) { lua_pushinteger(state, nxid); - lua_newtable(state); - - for (size_t i = 0; i < pvec.size(); i++) - { - Lua::PushDFObject(state, pvec[i]); - lua_rawseti(state, -2, i+1); - } - + push_pointer_vector(state, pvec); return 2; } else @@ -598,18 +604,55 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = { WRAPM(Units, isDead), WRAPM(Units, isAlive), WRAPM(Units, isSane), + WRAPM(Units, isInBurrow), + WRAPM(Units, setInBurrow), { NULL, NULL } }; +static bool maps_isBlockBurrowTile(df::burrow *burrow, df::map_block *block, int x, int y) +{ + return Maps::isBlockBurrowTile(burrow, block, df::coord2d(x,y)); +} + +static bool maps_setBlockBurrowTile(df::burrow *burrow, df::map_block *block, int x, int y, bool enable) +{ + return Maps::setBlockBurrowTile(burrow, block, df::coord2d(x,y), enable); +} + static const LuaWrapper::FunctionReg dfhack_maps_module[] = { WRAPN(getBlock, (df::map_block* (*)(int32_t,int32_t,int32_t))Maps::getBlock), WRAPN(getTileBlock, (df::map_block* (*)(df::coord))Maps::getTileBlock), WRAPM(Maps, getRegionBiome), WRAPM(Maps, getGlobalInitFeature), WRAPM(Maps, getLocalInitFeature), + WRAPM(Maps, findBurrowByName), + WRAPN(isBlockBurrowTile, maps_isBlockBurrowTile), + WRAPN(setBlockBurrowTile, maps_setBlockBurrowTile), + WRAPM(Maps, isBurrowTile), + WRAPM(Maps, setBurrowTile), + { NULL, NULL } +}; + +static int maps_listBurrowBlocks(lua_State *state) +{ + luaL_checkany(state, 1); + + auto ptr = Lua::GetDFObject(state, 1); + if (!ptr) + luaL_argerror(state, 1, "invalid burrow type"); + + std::vector pvec; + Maps::listBurrowBlocks(&pvec, ptr); + push_pointer_vector(state, pvec); + return 1; +} + +static const luaL_Reg dfhack_maps_funcs[] = { + { "listBurrowBlocks", maps_listBurrowBlocks }, { NULL, NULL } }; + /************************ * Main Open function * ************************/ @@ -623,5 +666,5 @@ void OpenDFHackApi(lua_State *state) OpenModule(state, "gui", dfhack_gui_module); OpenModule(state, "job", dfhack_job_module, dfhack_job_funcs); OpenModule(state, "units", dfhack_units_module); - OpenModule(state, "maps", dfhack_maps_module); + OpenModule(state, "maps", dfhack_maps_module, dfhack_maps_funcs); } diff --git a/library/include/DataFuncs.h b/library/include/DataFuncs.h index 6cd7d42f4..d78fe9e27 100644 --- a/library/include/DataFuncs.h +++ b/library/include/DataFuncs.h @@ -139,6 +139,14 @@ INSTANTIATE_WRAPPERS(3, (OSTREAM_ARG,A1,A2,A3), (out,vA1,vA2,vA3), INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4)) INSTANTIATE_WRAPPERS(4, (A1,A2,A3,A4), (vA1,vA2,vA3,vA4), LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);) +INSTANTIATE_WRAPPERS(4, (OSTREAM_ARG,A1,A2,A3,A4), (out,vA1,vA2,vA3,vA4), + LOAD_OSTREAM(out); LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);) +#undef FW_TARGS + +#define FW_TARGS class A1, class A2, class A3, class A4, class A5 +INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4,A5)) +INSTANTIATE_WRAPPERS(5, (A1,A2,A3,A4,A5), (vA1,vA2,vA3,vA4,vA5), + LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4); LOAD_ARG(A5);) #undef FW_TARGS #undef FW_TARGSC diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index c2a153eb1..0cf34c489 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -207,6 +207,22 @@ unsigned insert_into_vector(std::vector &vec, FT CT::*field, CT *obj, bool return pos; } +template +bool erase_from_vector(std::vector &vec, FT key) +{ + int pos = binsearch_index(vec, key); + vector_erase_at(vec, pos); + return pos >= 0; +} + +template +bool erase_from_vector(std::vector &vec, FT CT::*field, FT key) +{ + int pos = binsearch_index(vec, field, key); + vector_erase_at(vec, pos); + return pos >= 0; +} + template CT *binsearch_in_vector(const std::vector &vec, KT value) { diff --git a/library/include/df/custom/block_burrow.methods.inc b/library/include/df/custom/block_burrow.methods.inc new file mode 100644 index 000000000..7754ab0db --- /dev/null +++ b/library/include/df/custom/block_burrow.methods.inc @@ -0,0 +1,19 @@ +inline bool getassignment( const df::coord2d &xy ) +{ + return getassignment(xy.x,xy.y); +} +inline bool getassignment( int x, int y ) +{ + return (tile_bitmask[y] & (1 << x)); +} +inline void setassignment( const df::coord2d &xy, bool bit ) +{ + return setassignment(xy.x,xy.y, bit); +} +inline void setassignment( int x, int y, bool bit ) +{ + if(bit) + tile_bitmask[y] |= (1 << x); + else + tile_bitmask[y] &= ~(1 << x); +} \ No newline at end of file diff --git a/library/include/df/custom/block_square_event_mineralst.methods.inc b/library/include/df/custom/block_square_event_mineralst.methods.inc index e01d22f72..7754ab0db 100644 --- a/library/include/df/custom/block_square_event_mineralst.methods.inc +++ b/library/include/df/custom/block_square_event_mineralst.methods.inc @@ -15,5 +15,5 @@ inline void setassignment( int x, int y, bool bit ) if(bit) tile_bitmask[y] |= (1 << x); else - tile_bitmask[y] &= 0xFFFF ^ (1 << x); + tile_bitmask[y] &= ~(1 << x); } \ No newline at end of file diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h index 91b8ae7c2..0de262264 100644 --- a/library/include/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -38,7 +38,7 @@ distribution. #include "modules/Materials.h" #include "df/world.h" -#include "df/feature_init.h" +#include "df/world_data.h" #include "df/map_block.h" #include "df/block_square_event.h" #include "df/block_square_event_mineralst.h" @@ -49,13 +49,20 @@ distribution. #include "df/tile_liquid.h" #include "df/tile_dig_designation.h" #include "df/tile_traffic.h" -#include "df/world_data.h" +#include "df/feature_init.h" /** * \defgroup grp_maps Maps module and its types * @ingroup grp_modules */ +namespace df +{ + struct burrow; + struct world_data; + struct block_burrow; +} + namespace DFHack { /*************************************************************************** @@ -249,6 +256,26 @@ extern DFHACK_EXPORT bool SortBlockEvents(df::map_block *block, /// remove a block event from the block by address extern DFHACK_EXPORT bool RemoveBlockEvent(uint32_t x, uint32_t y, uint32_t z, df::block_square_event * which ); +/* + * BURROWS + */ + +DFHACK_EXPORT df::burrow *findBurrowByName(std::string name); + +void listBurrowBlocks(std::vector *pvec, df::burrow *burrow); + +df::block_burrow *getBlockBurrowMask(df::burrow *burrow, df::map_block *block, bool create = false); + +bool isBlockBurrowTile(df::burrow *burrow, df::map_block *block, df::coord2d tile); +bool setBlockBurrowTile(df::burrow *burrow, df::map_block *block, df::coord2d tile, bool enable); + +inline bool isBurrowTile(df::burrow *burrow, df::coord tile) { + return isBlockBurrowTile(burrow, getTileBlock(tile), tile); +} +inline bool setBurrowTile(df::burrow *burrow, df::coord tile, bool enable) { + return setBlockBurrowTile(burrow, getTileBlock(tile), tile, enable); +} + } } #endif diff --git a/library/include/modules/Units.h b/library/include/modules/Units.h index 838d1d596..35701b6ec 100644 --- a/library/include/modules/Units.h +++ b/library/include/modules/Units.h @@ -36,6 +36,7 @@ distribution. namespace df { struct nemesis_record; + struct burrow; } /** @@ -206,6 +207,10 @@ DFHACK_EXPORT df::nemesis_record *getNemesis(df::unit *unit); DFHACK_EXPORT bool isDead(df::unit *unit); DFHACK_EXPORT bool isAlive(df::unit *unit); DFHACK_EXPORT bool isSane(df::unit *unit); + +DFHACK_EXPORT bool isInBurrow(df::unit *unit, df::burrow *burrow); +DFHACK_EXPORT void setInBurrow(df::unit *unit, df::burrow *burrow, bool enable); + } } #endif diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua index 25d8c2ba8..a6606d152 100644 --- a/library/lua/dfhack.lua +++ b/library/lua/dfhack.lua @@ -80,6 +80,12 @@ function printall(table) end end +function copyall(table) + local rv = {} + for k,v in pairs(table) do rv[k] = v end + return rv +end + function dfhack.persistent:__tostring() return "" diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 4d653b4fa..c0aa9b634 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -47,6 +47,10 @@ using namespace std; #include "df/world_geo_biome.h" #include "df/world_geo_layer.h" #include "df/feature_init.h" +#include "df/world_data.h" +#include "df/burrow.h" +#include "df/block_burrow.h" +#include "df/block_burrow_link.h" using namespace DFHack; using namespace df::enums; @@ -681,3 +685,97 @@ MapExtras::Block *MapExtras::MapCache::BlockAt(DFCoord blockcoord) } } +df::burrow *Maps::findBurrowByName(std::string name) +{ + auto &vec = df::burrow::get_vector(); + + for (size_t i = 0; i < vec.size(); i++) + if (vec[i]->name == name) + return vec[i]; + + return NULL; +} + +void Maps::listBurrowBlocks(std::vector *pvec, df::burrow *burrow) +{ + CHECK_NULL_POINTER(burrow); + + pvec->clear(); + pvec->reserve(burrow->block_x.size()); + + df::coord base(world->map.region_x*3,world->map.region_y*3,world->map.region_z); + + for (size_t i = 0; i < burrow->block_x.size(); i++) + { + df::coord pos(burrow->block_x[i], burrow->block_y[i], burrow->block_z[i]); + + auto block = getBlock(pos - base); + if (block) + pvec->push_back(block); + } +} + +df::block_burrow *Maps::getBlockBurrowMask(df::burrow *burrow, df::map_block *block, bool create) +{ + CHECK_NULL_POINTER(burrow); + CHECK_NULL_POINTER(block); + + int32_t id = burrow->id; + df::block_burrow_link *prev = &block->block_burrows; + df::block_burrow_link *link = prev->next; + + for (; link; prev = link, link = link->next) + if (link->item->id == id) + return link->item; + + if (create) + { + link = new df::block_burrow_link; + link->item = new df::block_burrow; + + link->item->id = burrow->id; + memset(link->item->tile_bitmask,0,sizeof(link->item->tile_bitmask)); + link->item->link = link; + + link->next = NULL; + link->prev = prev; + prev->next = link; + + df::coord base(world->map.region_x*3,world->map.region_y*3,world->map.region_z); + df::coord pos = base + block->map_pos/16; + + burrow->block_x.push_back(pos.x); + burrow->block_y.push_back(pos.y); + burrow->block_z.push_back(pos.z); + + return link->item; + } + + return NULL; +} + +bool Maps::isBlockBurrowTile(df::burrow *burrow, df::map_block *block, df::coord2d tile) +{ + CHECK_NULL_POINTER(burrow); + + if (!block) return false; + + auto mask = getBlockBurrowMask(burrow, block); + + return mask ? mask->getassignment(tile & 15) : false; +} + +bool Maps::setBlockBurrowTile(df::burrow *burrow, df::map_block *block, df::coord2d tile, bool enable) +{ + CHECK_NULL_POINTER(burrow); + + if (!block) return false; + + auto mask = getBlockBurrowMask(burrow, block, enable); + + if (mask) + mask->setassignment(tile & 15, enable); + + return true; +} + diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index e210a9028..47208dcbc 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -44,6 +44,7 @@ using namespace std; #include "modules/Translation.h" #include "ModuleFactory.h" #include "Core.h" +#include "MiscUtils.h" #include "df/world.h" #include "df/ui.h" @@ -54,6 +55,7 @@ using namespace std; #include "df/historical_figure.h" #include "df/historical_figure_info.h" #include "df/assumed_identity.h" +#include "df/burrow.h" using namespace DFHack; using namespace df::enums; @@ -652,3 +654,40 @@ bool DFHack::Units::isSane(df::unit *unit) return true; } + +bool DFHack::Units::isInBurrow(df::unit *unit, df::burrow *burrow) +{ + CHECK_NULL_POINTER(unit); + CHECK_NULL_POINTER(burrow); + + return binsearch_index(unit->burrows, burrow->id) >= 0; +} + +void DFHack::Units::setInBurrow(df::unit *unit, df::burrow *burrow, bool enable) +{ + using df::global::ui; + + CHECK_NULL_POINTER(unit); + CHECK_NULL_POINTER(burrow); + + if (enable) + { + insert_into_vector(unit->burrows, burrow->id); + insert_into_vector(burrow->units, unit->id); + } + else + { + erase_from_vector(unit->burrows, burrow->id); + erase_from_vector(burrow->units, unit->id); + } + + // Sync ui if active + if (ui && ui->main.mode == ui_sidebar_mode::Burrows && + ui->burrows.in_add_units_mode && ui->burrows.sel_id == burrow->id) + { + int idx = linear_index(ui->burrows.list_units, unit); + if (idx >= 0) + ui->burrows.sel_units[idx] = enable; + } +} + diff --git a/library/xml b/library/xml index baeee2ce1..27fec9797 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit baeee2ce115e0b3432e5b66b843e8883e5f03b34 +Subproject commit 27fec9797d7d1215bd3f5530b44a55a9d394fe75