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.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;