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