diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 3eb053e73..a4130096b 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -3920,6 +3920,22 @@ A class with all the tcp functionality. Tries connecting to that address and port. Returns ``client`` object. + +.. _map-render: + +map-render +========== + +A way to ask df to render a slice of map. This uses native df rendering function so it's highly dependant on +df settings (e.g. used tileset, colors, if using graphics or not and so on...) + +Functions +--------- + +- ``render_map_rect(x,y,z,w,h)`` + + returns a table with w*h*4 entries of rendered tiles. The format is same as ``df.global.gps.screen`` (tile,foreground,bright,background). + .. _cxxrandom: cxxrandom diff --git a/docs/Plugins.rst b/docs/Plugins.rst index 4d122bb51..2b78fd700 100644 --- a/docs/Plugins.rst +++ b/docs/Plugins.rst @@ -2848,4 +2848,5 @@ in the `lua-api` file under `lua-plugins`: * `eventful` * `building-hacks` * `luasocket` +* `map-render` * `cxxrandom` diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 284922cc1..fbca6bca9 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -136,6 +136,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(liquids liquids.cpp Brushes.h LINK_LIBRARIES lua) DFHACK_PLUGIN(luasocket luasocket.cpp LINK_LIBRARIES clsocket lua dfhack-tinythread) DFHACK_PLUGIN(manipulator manipulator.cpp) + DFHACK_PLUGIN(map-render map-render.cpp LINK_LIBRARIES lua) DFHACK_PLUGIN(misery misery.cpp) DFHACK_PLUGIN(mode mode.cpp) DFHACK_PLUGIN(mousequery mousequery.cpp) diff --git a/plugins/lua/map-render.lua b/plugins/lua/map-render.lua new file mode 100644 index 000000000..9785c365e --- /dev/null +++ b/plugins/lua/map-render.lua @@ -0,0 +1,11 @@ +local _ENV = mkmodule('plugins.map-render') + +--[[ + + Native functions: + + * render_map_rect(x,y,z,w,h) + +--]] + +return _ENV \ No newline at end of file diff --git a/plugins/map-render.cpp b/plugins/map-render.cpp new file mode 100644 index 000000000..f89d8ab4e --- /dev/null +++ b/plugins/map-render.cpp @@ -0,0 +1,125 @@ +#include "Core.h" +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "VersionInfo.h" +#include "VTableInterpose.h" +#include "LuaTools.h" + +#include "DataDefs.h" + +#include "df/viewscreen_dwarfmodest.h" +#include "df/init.h" +#include "df/renderer.h" +#include "df/graphic.h" +#include "df/enabler.h" +#include "df/map_renderer.h" + +using std::string; +using std::vector; +using namespace DFHack; +using namespace df::enums; + +DFHACK_PLUGIN("map-render"); +REQUIRE_GLOBAL(window_x) +REQUIRE_GLOBAL(window_y) +REQUIRE_GLOBAL(window_z) +REQUIRE_GLOBAL_NO_USE(gps) +REQUIRE_GLOBAL_NO_USE(enabler) +REQUIRE_GLOBAL_NO_USE(twbt_render_map) +REQUIRE_GLOBAL(init) + +#ifdef WIN32 + // On Windows there's no parameter pointing to the map_renderer structure + typedef void(_stdcall *RENDER_MAP)(int); + + RENDER_MAP _render_map; + + void render_map(){ _render_map(0); } +#else +REQUIRE_GLOBAL(map_renderer) + + typedef void(*RENDER_MAP)(void*, int); + + RENDER_MAP _render_map; + + void render_map(){ _render_map(map_renderer,0); } +#endif +static int render_map_rect(lua_State* L) +{ + CoreSuspender suspender; + + int x = luaL_checkint(L, 1); + int y = luaL_checkint(L, 2); + int z = luaL_checkint(L, 3); + int w = luaL_checkint(L, 4); + int h = luaL_checkint(L, 5); + uint8_t *s = df::global::gps->screen; + //backup state + //TODO: figure out if we can replace screen with other pointer. That way it could be a bit more tidy + int32_t win_h = df::global::gps->dimy; + int32_t was_x = *window_x; + int32_t was_y = *window_y; + int32_t was_z = *window_z; + int32_t gx = init->display.grid_x; + int32_t gy = init->display.grid_y; + init->display.grid_x = w+1; + init->display.grid_y = h+1; + *window_x = x; + *window_y = y; + *window_z = z; + //force full redraw + df::global::gps->force_full_display_count = 1; + //this modifies screen so it REALLY wants to redraw stuff + for (int ty = 0; ty < h; ty++) + for (int tx = 0; tx < w; tx++) + { + for (int i = 0; i < 4; i++) + { + int t = (tx + 1)*win_h + ty + 1; + s[t * 4 + i] = 0; + } + } + render_map(); + //restore state + *window_x = was_x; + *window_y = was_y; + *window_z = was_z; + init->display.grid_x = gx; + init->display.grid_y = gy; + + lua_createtable(L,w*h*4,0); + + int counter = 0; + for (int ty = 0; ty < h; ty++) + for (int tx = 0; tx < w; tx++) + { + for (int i = 0; i < 4;i++) + { + int t = (tx + 1)*win_h + ty + 1; + lua_pushnumber(L, s[t*4+i]); + lua_rawseti(L, -2, counter); + counter++; + } + } + return 1; +} + +DFHACK_PLUGIN_LUA_COMMANDS{ + DFHACK_LUA_COMMAND(render_map_rect), + DFHACK_LUA_END +}; + +DFhackCExport command_result plugin_init(color_ostream &out, std::vector &commands) +{ + auto addr =reinterpret_cast(Core::getInstance().vinfo->getAddress("twbt_render_map")); + if (addr == nullptr) + return CR_FAILURE; + _render_map = addr; + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown(color_ostream &out) +{ + return CR_OK; +}