From d3dbc6225a0988784c3c9f44057762bca59adb03 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 17 Oct 2015 15:08:12 -0400 Subject: [PATCH 01/13] Implement getViewscreenByType() in lua --- docs/Lua API.rst | 10 ++++++++-- library/lua/dfhack.lua | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 0cee9a9dc..5a40fa8a8 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -856,6 +856,12 @@ Gui module Returns the focus string of the current viewscreen. +* ``dfhack.gui.getViewscreenByType(type [, depth])`` + + Returns the topmost viewscreen out of the top ``depth`` viewscreens with + the specified type (e.g. ``df.viewscreen_titlest``), or ``nil`` if none match. + If ``limit`` is not specified or is less than 1, all viewscreens are checked. + * ``dfhack.gui.getSelectedWorkshopJob([silent])`` When a job is selected in *'q'* mode, returns the job, else @@ -3480,7 +3486,7 @@ Client is a connection socket to a server. You can get this object either from ` from ``server:accept()``. It's a subclass of ``socket``. * ``client:receive(pattern)`` - + Receives data. If ``pattern`` is a number, it receives that much data. Other supported patterns: * ``*a`` @@ -3501,7 +3507,7 @@ Server class Server is a socket that is waiting for clients. You can get this object from ``tcp:bind(address,port)``. * ``server:accept()`` - + Accepts an incoming connection if it exists. Returns a ``client`` object representing that socket. Tcp class diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua index fa3a3a975..2d0bcd6bc 100644 --- a/library/lua/dfhack.lua +++ b/library/lua/dfhack.lua @@ -285,6 +285,27 @@ function dfhack.buildings.getSize(bld) return bld.x2+1-x, bld.y2+1-y, bld.centerx-x, bld.centery-y end +function dfhack.gui.getViewscreenByType(scr_type, n) + -- translated from modules/Gui.cpp + if n == nil then + n = 1 + end + local limit = (n > 0) + local scr = dfhack.gui.getCurViewscreen() + while scr do + if limit then + n = n - 1 + if n < 0 then + return nil + end + end + if scr_type:is_instance(scr) then + return scr + end + scr = scr.parent + end +end + -- Interactive local print_banner = true From 5387c03ea0142222ec39c34fcd5b77e892e9a5f4 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 17 Oct 2015 15:35:40 -0400 Subject: [PATCH 02/13] DFHackVersion: Expose whether the built commit is tagged --- library/Core.cpp | 15 +++++++++++++-- library/DFHackVersion.cpp | 9 +++++++++ library/LuaApi.cpp | 1 + library/git-describe.cmake | 10 +++++++++- library/include/DFHackVersion.h | 12 +++++++----- 5 files changed, 39 insertions(+), 8 deletions(-) diff --git a/library/Core.cpp b/library/Core.cpp index d187ccd49..823c68a59 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -241,6 +241,17 @@ struct sortable }; }; +static string dfhack_version_desc() +{ + stringstream s; + s << Version::dfhack_version() << " "; + if (Version::is_release()) + s << "(release)"; + else + s << "(development build " << Version::git_description() << ")"; + return s.str(); +} + static std::string getScriptHelp(std::string path, std::string helpprefix) { ifstream script(path.c_str()); @@ -611,7 +622,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v " reload PLUGIN|-all - Reload a plugin or all loaded plugins.\n" ); - con.print("\nDFHack version %s.\n", Version::dfhack_version()); + con.print("\nDFHack version %s\n", dfhack_version_desc().c_str()); } else if (parts.size() == 1) { @@ -1258,7 +1269,7 @@ void fIOthread(void * iodata) con.print("DFHack is ready. Have a nice day!\n" "DFHack version %s\n" "Type in '?' or 'help' for general help, 'ls' to see all commands.\n", - Version::dfhack_version()); + dfhack_version_desc().c_str()); int clueless_counter = 0; while (true) diff --git a/library/DFHackVersion.cpp b/library/DFHackVersion.cpp index cc56af180..d3200a42f 100644 --- a/library/DFHackVersion.cpp +++ b/library/DFHackVersion.cpp @@ -24,5 +24,14 @@ namespace DFHack { { return DFHACK_GIT_COMMIT; } + + bool is_release() + { + #ifdef DFHACK_GIT_TAGGED + return true; + #else + return false; + #endif + } } } diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 698b4ba5a..996cae8f1 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1417,6 +1417,7 @@ static const LuaWrapper::FunctionReg dfhack_module[] = { WRAP_VERSION_FUNC(getCompiledDFVersion, df_version), WRAP_VERSION_FUNC(getGitDescription, git_description), WRAP_VERSION_FUNC(getGitCommit, git_commit), + WRAP_VERSION_FUNC(isRelease, is_release), { NULL, NULL } }; diff --git a/library/git-describe.cmake b/library/git-describe.cmake index 9c5e7a874..e1216edad 100644 --- a/library/git-describe.cmake +++ b/library/git-describe.cmake @@ -4,12 +4,20 @@ execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --long execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD WORKING_DIRECTORY "${dfhack_SOURCE_DIR}" OUTPUT_VARIABLE DFHACK_GIT_COMMIT) +execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --exact-match + WORKING_DIRECTORY "${dfhack_SOURCE_DIR}" + RESULT_VARIABLE DFHACK_GIT_TAGGED_RESULT + OUTPUT_QUIET ERROR_QUIET) string(STRIP ${DFHACK_GIT_DESCRIPTION} DFHACK_GIT_DESCRIPTION) file(WRITE ${dfhack_SOURCE_DIR}/library/include/git-describe.tmp.h "#define DFHACK_GIT_DESCRIPTION \"${DFHACK_GIT_DESCRIPTION}\"\n") string(STRIP ${DFHACK_GIT_COMMIT} DFHACK_GIT_COMMIT) file(APPEND ${dfhack_SOURCE_DIR}/library/include/git-describe.tmp.h - "#define DFHACK_GIT_COMMIT \"${DFHACK_GIT_COMMIT}\"") + "#define DFHACK_GIT_COMMIT \"${DFHACK_GIT_COMMIT}\"\n") +if(${DFHACK_GIT_TAGGED_RESULT} EQUAL 0) + file(APPEND ${dfhack_SOURCE_DIR}/library/include/git-describe.tmp.h + "#define DFHACK_GIT_TAGGED\n") +endif() execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${dfhack_SOURCE_DIR}/library/include/git-describe.tmp.h ${dfhack_SOURCE_DIR}/library/include/git-describe.h) diff --git a/library/include/DFHackVersion.h b/library/include/DFHackVersion.h index 359ed0eba..f035e616a 100644 --- a/library/include/DFHackVersion.h +++ b/library/include/DFHackVersion.h @@ -6,13 +6,15 @@ namespace DFHack { const char *dfhack_release(); const char *git_description(); const char *git_commit(); + bool is_release(); } } #ifndef NO_DFHACK_VERSION_MACROS -#define DF_VERSION DFHack::Version::df_version() -#define DFHACK_RELEASE DFHack::Version::dfhack_release() -#define DFHACK_VERSION DFHack::Version::dfhack_version() -#define DFHACK_GIT_DESCRIPTION DFHack::Version::git_description() -#define DFHACK_GIT_COMMIT DFHack::Version::git_commit() + #define DF_VERSION (DFHack::Version::df_version()) + #define DFHACK_RELEASE (DFHack::Version::dfhack_release()) + #define DFHACK_VERSION (DFHack::Version::dfhack_version()) + #define DFHACK_GIT_DESCRIPTION (DFHack::Version::git_description()) + #define DFHACK_GIT_COMMIT (DFHack::Version::git_commit()) + #define DFHACK_IS_RELEASE (DFHack::Version::is_release()) #endif From 9ebaa4d695ae83548128c959391612780b772502 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 17 Oct 2015 15:45:49 -0400 Subject: [PATCH 03/13] Update Lua API.rst --- docs/Lua API.rst | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 5a40fa8a8..e938a51e0 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -789,11 +789,12 @@ can be omitted. Returns the DF version string from ``symbols.xml``. -* ``getDFHackVersion()`` -* ``getDFHackRelease()`` -* ``getCompiledDFVersion()`` -* ``getGitDescription()`` -* ``getGitCommit()`` +* ``dfhack.getDFHackVersion()`` +* ``dfhack.getDFHackRelease()`` +* ``dfhack.getCompiledDFVersion()`` +* ``dfhack.getGitDescription()`` +* ``dfhack.getGitCommit()`` +* ``dfhack.isRelease()`` Return information about the DFHack build in use. @@ -835,10 +836,20 @@ can be omitted. Convert a string from DF's CP437 encoding to UTF-8. +* ``dfhack.df2console()`` + + Convert a string from DF's CP437 encoding to the correct encoding for the + DFHack console. + * ``dfhack.utf2df(string)`` Convert a string from UTF-8 to DF's CP437 encoding. +**Note:** When printing CP437-encoded text to the console (for example, names +returned from TranslateName()), use ``print(dfhack.df2console(text)`` to ensure +proper display on all platforms. + + Gui module ---------- @@ -860,7 +871,7 @@ Gui module Returns the topmost viewscreen out of the top ``depth`` viewscreens with the specified type (e.g. ``df.viewscreen_titlest``), or ``nil`` if none match. - If ``limit`` is not specified or is less than 1, all viewscreens are checked. + If ``depth`` is not specified or is less than 1, all viewscreens are checked. * ``dfhack.gui.getSelectedWorkshopJob([silent])`` From c44ac8ec6e42f21c25d5666fc1fcf936e7748d42 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 17 Oct 2015 21:18:04 -0400 Subject: [PATCH 04/13] Improve handling of fatal errors and errors in dfhack.lua * Several fatal errors that occurred during core initialization didn't stop initialization or set 'errorstate' properly, which caused update hooks and other code to crash later. This has been fixed and should address crashes like the one mentioned in #470. * Errors when loading dfhack.lua now cause Lua::Open() to fail, which triggers a fatal error in Core::Init() * Failure to initialize the console no longer results in a call to fatal() (since it didn't actually stop initialization previously) --- library/Core.cpp | 22 +++++++++++++++------- library/LuaTools.cpp | 16 +++++++++++----- library/include/Core.h | 2 +- library/include/LuaTools.h | 2 +- plugins/dwarfmonitor.cpp | 2 ++ 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/library/Core.cpp b/library/Core.cpp index 823c68a59..6fdf65a09 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -1336,15 +1336,19 @@ Core::Core() script_path_mutex = new mutex(); }; -void Core::fatal (std::string output, bool deactivate) +void Core::fatal (std::string output) { + errorstate = true; stringstream out; out << output ; - if(deactivate) - out << "DFHack will now deactivate.\n"; + if (output[output.size() - 1] != '\n') + out << '\n'; + out << "DFHack will now deactivate.\n"; if(con.isInited()) { con.printerr("%s", out.str().c_str()); + con.reset_color(); + con.print("\n"); } fprintf(stderr, "%s\n", out.str().c_str()); #ifndef LINUX_BUILD @@ -1395,7 +1399,7 @@ bool Core::Init() delete vif; vif = NULL; errorstate = true; - fatal(out.str(), true); + fatal(out.str()); return false; } p = new DFHack::Process(vif); @@ -1403,7 +1407,7 @@ bool Core::Init() if(!vinfo || !p->isIdentified()) { - fatal ("Not a known DF version.\n", true); + fatal("Not a known DF version.\n"); errorstate = true; delete p; p = NULL; @@ -1429,7 +1433,7 @@ bool Core::Init() else if(con.init(false)) cerr << "Console is running.\n"; else - fatal ("Console has failed to initialize!\n", false); + cerr << "Console has failed to initialize!\n"; /* // dump offsets to a file std::ofstream dump("offsets.log"); @@ -1476,7 +1480,11 @@ bool Core::Init() } // initialize common lua context - Lua::Core::Init(con); + if (!Lua::Core::Init(con)) + { + fatal("Lua failed to initialize"); + return false; + } // create mutex for syncing with interactive tasks misc_data_mutex=new mutex(); diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp index 7992373a9..008cb00c2 100644 --- a/library/LuaTools.cpp +++ b/library/LuaTools.cpp @@ -1701,7 +1701,11 @@ lua_State *DFHack::Lua::Open(color_ostream &out, lua_State *state) Lua::Core::InitCoreContext(); // load dfhack.lua - Require(out, state, "dfhack"); + if (!Require(out, state, "dfhack")) + { + out.printerr("Could not load dfhack.lua\n"); + return NULL; + } lua_settop(state, 0); if (!lua_checkstack(state, 64)) @@ -1868,15 +1872,17 @@ void DFHack::Lua::Core::onUpdate(color_ostream &out) run_timers(out, State, tick_timers, frame[1], world->frame_counter); } -void DFHack::Lua::Core::Init(color_ostream &out) +bool DFHack::Lua::Core::Init(color_ostream &out) { - if (State) - return; + if (State) { + out.printerr("state already exists\n"); + return false; + } State = luaL_newstate(); // Calls InitCoreContext after checking IsCoreContext - Lua::Open(out, State); + return (Lua::Open(out, State) != NULL); } static void Lua::Core::InitCoreContext() diff --git a/library/include/Core.h b/library/include/Core.h index 2d74405e1..f76ba2b73 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -217,7 +217,7 @@ namespace DFHack void operator=(Core const&); // Don't implement // report error to user while failing - void fatal (std::string output, bool will_deactivate); + void fatal (std::string output); // 1 = fatal failure bool errorstate; diff --git a/library/include/LuaTools.h b/library/include/LuaTools.h index 9121660ec..0a1c4ccaa 100644 --- a/library/include/LuaTools.h +++ b/library/include/LuaTools.h @@ -380,7 +380,7 @@ namespace DFHack {namespace Lua { DFHACK_EXPORT extern lua_State *State; // Not exported; for use by the Core class - void Init(color_ostream &out); + bool Init(color_ostream &out); void Reset(color_ostream &out, const char *where); // Events signalled by the core diff --git a/plugins/dwarfmonitor.cpp b/plugins/dwarfmonitor.cpp index 216664a93..ca61ddb2e 100644 --- a/plugins/dwarfmonitor.cpp +++ b/plugins/dwarfmonitor.cpp @@ -1977,6 +1977,8 @@ DFhackCExport command_result plugin_init(color_ostream &out, std::vector Date: Sun, 18 Oct 2015 13:08:48 -0400 Subject: [PATCH 05/13] Make buildingplan-lib a static library This avoids building buildingplan-lib.cpp multiple times --- plugins/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 4b37095f1..80ad381d8 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -79,6 +79,8 @@ add_custom_target(generate_proto DEPENDS ${PROJECT_PROTO_SRCS} ${PROJECT_PROTO_H SET_SOURCE_FILES_PROPERTIES( Brushes.h PROPERTIES HEADER_FILE_ONLY TRUE ) +ADD_LIBRARY(buildingplan-lib STATIC buildingplan-lib.cpp) + # Plugins OPTION(BUILD_SUPPORTED "Build the supported plugins (reveal, probe, etc.)." ON) if (BUILD_SUPPORTED) @@ -95,7 +97,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(blueprint blueprint.cpp) DFHACK_PLUGIN(burrows burrows.cpp LINK_LIBRARIES lua) DFHACK_PLUGIN(building-hacks building-hacks.cpp LINK_LIBRARIES lua) - DFHACK_PLUGIN(buildingplan buildingplan-lib.cpp buildingplan.cpp) + DFHACK_PLUGIN(buildingplan buildingplan.cpp LINK_LIBRARIES buildingplan-lib) DFHACK_PLUGIN(catsplosion catsplosion.cpp) DFHACK_PLUGIN(changeitem changeitem.cpp) DFHACK_PLUGIN(changelayer changelayer.cpp) @@ -126,7 +128,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(flows flows.cpp) DFHACK_PLUGIN(follow follow.cpp) DFHACK_PLUGIN(forceequip forceequip.cpp) - DFHACK_PLUGIN(fortplan buildingplan-lib.cpp fortplan.cpp) + DFHACK_PLUGIN(fortplan fortplan.cpp LINK_LIBRARIES buildingplan-lib) DFHACK_PLUGIN(getplants getplants.cpp) DFHACK_PLUGIN(hotkeys hotkeys.cpp) DFHACK_PLUGIN(infiniteSky infiniteSky.cpp) From 757c05db862bfe422fb48bccd77e37e3942c32fa Mon Sep 17 00:00:00 2001 From: lethosor Date: Sun, 18 Oct 2015 17:46:37 -0400 Subject: [PATCH 06/13] buildingplan-lib: depend on dfhack --- plugins/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 80ad381d8..0cb8b6df2 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -80,6 +80,7 @@ add_custom_target(generate_proto DEPENDS ${PROJECT_PROTO_SRCS} ${PROJECT_PROTO_H SET_SOURCE_FILES_PROPERTIES( Brushes.h PROPERTIES HEADER_FILE_ONLY TRUE ) ADD_LIBRARY(buildingplan-lib STATIC buildingplan-lib.cpp) +TARGET_LINK_LIBRARIES(buildingplan-lib dfhack) # Plugins OPTION(BUILD_SUPPORTED "Build the supported plugins (reveal, probe, etc.)." ON) From 5fbb950bc2e1922c6ee3de3f1c3e02508a0c0fbc Mon Sep 17 00:00:00 2001 From: Warmist Date: Mon, 19 Oct 2015 18:42:15 +0300 Subject: [PATCH 07/13] Fix gm-editor to work with df.global structs It was broken because df.global is not a real struct and does not have ._field at all. --- scripts/gui/gm-editor.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/gui/gm-editor.lua b/scripts/gui/gm-editor.lua index 0743e1907..817c56138 100644 --- a/scripts/gui/gm-editor.lua +++ b/scripts/gui/gm-editor.lua @@ -173,8 +173,14 @@ end function GmEditorUi:getSelectedEnumType() local trg=self:currentTarget() local trg_key=trg.keys[self.subviews.list_main:getSelected()] - if trg.target._field==nil then return nil end - if trg.target:_field(trg_key)==nil then return nil end + + local ok,ret=pcall(function () --super safe way to check if the field has enum + return trg.target._field==nil or trg.target:_field(trg_key)==nil + end) + if not ok or ret==true then + return nil + end + local enum=trg.target:_field(trg_key)._type if enum._kind=="enum-type" then return enum From 8de710f1c1449c010e6c29b948c5681cda8ca6b7 Mon Sep 17 00:00:00 2001 From: lethosor Date: Fri, 28 Aug 2015 16:21:11 -0400 Subject: [PATCH 08/13] Add Renderer module - safer way to install custom renderers --- library/CMakeLists.txt | 2 + library/include/modules/Renderer.h | 38 +++++++ library/modules/Renderer.cpp | 156 +++++++++++++++++++++++++++++ plugins/devel/CMakeLists.txt | 1 + plugins/devel/renderer-msg.cpp | 58 +++++++++++ 5 files changed, 255 insertions(+) create mode 100644 library/include/modules/Renderer.h create mode 100644 library/modules/Renderer.cpp create mode 100644 plugins/devel/renderer-msg.cpp diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index fc0b91e0f..3cd415780 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -127,6 +127,7 @@ include/modules/MapCache.h include/modules/Materials.h include/modules/Notes.h include/modules/Random.h +include/modules/Renderer.h include/modules/Screen.h include/modules/Translation.h include/modules/Vermin.h @@ -152,6 +153,7 @@ modules/Maps.cpp modules/Materials.cpp modules/Notes.cpp modules/Random.cpp +modules/Renderer.cpp modules/Screen.cpp modules/Translation.cpp modules/Vermin.cpp diff --git a/library/include/modules/Renderer.h b/library/include/modules/Renderer.h new file mode 100644 index 000000000..11abd7c1d --- /dev/null +++ b/library/include/modules/Renderer.h @@ -0,0 +1,38 @@ +#include "Export.h" +#include "df/enabler.h" +#include "df/graphic.h" +#include "df/renderer.h" +#pragma once + +namespace DFHack { namespace Renderer { + struct DFHACK_EXPORT renderer_wrap : public df::renderer { + void set_to_null(); + void copy_from_parent(); + void copy_to_parent(); + renderer_wrap *parent; + renderer_wrap *child; + + virtual void update_tile(int32_t x, int32_t y); + virtual void update_all(); + virtual void render(); + virtual void set_fullscreen(); + virtual void zoom(df::zoom_commands z); + virtual void resize(int32_t w, int32_t h); + virtual void grid_resize(int32_t w, int32_t h); + virtual ~renderer_wrap() { + // All necessary cleanup should be handled by RemoveRenderer() + }; + virtual bool get_mouse_coords(int32_t *x, int32_t *y); + virtual bool uses_opengl(); + }; + // Returns the renderer instance given on success, or deletes it and returns NULL on failure + // Usage: renderer_foo *r = AddRenderer(new renderer_foo) + DFHACK_EXPORT renderer_wrap *AddRenderer(renderer_wrap*, bool refresh_screen = false); + // Removes and deletes the given renderer instance + DFHACK_EXPORT void RemoveRenderer(renderer_wrap*); + DFHACK_EXPORT bool RendererExists(renderer_wrap*); + inline renderer_wrap *GetRenderer() + { + return (renderer_wrap*)(df::global::enabler ? df::global::enabler->renderer : NULL); + } +}} diff --git a/library/modules/Renderer.cpp b/library/modules/Renderer.cpp new file mode 100644 index 000000000..474dc3656 --- /dev/null +++ b/library/modules/Renderer.cpp @@ -0,0 +1,156 @@ +#include "DataDefs.h" +#include "MiscUtils.h" +#include "modules/Renderer.h" + +using namespace DFHack; +using df::global::enabler; +using df::global::gps; +using DFHack::Renderer::renderer_wrap; + +static renderer_wrap *original_renderer = NULL; + +bool init() +{ + if (!original_renderer) + original_renderer = Renderer::GetRenderer(); + return original_renderer; +} + +renderer_wrap *Renderer::AddRenderer (renderer_wrap *r, bool refresh_screen) +{ + if (!init()) + { + delete r; + return NULL; + } + renderer_wrap *cur = GetRenderer(); + r->parent = cur; + r->child = NULL; + r->copy_from_parent(); + if (cur != original_renderer) + { + cur->child = original_renderer; + } + r->copy_from_parent(); + enabler->renderer = r; + if (refresh_screen && gps) + gps->force_full_display_count++; + return r; +} + +void Renderer::RemoveRenderer (renderer_wrap *r) +{ + if (r) + { + if (original_renderer) + { + r->parent->child = r->child; + if (r->child) + { + r->child->parent = r->parent; + } + enabler->renderer = r->parent; + } + delete r; + } +} + +bool Renderer::RendererExists (renderer_wrap *r) +{ + renderer_wrap *cur = GetRenderer(); + while (cur && cur != r && cur != original_renderer) + cur = cur->parent; + return cur == r; +} + +void Renderer::renderer_wrap::set_to_null() { + screen = NULL; + screentexpos = NULL; + screentexpos_addcolor = NULL; + screentexpos_grayscale = NULL; + screentexpos_cf = NULL; + screentexpos_cbr = NULL; + screen_old = NULL; + screentexpos_old = NULL; + screentexpos_addcolor_old = NULL; + screentexpos_grayscale_old = NULL; + screentexpos_cf_old = NULL; + screentexpos_cbr_old = NULL; +} + +void Renderer::renderer_wrap::copy_from_parent() { + screen = parent->screen; + screentexpos = parent->screentexpos; + screentexpos_addcolor = parent->screentexpos_addcolor; + screentexpos_grayscale = parent->screentexpos_grayscale; + screentexpos_cf = parent->screentexpos_cf; + screentexpos_cbr = parent->screentexpos_cbr; + screen_old = parent->screen_old; + screentexpos_old = parent->screentexpos_old; + screentexpos_addcolor_old = parent->screentexpos_addcolor_old; + screentexpos_grayscale_old = parent->screentexpos_grayscale_old; + screentexpos_cf_old = parent->screentexpos_cf_old; + screentexpos_cbr_old = parent->screentexpos_cbr_old; +} + +void Renderer::renderer_wrap::copy_to_parent() { + parent->screen = screen; + parent->screentexpos = screentexpos; + parent->screentexpos_addcolor = screentexpos_addcolor; + parent->screentexpos_grayscale = screentexpos_grayscale; + parent->screentexpos_cf = screentexpos_cf; + parent->screentexpos_cbr = screentexpos_cbr; + parent->screen_old = screen_old; + parent->screentexpos_old = screentexpos_old; + parent->screentexpos_addcolor_old = screentexpos_addcolor_old; + parent->screentexpos_grayscale_old = screentexpos_grayscale_old; + parent->screentexpos_cf_old = screentexpos_cf_old; + parent->screentexpos_cbr_old = screentexpos_cbr_old; +} + +void Renderer::renderer_wrap::update_tile(int32_t x, int32_t y) { + copy_to_parent(); + parent->update_tile(x,y); +}; + +void Renderer::renderer_wrap::update_all() { + copy_to_parent(); + parent->update_all(); +}; + +void Renderer::renderer_wrap::render() { + copy_to_parent(); + parent->render(); +}; + +void Renderer::renderer_wrap::set_fullscreen() { + copy_to_parent(); + parent->set_fullscreen(); + copy_from_parent(); +}; + +void Renderer::renderer_wrap::zoom(df::zoom_commands z) { + copy_to_parent(); + parent->zoom(z); + copy_from_parent(); +}; + +void Renderer::renderer_wrap::resize(int32_t w, int32_t h) { + copy_to_parent(); + parent->resize(w,h); + copy_from_parent(); +}; + +void Renderer::renderer_wrap::grid_resize(int32_t w, int32_t h) { + copy_to_parent(); + parent->grid_resize(w,h); + copy_from_parent(); +}; + +bool Renderer::renderer_wrap::get_mouse_coords(int32_t* x, int32_t* y) { + return parent->get_mouse_coords(x,y); +}; + +bool Renderer::renderer_wrap::uses_opengl() { + return parent->uses_opengl(); +}; diff --git a/plugins/devel/CMakeLists.txt b/plugins/devel/CMakeLists.txt index 74c198645..79bf55ff6 100644 --- a/plugins/devel/CMakeLists.txt +++ b/plugins/devel/CMakeLists.txt @@ -14,6 +14,7 @@ DFHACK_PLUGIN(memview memview.cpp) DFHACK_PLUGIN(nestboxes nestboxes.cpp) DFHACK_PLUGIN(notes notes.cpp) DFHACK_PLUGIN(onceExample onceExample.cpp) +DFHACK_PLUGIN(renderer-msg renderer-msg.cpp) DFHACK_PLUGIN(rprobe rprobe.cpp) DFHACK_PLUGIN(stepBetween stepBetween.cpp) DFHACK_PLUGIN(stockcheck stockcheck.cpp) diff --git a/plugins/devel/renderer-msg.cpp b/plugins/devel/renderer-msg.cpp new file mode 100644 index 000000000..a2143d137 --- /dev/null +++ b/plugins/devel/renderer-msg.cpp @@ -0,0 +1,58 @@ +#include "Console.h" +#include "Core.h" +#include "DataDefs.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Screen.h" +#include "modules/Renderer.h" + +#include "df/enabler.h" +#include "df/renderer.h" + +//#include "df/world.h" + +using namespace DFHack; + +DFHACK_PLUGIN("renderer-msg"); +DFHACK_PLUGIN_IS_ENABLED(is_enabled); +REQUIRE_GLOBAL(enabler); +REQUIRE_GLOBAL(gps); + +struct scdata { + uint8_t ch, fg, bg, bold; +}; + +struct renderer_msg : public Renderer::renderer_wrap { + virtual void update_tile (int32_t x, int32_t y) { + static std::string str = std::string("DFHack: ") + plugin_name + " active"; + Screen::paintString(Screen::Pen(' ', 9, 0), 0, gps->dimy - 1, str); + for (size_t i = 0; i < gps->dimx; ++i) + ((scdata*)screen)[i * gps->dimy + gps->dimy - 1].bg = 2; + renderer_wrap::update_tile(x, y); + }; +}; + +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) +{ + return CR_OK; +} + +static Renderer::renderer_wrap *w = NULL; +DFhackCExport command_result plugin_enable (color_ostream &out, bool enable) +{ + if (is_enabled == enable) + return CR_OK; + CoreSuspender s; + is_enabled = enable; + if (enable) + w = Renderer::AddRenderer(new renderer_msg, true); + else + Renderer::RemoveRenderer(w); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown (color_ostream &out) +{ + plugin_enable(out, false); + return plugin_enable(out, false); +} From daf20c16bdf02d2ef03764585666b90d9be388e6 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 24 Oct 2015 14:52:00 -0400 Subject: [PATCH 09/13] Indicate development builds --- plugins/title-version.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/title-version.cpp b/plugins/title-version.cpp index c52a7a9f5..c62568f1e 100644 --- a/plugins/title-version.cpp +++ b/plugins/title-version.cpp @@ -33,6 +33,8 @@ struct title_version_hook : df::viewscreen_titlest { INTERPOSE_NEXT(render)(); int x = 0, y = 0; OutputString(COLOR_WHITE, x, y, string("DFHack ") + DFHACK_VERSION); + if (!DFHACK_IS_RELEASE) + OutputString(COLOR_WHITE, x, y, " (dev)"); } }; From 7dd091e57a0ed05a6f53e06856eee631b2d92ee9 Mon Sep 17 00:00:00 2001 From: lethosor Date: Mon, 26 Oct 2015 21:02:03 -0400 Subject: [PATCH 10/13] create-unit: add nickname option --- scripts/modtools/create-unit.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/modtools/create-unit.lua b/scripts/modtools/create-unit.lua index 948b94486..22a4dee9d 100644 --- a/scripts/modtools/create-unit.lua +++ b/scripts/modtools/create-unit.lua @@ -103,7 +103,7 @@ function createFigure(trgunit,he,he_group) hf.sex = trgunit.sex df.global.hist_figure_next_id=df.global.hist_figure_next_id+1 hf.appeared_year = df.global.cur_year - + hf.born_year = trgunit.relations.birth_year hf.born_seconds = trgunit.relations.birth_time hf.curse_year = trgunit.relations.curse_year @@ -330,6 +330,7 @@ validArgs = --[[validArgs or]]utils.invert({ 'flagSet', 'flagClear', 'name', + 'nick', 'location', 'age' }) @@ -369,6 +370,8 @@ arguments: set the unit's name to be a random name appropriate for the given entity examples: MOUNTAIN + -nick nickname + set the unit's nickname directly -location [ x y z ] create the unit at the specified coordinates -age howOld @@ -505,6 +508,10 @@ else end--]] end +if args.nick and type(args.nick) == 'string' then + dfhack.units.setNickname(df.unit.find(unitId), args.nick) +end + if civ_id then local u = df.unit.find(unitId) u.civ_id = civ_id From 74860e2904d36f0bb7ea4f7fe54699677a60d1e8 Mon Sep 17 00:00:00 2001 From: lethosor Date: Mon, 26 Oct 2015 21:02:38 -0400 Subject: [PATCH 11/13] Add spawnunit wrapper See #716 --- scripts/spawnunit.lua | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 scripts/spawnunit.lua diff --git a/scripts/spawnunit.lua b/scripts/spawnunit.lua new file mode 100644 index 000000000..1c2964936 --- /dev/null +++ b/scripts/spawnunit.lua @@ -0,0 +1,57 @@ +-- create unit at pointer or given location +-- wraps modtools/create-unit.lua + +usage = [[Usage: +- spawnunit RACE CASTE +- spawnunit RACE CASTE NAME +- spawnunit RACE CASTE NAME x y z +- spawnunit RACE CASTE [NAME] [additional arguments] + Create a unit +- spawnunit -help + Display this help message +- spawnunit -command ARGUMENTS + Display the command used to invoke modtools/create-unit + +additional arguments are passed to modtools/create-unit - +see "modtools/create-unit -help" for more information. +]] + +function extend(tbl, tbl2) + for _, v in pairs(tbl2) do + table.insert(tbl, v) + end +end + +local show_command = false +local args = {...} +local first_arg = (args[1] or ''):gsub('^-*', '') +if first_arg == 'help' or #args < 2 then + print(usage) + return +elseif first_arg == 'command' then + show_command = true + table.remove(args, 1) +end + +local new_args = {'-race', args[1], '-caste', args[2]} +if #args == 3 then + extend(new_args, {'-nick', args[3]}) +elseif #args == 6 then + if tonumber(args[4]) and tonumber(args[5]) and tonumber(args[6]) then + extend(new_args, {'-nick', args[3], '-location', '[', args[4], args[5], args[6], ']'}) + end +else + local start = 3 + if #args >= 3 and args[3]:sub(1, 1) ~= '-' then + extend(new_args, {'-nick', args[3]}) + start = 4 + end + for i = start, #args do + table.insert(new_args, args[i]) + end +end +if show_command then + print('modtools/create-unit ' .. table.concat(new_args, ' ')) + return +end +dfhack.run_script('modtools/create-unit', table.unpack(new_args)) From d58c9019be71c73a7d6b1e8296466df14d1a5542 Mon Sep 17 00:00:00 2001 From: lethosor Date: Tue, 27 Oct 2015 17:33:51 -0400 Subject: [PATCH 12/13] alias migrants-now -> devel/migrants-now --- scripts/migrants-now.lua | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 scripts/migrants-now.lua diff --git a/scripts/migrants-now.lua b/scripts/migrants-now.lua new file mode 100644 index 000000000..22719be19 --- /dev/null +++ b/scripts/migrants-now.lua @@ -0,0 +1,2 @@ +-- Force a migrant wave (only works after hardcoded waves) +--@alias = 'devel/migrants-now' From 1250bb52041cd35d06b8d72a2c9a207a8634e0a5 Mon Sep 17 00:00:00 2001 From: lethosor Date: Tue, 27 Oct 2015 17:34:32 -0400 Subject: [PATCH 13/13] type: Provide more useful information (script paths, plugin names) --- library/Core.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/library/Core.cpp b/library/Core.cpp index 6fdf65a09..ea3eca5f8 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -919,29 +919,34 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v } con << parts[0]; string builtin_cmd = getBuiltinCommand(parts[0]); + string lua_path = findScript(parts[0] + ".lua"); + string ruby_path = findScript(parts[0] + ".rb"); Plugin *plug = plug_mgr->getPluginByCommand(parts[0]); if (builtin_cmd.size()) { con << " is a built-in command"; if (builtin_cmd != parts[0]) con << " (aliased to " << builtin_cmd << ")"; - con << "." << std::endl; + con << std::endl; } else if (plug) { - con << " is part of plugin " << plug->getName() << "." << std::endl; + con << " is a command implemented by the plugin " << plug->getName() << std::endl; } - else if (findScript(parts[0] + ".lua").size()) + else if (lua_path.size()) { - con << " is a Lua script." << std::endl; + con << " is a Lua script: " << lua_path << std::endl; } - else if (findScript(parts[0] + ".rb").size()) + else if (ruby_path.size()) { - con << " is a Ruby script." << std::endl; + con << " is a Ruby script: " << ruby_path << std::endl; } else { - con << " is not recognized." << std::endl; + con << " is not a recognized command." << std::endl; + plug = plug_mgr->getPluginByName(parts[0]); + if (plug) + con << "Plugin " << parts[0] << " exists and implements " << plug->size() << " commands." << std::endl; return CR_FAILURE; } }