From 87ec1de891625e9dc68924c570ede0fe23b4b6b7 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 13 May 2012 13:58:41 +0400 Subject: [PATCH] Improve lua api for tile biome access. --- LUA_API.rst | 6 +++- Lua API.html | 5 +++- library/LuaApi.cpp | 52 +++++++++++++++++++++++++++++++++- library/include/LuaTools.h | 8 ++++-- library/include/modules/Maps.h | 12 ++++++++ library/lua/dfhack.lua | 8 ++++-- library/modules/Maps.cpp | 47 +++++++++++++++++++++++------- 7 files changed, 120 insertions(+), 18 deletions(-) diff --git a/LUA_API.rst b/LUA_API.rst index d8d53a4d1..bb1ef803e 100644 --- a/LUA_API.rst +++ b/LUA_API.rst @@ -807,7 +807,7 @@ Maps module Returns a map block object for given df::coord or x,y,z in local tile coordinates. -* ``dfhack.maps.getRegionBiome(region_coord2d)`` +* ``dfhack.maps.getRegionBiome(region_coord2d)``, or ``getRegionBiome(x,y)`` Returns the biome info struct for the given global map region. @@ -823,6 +823,10 @@ Maps module Returns the local feature object with the given region coords and index. +* ``dfhack.maps.getTileBiomeRgn(coords)``, or ``getTileBiomeRgn(x,y,z)`` + + Returns *x, y* for use with ``getRegionBiome``. + * ``dfhack.maps.canWalkBetween(pos1, pos2)`` Checks if a dwarf may be able to walk between the two tiles, diff --git a/Lua API.html b/Lua API.html index 846299a35..3e023ebd3 100644 --- a/Lua API.html +++ b/Lua API.html @@ -1026,7 +1026,7 @@ Returns false in case of error.

  • dfhack.maps.getTileBlock(coords), or getTileBlock(x,y,z)

    Returns a map block object for given df::coord or x,y,z in local tile coordinates.

  • -
  • dfhack.maps.getRegionBiome(region_coord2d)

    +
  • dfhack.maps.getRegionBiome(region_coord2d), or getRegionBiome(x,y)

    Returns the biome info struct for the given global map region.

  • dfhack.maps.enableBlockUpdates(block[,flow,temperature])

    @@ -1038,6 +1038,9 @@ Returns false in case of error.

  • dfhack.maps.getLocalInitFeature(region_coord2d,index)

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

  • +
  • dfhack.maps.getTileBiomeRgn(coords), or getTileBiomeRgn(x,y,z)

    +

    Returns x, y for use with getRegionBiome.

    +
  • dfhack.maps.canWalkBetween(pos1, pos2)

    Checks if a dwarf may be able to walk between the two tiles, using a pathfinding cache maintained by the game. Note that diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 1baa4045d..529bdd077 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -94,6 +94,26 @@ void Lua::Push(lua_State *state, const Units::NoblePosition &pos) lua_setfield(state, -2, "position"); } +void Lua::Push(lua_State *state, df::coord pos) +{ + lua_createtable(state, 0, 3); + lua_pushinteger(state, pos.x); + lua_setfield(state, -2, "x"); + lua_pushinteger(state, pos.y); + lua_setfield(state, -2, "y"); + lua_pushinteger(state, pos.z); + lua_setfield(state, -2, "z"); +} + +void Lua::Push(lua_State *state, df::coord2d pos) +{ + lua_createtable(state, 0, 2); + lua_pushinteger(state, pos.x); + lua_setfield(state, -2, "x"); + lua_pushinteger(state, pos.y); + lua_setfield(state, -2, "y"); +} + int Lua::PushPosXYZ(lua_State *state, df::coord pos) { if (!pos.isValid()) @@ -110,6 +130,21 @@ int Lua::PushPosXYZ(lua_State *state, df::coord pos) } } +int Lua::PushPosXY(lua_State *state, df::coord2d pos) +{ + if (!pos.isValid()) + { + lua_pushnil(state); + return 1; + } + else + { + lua_pushinteger(state, pos.x); + lua_pushinteger(state, pos.y); + return 2; + } +} + static df::coord2d CheckCoordXY(lua_State *state, int base, bool vararg = false) { df::coord2d p; @@ -754,7 +789,6 @@ static const luaL_Reg dfhack_items_funcs[] = { static const LuaWrapper::FunctionReg dfhack_maps_module[] = { WRAPN(getBlock, (df::map_block* (*)(int32_t,int32_t,int32_t))Maps::getBlock), - WRAPM(Maps, getRegionBiome), WRAPM(Maps, enableBlockUpdates), WRAPM(Maps, getGlobalInitFeature), WRAPM(Maps, getLocalInitFeature), @@ -769,8 +803,24 @@ static int maps_getTileBlock(lua_State *L) return 1; } +static int maps_getRegionBiome(lua_State *L) +{ + auto pos = CheckCoordXY(L, 1, true); + Lua::PushDFObject(L, Maps::getRegionBiome(pos)); + return 1; +} + +static int maps_getTileBiomeRgn(lua_State *L) +{ + auto pos = CheckCoordXYZ(L, 1, true); + Lua::PushPosXY(L, Maps::getTileBiomeRgn(pos)); + return 1; +} + static const luaL_Reg dfhack_maps_funcs[] = { { "getTileBlock", maps_getTileBlock }, + { "getRegionBiome", maps_getRegionBiome }, + { "getTileBiomeRgn", maps_getTileBiomeRgn }, { NULL, NULL } }; diff --git a/library/include/LuaTools.h b/library/include/LuaTools.h index a52db2572..d3c7a65d2 100644 --- a/library/include/LuaTools.h +++ b/library/include/LuaTools.h @@ -264,11 +264,14 @@ namespace DFHack {namespace Lua { inline void Push(lua_State *state, bool value) { lua_pushboolean(state, value); } + inline void Push(lua_State *state, const char *str) { + lua_pushstring(state, str); + } inline void Push(lua_State *state, const std::string &str) { lua_pushlstring(state, str.data(), str.size()); } - inline void Push(lua_State *state, df::coord &obj) { PushDFObject(state, &obj); } - inline void Push(lua_State *state, df::coord2d &obj) { PushDFObject(state, &obj); } + DFHACK_EXPORT void Push(lua_State *state, df::coord obj); + DFHACK_EXPORT void Push(lua_State *state, df::coord2d obj); void Push(lua_State *state, const Units::NoblePosition &pos); template inline void Push(lua_State *state, T *ptr) { PushDFObject(state, ptr); @@ -293,6 +296,7 @@ namespace DFHack {namespace Lua { } DFHACK_EXPORT int PushPosXYZ(lua_State *state, df::coord pos); + DFHACK_EXPORT int PushPosXY(lua_State *state, df::coord2d pos); DFHACK_EXPORT bool IsCoreContext(lua_State *state); diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h index c6dc7c404..e63eef733 100644 --- a/library/include/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -255,8 +255,20 @@ inline df::tile_occupancy *getTileOccupancy(df::coord pos) { return getTileOccupancy(pos.x, pos.y, pos.z); } +/** + * Returns biome info about the specified world region. + */ DFHACK_EXPORT df::world_data::T_region_map *getRegionBiome(df::coord2d rgn_pos); +/** + * Returns biome world region coordinates for the given tile within given block. + */ +DFHACK_EXPORT df::coord2d getBlockTileBiomeRgn(df::map_block *block, df::coord2d pos); + +inline df::coord2d getTileBiomeRgn(df::coord pos) { + return getBlockTileBiomeRgn(getTileBlock(pos), pos); +} + // Enables per-frame updates for liquid flow and/or temperature. DFHACK_EXPORT void enableBlockUpdates(df::map_block *blk, bool flow = false, bool temperature = false); diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua index c0ba64375..926600c0f 100644 --- a/library/lua/dfhack.lua +++ b/library/lua/dfhack.lua @@ -111,9 +111,11 @@ function copyall(table) end function pos2xyz(pos) - local x = pos.x - if x and x ~= -30000 then - return x, pos.y, pos.z + if pos then + local x = pos.x + if x and x ~= -30000 then + return x, pos.y, pos.z + end end end diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index a8b7945d1..3160af75e 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -369,6 +369,39 @@ bool Maps::RemoveBlockEvent(uint32_t x, uint32_t y, uint32_t z, df::block_square return false; } +static df::coord2d biome_offsets[9] = { + df::coord2d(-1,-1), df::coord2d(0,-1), df::coord2d(1,-1), + df::coord2d(-1,0), df::coord2d(0,0), df::coord2d(1,0), + df::coord2d(-1,1), df::coord2d(0,1), df::coord2d(1,1) +}; + +inline df::coord2d getBiomeRgnPos(df::coord2d base, int idx) +{ + auto r = base + biome_offsets[idx]; + + int world_width = world->world_data->world_width; + int world_height = world->world_data->world_height; + + return df::coord2d(clip_range(r.x,0,world_width-1),clip_range(r.y,0,world_height-1)); +} + +df::coord2d Maps::getBlockTileBiomeRgn(df::map_block *block, df::coord2d pos) +{ + if (!block || !world->world_data) + return df::coord2d(); + + auto des = MapExtras::index_tile(block->designation,pos); + unsigned idx = des.bits.biome; + if (idx < 9) + { + idx = block->region_offset[idx]; + if (idx < 9) + return getBiomeRgnPos(block->region_pos, idx); + } + + return df::coord2d(); +} + /* * Layer geology */ @@ -386,20 +419,14 @@ bool Maps::ReadGeology(vector > *layer_mats, vector (*geoidx)[i] = df::coord2d(-30000,-30000); } - int world_width = world->world_data->world_width; - int world_height = world->world_data->world_height; + // regionX is in embark squares + // regionX/16 is in 16x16 embark square regions + df::coord2d map_region(world->map.region_x / 16, world->map.region_y / 16); // iterate over 8 surrounding regions + local region for (int i = eNorthWest; i < eBiomeCount; i++) { - // check against worldmap boundaries, fix if needed - // regionX is in embark squares - // regionX/16 is in 16x16 embark square regions - // i provides -1 .. +1 offset from the current region - int bioRX = world->map.region_x / 16 + ((i % 3) - 1); - int bioRY = world->map.region_y / 16 + ((i / 3) - 1); - - df::coord2d rgn_pos(clip_range(bioRX,0,world_width-1),clip_range(bioRY,0,world_height-1)); + df::coord2d rgn_pos = getBiomeRgnPos(map_region, i); (*geoidx)[i] = rgn_pos;