From fb8d6614c7598fe843461d587b9139e65fc5514d Mon Sep 17 00:00:00 2001 From: myk002 Date: Wed, 2 Jun 2021 14:49:19 -0700 Subject: [PATCH] expose core flood unhide logic to Lua refactor is a straight copy-paste. this code could really stand some cleanup (unused vars, unnecessary use of the MapCache layer, forced allocation of all blocks even if they are not being unhidden, etc.), but that can come in a later PR. --- docs/Lua API.rst | 15 ++++ library/include/PluginManager.h | 1 + plugins/CMakeLists.txt | 2 +- plugins/lua/reveal.lua | 12 +++ plugins/reveal.cpp | 147 +++++++++++++++++++------------- 5 files changed, 117 insertions(+), 60 deletions(-) create mode 100644 plugins/lua/reveal.lua diff --git a/docs/Lua API.rst b/docs/Lua API.rst index d00acd271..14c4b307f 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -4297,6 +4297,21 @@ single Lua function, in ``hack/lua/plugins/pathable.lua``: ``cursor``. If ``skip_unrevealed`` is specified and true, do not draw unrevealed tiles. +reveal +====== + +Native functions provided by the `reveal` plugin: + +* ``void unhideFlood(pos)``: Unhides map tiles according to visibility rules, + starting from the given coordinates. This algorithm only processes adjacent + hidden tiles, so it must start on a hidden tile in order to have any effect. + It will not reveal hidden sections separated by already-unhidden tiles. + +Example of revealing a cavern that happens to have an open tile at the specified +coordinate:: + + unhideFlood({x=25, y=38, z=140}) + sort ==== diff --git a/library/include/PluginManager.h b/library/include/PluginManager.h index 8f73c8ec2..ec00e4ab0 100644 --- a/library/include/PluginManager.h +++ b/library/include/PluginManager.h @@ -33,6 +33,7 @@ distribution. #include #include "Core.h" +#include "DataFuncs.h" #include "RemoteClient.h" diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 822ab531b..de6388050 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -155,7 +155,7 @@ if(BUILD_SUPPORTED) dfhack_plugin(rename rename.cpp LINK_LIBRARIES lua PROTOBUFS rename) add_subdirectory(rendermax) dfhack_plugin(resume resume.cpp LINK_LIBRARIES lua) - dfhack_plugin(reveal reveal.cpp) + dfhack_plugin(reveal reveal.cpp LINK_LIBRARIES lua) dfhack_plugin(search search.cpp) dfhack_plugin(seedwatch seedwatch.cpp) dfhack_plugin(showmood showmood.cpp) diff --git a/plugins/lua/reveal.lua b/plugins/lua/reveal.lua new file mode 100644 index 000000000..f84cfed96 --- /dev/null +++ b/plugins/lua/reveal.lua @@ -0,0 +1,12 @@ +local _ENV = mkmodule('plugins.reveal') + +--[[ + + Native functions: + + * isEnabled() + * unhideFlood(pos) + +--]] + +return _ENV diff --git a/plugins/reveal.cpp b/plugins/reveal.cpp index 257dd5127..c23f512b9 100644 --- a/plugins/reveal.cpp +++ b/plugins/reveal.cpp @@ -2,10 +2,12 @@ #include #include #include + #include "Core.h" #include "Console.h" #include "Export.h" #include "PluginManager.h" + #include "modules/Maps.h" #include "modules/World.h" #include "modules/MapCache.h" @@ -329,66 +331,12 @@ command_result revtoggle (color_ostream &out, vector & params) } } -command_result revflood(color_ostream &out, vector & params) +// Unhides map tiles according to visibility, starting from the given +// coordinates. This algorithm only processes adjacent hidden tiles, so it must +// start on a hidden tile and it will not reveal hidden sections separated by +// already-unhidden tiles. +static void unhideFlood_internal(MapCache *MCache, const DFCoord &xy) { - for(size_t i = 0; i < params.size();i++) - { - if(params[i] == "help" || params[i] == "?") - return CR_WRONG_USAGE; - } - CoreSuspender suspend; - uint32_t x_max,y_max,z_max; - if (!Maps::IsValid()) - { - out.printerr("Map is not available!\n"); - return CR_FAILURE; - } - if(revealed != NOT_REVEALED) - { - out.printerr("This is only safe to use with non-revealed map.\n"); - return CR_FAILURE; - } - t_gamemodes gm; - World::ReadGameMode(gm); - if(!World::isFortressMode(gm.g_type) || gm.g_mode != game_mode::DWARF ) - { - out.printerr("Only in proper dwarf mode.\n"); - return CR_FAILURE; - } - int32_t cx, cy, cz; - Maps::getSize(x_max,y_max,z_max); - uint32_t tx_max = x_max * 16; - uint32_t ty_max = y_max * 16; - - Gui::getCursorCoords(cx,cy,cz); - if(cx == -30000) - { - out.printerr("Cursor is not active. Point the cursor at some empty space you want to be unhidden.\n"); - return CR_FAILURE; - } - DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz); - MapCache * MCache = new MapCache; - df::tiletype tt = MCache->tiletypeAt(xy); - if(isWallTerrain(tt)) - { - out.printerr("Point the cursor at some empty space you want to be unhidden.\n"); - delete MCache; - return CR_FAILURE; - } - // hide all tiles, flush cache - Maps::getSize(x_max,y_max,z_max); - - for(size_t i = 0; i < world->map.map_blocks.size(); i++) - { - df::map_block * b = world->map.map_blocks[i]; - // change the hidden flag to 0 - for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++) - { - b->designation[x][y].bits.hidden = 1; - } - } - MCache->trash(); - typedef std::pair foo; std::stack < foo > flood; flood.push( foo(xy,false) ); @@ -500,8 +448,84 @@ command_result revflood(color_ostream &out, vector & params) flood.push(foo(DFCoord(current.x, current.y, current.z - 1), false)); } } +} + +// Lua entrypoint for unhideFlood_internal +static void unhideFlood(DFCoord pos) +{ + CoreSuspender suspend; + + MapCache MCache; + // no bounds checking needed for pos. if it's invalid, unhideFlood_internal + // will just exit immeditately + unhideFlood_internal(&MCache, pos); + MCache.WriteAll(); +} + +command_result revflood(color_ostream &out, vector & params) +{ + for(size_t i = 0; i < params.size();i++) + { + if(params[i] == "help" || params[i] == "?") + return CR_WRONG_USAGE; + } + CoreSuspender suspend; + uint32_t x_max,y_max,z_max; + if (!Maps::IsValid()) + { + out.printerr("Map is not available!\n"); + return CR_FAILURE; + } + if(revealed != NOT_REVEALED) + { + out.printerr("This is only safe to use with non-revealed map.\n"); + return CR_FAILURE; + } + t_gamemodes gm; + World::ReadGameMode(gm); + if(!World::isFortressMode(gm.g_type) || gm.g_mode != game_mode::DWARF ) + { + out.printerr("Only in proper dwarf mode.\n"); + return CR_FAILURE; + } + int32_t cx, cy, cz; + Maps::getSize(x_max,y_max,z_max); + uint32_t tx_max = x_max * 16; + uint32_t ty_max = y_max * 16; + + Gui::getCursorCoords(cx,cy,cz); + if(cx == -30000) + { + out.printerr("Cursor is not active. Point the cursor at some empty space you want to be unhidden.\n"); + return CR_FAILURE; + } + DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz); + MapCache * MCache = new MapCache; + df::tiletype tt = MCache->tiletypeAt(xy); + if(isWallTerrain(tt)) + { + out.printerr("Point the cursor at some empty space you want to be unhidden.\n"); + delete MCache; + return CR_FAILURE; + } + // hide all tiles, flush cache + Maps::getSize(x_max,y_max,z_max); + + for(size_t i = 0; i < world->map.map_blocks.size(); i++) + { + df::map_block * b = world->map.map_blocks[i]; + // change the hidden flag to 0 + for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++) + { + b->designation[x][y].bits.hidden = 1; + } + } + MCache->trash(); + + unhideFlood_internal(MCache, xy); MCache->WriteAll(); delete MCache; + return CR_OK; } @@ -525,3 +549,8 @@ command_result revforget(color_ostream &out, vector & params) con.print("Reveal data forgotten!\n"); return CR_OK; } + +DFHACK_PLUGIN_LUA_FUNCTIONS { + DFHACK_LUA_FUNCTION(unhideFlood), + DFHACK_LUA_END +};