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++)