From b70130cf3684d8adbf36023b27aec0f10b213cc7 Mon Sep 17 00:00:00 2001
From: Alexander Gavrilov
Date: Sun, 6 May 2012 11:22:55 +0400
Subject: [PATCH] Add a couple more building api functions.
---
LUA_API.rst | 16 +++++--
Lua API.html | 14 ++++--
library/LuaApi.cpp | 74 +++++++++++++++++++++++------
library/include/modules/Buildings.h | 13 ++++-
library/modules/Buildings.cpp | 45 ++++++++++++++++++
5 files changed, 140 insertions(+), 22 deletions(-)
diff --git a/LUA_API.rst b/LUA_API.rst
index 938664379..681caef54 100644
--- a/LUA_API.rst
+++ b/LUA_API.rst
@@ -873,10 +873,16 @@ Buildings module
Returns *width, height, centerx, centery*.
-* ``dfhack.buildings.findAtTile(pos)``
+* ``dfhack.buildings.findAtTile(pos)``, or ``findAtTile(x,y,z)``
Scans the buildings for the one located at the given tile.
- Does not work on civzones. Warning: linear scan.
+ Does not work on civzones. Warning: linear scan if the map
+ tile indicates there are buildings at it.
+
+* ``dfhack.buildings.findCivzonesAt(pos)``, or ``findCivzonesAt(x,y,z)``
+
+ Scans civzones, and returns a lua sequence of those that touch
+ the given tile, or *nil* if none.
* ``dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)``
@@ -894,6 +900,10 @@ Buildings module
Returns the number of tiles included by extents, or defval.
+* ``dfhack.buildings.containsTile(building, x, y[, room])``
+
+ Checks if the building contains the specified tile, either directly, or as room.
+
* ``dfhack.buildings.hasSupport(pos,size)``
Checks if a bridge constructed at specified position would have
@@ -911,7 +921,7 @@ Low-level building creation functions;
Configures an object returned by ``allocInstance``, using specified
parameters wherever appropriate. If the building has fixed size along
any dimension, the corresponding input parameter will be ignored.
- Returns *nil* if the building cannot be placed, or *true, width,
+ Returns *false* if the building cannot be placed, or *true, width,
height, rect_area, true_area*. Returned width and height are the
final values used by the building; true_area is less than rect_area
if any tiles were removed from designation.
diff --git a/Lua API.html b/Lua API.html
index b96d12156..094b522c3 100644
--- a/Lua API.html
+++ b/Lua API.html
@@ -1081,9 +1081,14 @@ burrows, or the presence of invaders.
dfhack.buildings.getSize(building)
Returns width, height, centerx, centery.
-dfhack.buildings.findAtTile(pos)
+dfhack.buildings.findAtTile(pos), or findAtTile(x,y,z)
Scans the buildings for the one located at the given tile.
-Does not work on civzones. Warning: linear scan.
+Does not work on civzones. Warning: linear scan if the map
+tile indicates there are buildings at it.
+
+dfhack.buildings.findCivzonesAt(pos), or findCivzonesAt(x,y,z)
+Scans civzones, and returns a lua sequence of those that touch
+the given tile, or nil if none.
dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)
Computes correct dimensions for the specified building type and orientation,
@@ -1098,6 +1103,9 @@ are removed from extents. If allow_occupied, t
dfhack.buildings.countExtentTiles(extents,defval)
Returns the number of tiles included by extents, or defval.
+dfhack.buildings.containsTile(building, x, y[, room])
+Checks if the building contains the specified tile, either directly, or as room.
+
dfhack.buildings.hasSupport(pos,size)
Checks if a bridge constructed at specified position would have
support from terrain, and thus won't collapse if retracted.
@@ -1113,7 +1121,7 @@ at specified position. Returns the object, or nil in case of an error.<
Configures an object returned by allocInstance, using specified
parameters wherever appropriate. If the building has fixed size along
any dimension, the corresponding input parameter will be ignored.
-Returns nil if the building cannot be placed, or true, width,
+Returns false if the building cannot be placed, or true, width,
height, rect_area, true_area. Returned width and height are the
final values used by the building; true_area is less than rect_area
if any tiles were removed from designation.
diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp
index 6a8100a34..bf2ec9364 100644
--- a/library/LuaApi.cpp
+++ b/library/LuaApi.cpp
@@ -74,6 +74,7 @@ distribution.
#include "df/dfhack_material_category.h"
#include "df/job_material_category.h"
#include "df/burrow.h"
+#include "df/building_civzonest.h"
#include
#include
@@ -109,6 +110,37 @@ int Lua::PushPosXYZ(lua_State *state, df::coord pos)
}
}
+static df::coord2d CheckCoordXY(lua_State *state, int base, bool vararg = false)
+{
+ df::coord2d p;
+ if (vararg && lua_gettop(state) <= base)
+ Lua::CheckDFAssign(state, &p, base);
+ else
+ {
+ p = df::coord2d(
+ luaL_checkint(state, base),
+ luaL_checkint(state, base+1)
+ );
+ }
+ return p;
+}
+
+static df::coord CheckCoordXYZ(lua_State *state, int base, bool vararg = false)
+{
+ df::coord p;
+ if (vararg && lua_gettop(state) <= base)
+ Lua::CheckDFAssign(state, &p, base);
+ else
+ {
+ p = df::coord(
+ luaL_checkint(state, base),
+ luaL_checkint(state, base+1),
+ luaL_checkint(state, base+2)
+ );
+ }
+ return p;
+}
+
/**************************************************
* Per-world persistent configuration storage API *
**************************************************/
@@ -729,20 +761,8 @@ static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
static int maps_getTileBlock(lua_State *L)
{
- df::map_block *block;
- if (lua_gettop(L) == 1)
- {
- df::coord pos;
- Lua::CheckDFAssign(L, &pos, 1);
- block = Maps::getTileBlock(pos);
- }
- else
- {
- block = Maps::getTileBlock(
- luaL_checkint(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3)
- );
- }
- Lua::PushDFObject(L, block);
+ auto pos = CheckCoordXYZ(L, 1, true);
+ Lua::PushDFObject(L, Maps::getTileBlock(pos));
return 1;
}
@@ -791,17 +811,39 @@ static const luaL_Reg dfhack_burrows_funcs[] = {
/***** Buildings module *****/
+static bool buildings_containsTile(df::building *bld, int x, int y, bool room) {
+ return Buildings::containsTile(bld, df::coord2d(x,y), room);
+}
+
static const LuaWrapper::FunctionReg dfhack_buildings_module[] = {
- WRAPM(Buildings, findAtTile),
WRAPM(Buildings, allocInstance),
WRAPM(Buildings, checkFreeTiles),
WRAPM(Buildings, countExtentTiles),
+ WRAPN(containsTile, buildings_containsTile),
WRAPM(Buildings, hasSupport),
WRAPM(Buildings, constructWithItems),
WRAPM(Buildings, constructWithFilters),
{ NULL, NULL }
};
+static int buildings_findAtTile(lua_State *L)
+{
+ auto pos = CheckCoordXYZ(L, 1, true);
+ Lua::PushDFObject(L, Buildings::findAtTile(pos));
+ return 1;
+}
+
+static int buildings_findCivzonesAt(lua_State *L)
+{
+ auto pos = CheckCoordXYZ(L, 1, true);
+ std::vector pvec;
+ if (Buildings::findCivzonesAt(&pvec, pos))
+ Lua::PushVector(L, pvec);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
static int buildings_getCorrectSize(lua_State *state)
{
df::coord2d size(luaL_optint(state, 1, 1), luaL_optint(state, 2, 1));
@@ -844,6 +886,8 @@ static int buildings_setSize(lua_State *state)
}
static const luaL_Reg dfhack_buildings_funcs[] = {
+ { "findAtTile", buildings_findAtTile },
+ { "findCivzonesAt", buildings_findCivzonesAt },
{ "getCorrectSize", buildings_getCorrectSize },
{ "setSize", buildings_setSize },
{ NULL, NULL }
diff --git a/library/include/modules/Buildings.h b/library/include/modules/Buildings.h
index 9e529b6ca..9bb3ba001 100644
--- a/library/include/modules/Buildings.h
+++ b/library/include/modules/Buildings.h
@@ -39,6 +39,7 @@ namespace df
struct job_item;
struct item;
struct building_extents;
+ struct building_civzonest;
}
namespace DFHack
@@ -91,12 +92,17 @@ DFHACK_EXPORT bool Read (const uint32_t index, t_building & building);
*/
DFHACK_EXPORT bool ReadCustomWorkshopTypes(std::map & btypes);
-/*
+/**
* Find the building located at the specified tile.
* Does not work on civzones.
*/
DFHACK_EXPORT df::building *findAtTile(df::coord pos);
+/**
+ * Find civzones located at the specified tile.
+ */
+DFHACK_EXPORT bool findCivzonesAt(std::vector *pvec, df::coord pos);
+
/**
* Allocates a building object using this type and position.
*/
@@ -122,6 +128,11 @@ DFHACK_EXPORT bool checkFreeTiles(df::coord pos, df::coord2d size,
*/
DFHACK_EXPORT int countExtentTiles(df::building_extents *ext, int defval = -1);
+/**
+ * Checks if the building contains the specified tile.
+ */
+DFHACK_EXPORT bool containsTile(df::building *bld, df::coord2d tile, bool room = false);
+
/**
* Checks if the area has support from the terrain.
*/
diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp
index 0512e9f03..2c5162673 100644
--- a/library/modules/Buildings.cpp
+++ b/library/modules/Buildings.cpp
@@ -58,6 +58,7 @@ using namespace DFHack;
#include "df/building_trapst.h"
#include "df/building_bridgest.h"
#include "df/building_coffinst.h"
+#include "df/building_civzonest.h"
#include "df/building_furnacest.h"
#include "df/building_workshopst.h"
#include "df/building_screw_pumpst.h"
@@ -153,6 +154,25 @@ df::building *Buildings::findAtTile(df::coord pos)
return NULL;
}
+bool Buildings::findCivzonesAt(std::vector *pvec, df::coord pos)
+{
+ pvec->clear();
+
+ auto &vec = world->buildings.other[buildings_other_id::ANY_ZONE];
+
+ for (size_t i = 0; i < vec.size(); i++)
+ {
+ auto bld = strict_virtual_cast(vec[i]);
+
+ if (!bld || bld->z != pos.z || !containsTile(bld, pos))
+ continue;
+
+ pvec->push_back(bld);
+ }
+
+ return !pvec->empty();
+}
+
df::building *Buildings::allocInstance(df::coord pos, df::building_type type, int subtype, int custom)
{
if (!building_next_id)
@@ -464,6 +484,31 @@ int Buildings::countExtentTiles(df::building_extents *ext, int defval)
return cnt;
}
+bool Buildings::containsTile(df::building *bld, df::coord2d tile, bool room)
+{
+ CHECK_NULL_POINTER(bld);
+
+ if (room)
+ {
+ if (!bld->is_room || !bld->room.extents)
+ return false;
+ }
+ else
+ {
+ if (tile.x < bld->x1 || tile.x > bld->x2 || tile.y < bld->y1 || tile.y >= bld->y2)
+ return false;
+ }
+
+ if (bld->room.extents && (room || bld->isExtentShaped()))
+ {
+ uint8_t *etile = getExtentTile(bld->room, tile);
+ if (!etile || !*etile)
+ return false;
+ }
+
+ return true;
+}
+
bool Buildings::hasSupport(df::coord pos, df::coord2d size)
{
for (int dx = -1; dx <= size.x; dx++)