diff --git a/.gitmodules b/.gitmodules index 5fcc3ec0d..76fb139db 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "plugins/df2mc"] path = plugins/df2mc url = git://github.com/peterix/DF2MC.git +[submodule "library/xml"] + path = library/xml + url = git://github.com/peterix/df-structures.git diff --git a/COMPILE.rst b/COMPILE.rst index ab6debd78..175060060 100644 --- a/COMPILE.rst +++ b/COMPILE.rst @@ -19,8 +19,8 @@ a 64-bit distribution like Arch, you'll need the multilib development tools and Before you can build anything, you'll also need ``cmake``. It is advisable to also get ``ccmake`` on distributions that split the cmake package into multiple parts. -For the code generation parts, you need perl and the XML::LibXML perl package. -You should be able to find them in your distro repositories (on Arch linux 'perl-xml-libxml'). +For the code generation parts, you need perl and the XML::LibXML and XML::LibXSLT perl packages. +You should be able to find them in your distro repositories (on Arch linux 'perl-xml-libxml' and 'perl-xml-libxslt'). Build ===== @@ -58,9 +58,11 @@ You'll need a copy of Microsoft Visual C++ 2010. The Express version is sufficie Grab it from Microsoft's site. For the code generation parts, you'll need perl and XML::LibXML. You can install them like this: + * download and install strawberry perl from http://strawberryperl.com/ * reboot so that the system can pick up the new binary path * open a cmd.exe window and run "cpan XML::LibXML" (obviously without the quotes). This can take a while to complete. +* Same with "cpan XML::LibXSLT". Build ===== diff --git a/Compile.html b/Compile.html index 95847f4f4..35e4ff3e6 100644 --- a/Compile.html +++ b/Compile.html @@ -351,8 +351,8 @@ ul.auto-toc { a 64-bit distribution like Arch, you'll need the multilib development tools and libraries.

Before you can build anything, you'll also need cmake. It is advisable to also get ccmake on distributions that split the cmake package into multiple parts.

-

For the code generation parts, you need perl and the XML::LibXML perl package. -You should be able to find them in your distro repositories (on Arch linux 'perl-xml-libxml').

+

For the code generation parts, you need perl and the XML::LibXML and XML::LibXSLT perl packages. +You should be able to find them in your distro repositories (on Arch linux 'perl-xml-libxml' and 'perl-xml-libxslt').

Build

@@ -384,10 +384,13 @@ site: +
  • download and install strawberry perl from http://strawberryperl.com/
  • +
  • reboot so that the system can pick up the new binary path
  • +
  • open a cmd.exe window and run "cpan XML::LibXML" (obviously without the quotes). This can take a while to complete.
  • +
  • Same with "cpan XML::LibXSLT".
  • +

    Build

    Open the build folder and double click the batch script there. This will eventually open diff --git a/Memory.xml b/Memory.xml index b4f7ce1f3..62f20f9ab 100644 --- a/Memory.xml +++ b/Memory.xml @@ -1078,12 +1078,23 @@

    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    @@ -2316,12 +2327,27 @@
    + + + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    cmake @@ -3188,12 +3214,27 @@
    + + + +
    +
    +
    + +
    +
    +
    + +
    +
    + +
    diff --git a/build/.gitignore b/build/.gitignore index 474fe987c..990de1678 100644 --- a/build/.gitignore +++ b/build/.gitignore @@ -1 +1,2 @@ -build-real \ No newline at end of file +VC2010 +DF_PATH.txt diff --git a/build/build-debug.bat b/build/build-debug.bat new file mode 100644 index 000000000..a9492de13 --- /dev/null +++ b/build/build-debug.bat @@ -0,0 +1,4 @@ +call "%VS100COMNTOOLS%vsvars32.bat" +cd VC2010 +msbuild /m /p:Platform=Win32 /p:Configuration=RelWithDebInfo ALL_BUILD.vcxproj +cd .. \ No newline at end of file diff --git a/build/build-release.bat b/build/build-release.bat new file mode 100644 index 000000000..e1ad315e5 --- /dev/null +++ b/build/build-release.bat @@ -0,0 +1,5 @@ +call "%VS100COMNTOOLS%vsvars32.bat" +cd VC2010 +msbuild /m /p:Platform=Win32 /p:Configuration=Release ALL_BUILD.vcxproj +cd .. +pause \ No newline at end of file diff --git a/build/generate-MSVC-2010.bat b/build/generate-MSVC-2010.bat deleted file mode 100644 index 00c990083..000000000 --- a/build/generate-MSVC-2010.bat +++ /dev/null @@ -1,5 +0,0 @@ -mkdir VC2010 -cd VC2010 -echo Pre-generating a build folder -cmake ..\.. -G"Visual Studio 10" -cmake-gui . \ No newline at end of file diff --git a/build/generate-MSVC-all.bat b/build/generate-MSVC-all.bat new file mode 100644 index 000000000..686ec3bcf --- /dev/null +++ b/build/generate-MSVC-all.bat @@ -0,0 +1,6 @@ +IF EXIST DF_PATH.txt SET /P _DF_PATH= 0 Then + Set spoFile = fso.CreateTextFile("DF_PATH.txt", True) + spoFile.WriteLine(objF.Self.Path) + End If +End If + +Function IsValue(obj) + ' Check whether the value has been returned. + Dim tmp + On Error Resume Next + tmp = " " & obj + If Err <> 0 Then + IsValue = False + Else + IsValue = True + End If + On Error GoTo 0 +End Function \ No newline at end of file diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 9a87db9af..808c13a18 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -13,60 +13,59 @@ include_directories (include) include_directories (depends/md5) include_directories (depends/tinyxml) include_directories (depends/tthread) -include_directories (private) -execute_process(COMMAND perl xml/list.pl xml include/dfhack/df ";" +execute_process(COMMAND perl xml/list.pl xml include/df ";" WORKING_DIRECTORY ${dfapi_SOURCE_DIR} OUTPUT_VARIABLE GENERATED_HDRS) SET(PROJECT_HDRS_INTERNAL - private/ContextShared.h - private/Internal.h - private/wdirent.h ) SET(PROJECT_HDRS +include/Internal.h include/DFHack.h -include/dfhack/Console.h -include/dfhack/Core.h -include/dfhack/DataDefs.h -include/dfhack/Error.h -include/dfhack/Export.h -include/dfhack/FakeSDL.h -include/dfhack/MiscUtils.h -include/dfhack/Module.h -include/dfhack/Pragma.h -include/dfhack/Process.h -include/dfhack/TileTypes.h -include/dfhack/Types.h -include/dfhack/Vector.h -include/dfhack/VersionInfo.h -include/dfhack/VersionInfoFactory.h -include/dfhack/Virtual.h -include/dfhack/extra/MapExtras.h -include/dfhack/extra/stopwatch.h -include/dfhack/extra/termutil.h -include/dfhack/modules/Buildings.h -include/dfhack/modules/Constructions.h -include/dfhack/modules/Units.h -include/dfhack/modules/Engravings.h -include/dfhack/modules/Gui.h -include/dfhack/modules/Items.h -include/dfhack/modules/kitchen.h -include/dfhack/modules/Maps.h -include/dfhack/modules/Materials.h -include/dfhack/modules/Notes.h -include/dfhack/modules/Translation.h -include/dfhack/modules/Vegetation.h -include/dfhack/modules/Vermin.h -include/dfhack/modules/World.h -include/dfhack/modules/Graphic.h +include/Console.h +include/Core.h +include/DataDefs.h +include/Error.h +include/Export.h +include/Hooks.h +include/MiscUtils.h +include/Module.h +include/Pragma.h +include/MemAccess.h +include/SDL_events.h +include/SDL_keyboard.h +include/SDL_keysym.h +include/TileTypes.h +include/Types.h +include/VersionInfo.h +include/VersionInfoFactory.h +include/Virtual.h +include/modules/Buildings.h +include/modules/Constructions.h +include/modules/Units.h +include/modules/Engravings.h +include/modules/Gui.h +include/modules/Items.h +include/modules/kitchen.h +include/modules/Maps.h +include/modules/MapCache.h +include/modules/Materials.h +include/modules/Notes.h +include/modules/Translation.h +include/modules/Vegetation.h +include/modules/Vermin.h +include/modules/World.h +include/modules/Graphic.h ) SET(PROJECT_SRCS Core.cpp DataDefs.cpp DataStatics.cpp +DataStaticsCtor.cpp +MiscUtils.cpp PluginManager.cpp TileTypes.cpp VersionInfo.cpp @@ -104,17 +103,18 @@ SET(PROJECT_HDRS_LINUX ) SET(PROJECT_HDRS_WINDOWS +include/wdirent.h ) SET(PROJECT_SRCS_LINUX Console-linux.cpp -FakeSDL-linux.cpp +Hooks-linux.cpp Process-linux.cpp ) SET(PROJECT_SRCS_WINDOWS Console-windows.cpp -FakeSDL-windows.cpp +Hooks-windows.cpp Process-windows.cpp ) @@ -134,17 +134,18 @@ LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS}) SET_SOURCE_FILES_PROPERTIES(${GENERATED_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE GENERATED TRUE) +FILE(GLOB GENERATE_INPUT_SCRIPTS ${dfapi_SOURCE_DIR}/xml/*.pm ${dfapi_SOURCE_DIR}/xml/*.xslt) FILE(GLOB GENERATE_INPUT_XMLS ${dfapi_SOURCE_DIR}/xml/*.xml) ADD_CUSTOM_COMMAND( - OUTPUT ${dfapi_SOURCE_DIR}/include/dfhack/df/static.inc - COMMAND perl xml/codegen.pl xml include/dfhack/df + OUTPUT ${dfapi_SOURCE_DIR}/include/df/static.inc + COMMAND perl xml/codegen.pl xml include/df WORKING_DIRECTORY ${dfapi_SOURCE_DIR} MAIN_DEPENDENCY ${dfapi_SOURCE_DIR}/xml/codegen.pl - DEPENDS ${GENERATE_INPUT_XMLS} + DEPENDS ${GENERATE_INPUT_XMLS} ${GENERATE_INPUT_SCRIPTS} ) -ADD_CUSTOM_TARGET(generate_headers DEPENDS ${dfapi_SOURCE_DIR}/include/dfhack/df/static.inc) +ADD_CUSTOM_TARGET(generate_headers DEPENDS ${dfapi_SOURCE_DIR}/include/df/static.inc) # Compilation diff --git a/library/Console-linux.cpp b/library/Console-linux.cpp index e15a6e9cb..c1bea16d6 100644 --- a/library/Console-linux.cpp +++ b/library/Console-linux.cpp @@ -61,8 +61,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include "dfhack/Console.h" -#include "dfhack/FakeSDL.h" +#include "Console.h" +#include "Hooks.h" using namespace DFHack; #include "tinythread.h" diff --git a/library/Console-windows.cpp b/library/Console-windows.cpp index 4daab5c2f..de2c2aca8 100644 --- a/library/Console-windows.cpp +++ b/library/Console-windows.cpp @@ -50,8 +50,8 @@ POSSIBILITY OF SUCH DAMAGE. #include #include -#include "dfhack/Console.h" -#include "dfhack/FakeSDL.h" +#include "Console.h" +#include "Hooks.h" #include #include #include diff --git a/library/Core.cpp b/library/Core.cpp index 5296a057e..4a3dacd25 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -34,30 +34,37 @@ distribution. #include using namespace std; -#include "dfhack/Error.h" -#include "dfhack/Process.h" -#include "dfhack/Core.h" -#include "dfhack/DataDefs.h" -#include "dfhack/Console.h" -#include "dfhack/Module.h" -#include "dfhack/VersionInfoFactory.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/PluginManager.h" +#include "Error.h" +#include "MemAccess.h" +#include "Core.h" +#include "DataDefs.h" +#include "Console.h" +#include "Module.h" +#include "VersionInfoFactory.h" +#include "VersionInfo.h" +#include "PluginManager.h" #include "ModuleFactory.h" -#include "dfhack/modules/Gui.h" -#include "dfhack/modules/World.h" -#include "dfhack/modules/Graphic.h" +#include "modules/Gui.h" +#include "modules/World.h" +#include "modules/Graphic.h" using namespace DFHack; -#include "dfhack/SDL_fakes/events.h" +#include "SDL_events.h" + +#include "df/ui.h" +#include "df/world.h" +#include "df/world_data.h" +#include "df/interface.h" +#include "df/viewscreen_dwarfmodest.h" #include #include #include #include #include "tinythread.h" -using namespace tthread; +using namespace tthread; +using namespace df::enums; struct Core::Cond { @@ -91,9 +98,35 @@ struct Core::Cond void cheap_tokenise(string const& input, vector &output) { - istringstream str(input); - istream_iterator cur(str), end; - output.assign(cur, end); + string *cur = NULL; + + for (unsigned i = 0; i < input.size(); i++) { + char c = input[i]; + if (isspace(c)) { + cur = NULL; + } else { + if (!cur) { + output.push_back(""); + cur = &output.back(); + } + + if (c == '"') { + for (i++; i < input.size(); i++) { + c = input[i]; + if (c == '"') + break; + else if (c == '\\') { + if (++i < input.size()) + cur->push_back(input[i]); + } + else + cur->push_back(c); + } + } else { + cur->push_back(c); + } + } + } } struct IODATA @@ -119,8 +152,17 @@ void fHKthread(void * iodata) std::string stuff = core->getHotkeyCmd(); // waits on mutex! if(!stuff.empty()) { - vector crap; - command_result cr = plug_mgr->InvokeCommand(stuff, crap, false); + vector args; + cheap_tokenise(stuff, args); + if (args.empty()) { + core->con.printerr("Empty hotkey command.\n"); + continue; + } + + string first = args[0]; + args.erase(args.begin()); + command_result cr = plug_mgr->InvokeCommand(first, args, false); + if(cr == CR_WOULD_BREAK) { core->con.printerr("It isn't possible to run an interactive command outside the console.\n"); @@ -129,53 +171,25 @@ void fHKthread(void * iodata) } } -// A thread function... for the interactive console. -void fIOthread(void * iodata) +static void runInteractiveCommand(Core *core, PluginManager *plug_mgr, int &clueless_counter, const string &command) { - IODATA * iod = ((IODATA*) iodata); - Core * core = iod->core; - PluginManager * plug_mgr = ((IODATA*) iodata)->plug_mgr; - CommandHistory main_history; - main_history.load("dfhack.history"); Console & con = core->con; - if(plug_mgr == 0 || core == 0) - { - con.printerr("Something horrible happened in Core's constructor...\n"); - return; - } - con.print("DFHack is ready. Have a nice day!\n" - "Type in '?' or 'help' for general help, 'ls' to see all commands.\n"); - int clueless_counter = 0; - while (true) + + if (!command.empty()) { - string command = ""; - int ret = con.lineedit("[DFHack]# ",command, main_history); - if(ret == -2) - { - cerr << "Console is shutting down properly." << endl; - return; - } - else if(ret == -1) - { - cerr << "Console caught an unspecified error." << endl; - continue; - } - else if(ret) - { - // a proper, non-empty command was entered - main_history.add(command); - main_history.save("dfhack.history"); - } // cut the input into parts vector parts; cheap_tokenise(command,parts); if(parts.size() == 0) { clueless_counter ++; - continue; + return; } string first = parts[0]; parts.erase(parts.begin()); + + if (first[0] == '#') return; + cerr << "Invoking: " << command << endl; // let's see what we actually got @@ -194,6 +208,7 @@ void fIOthread(void * iodata) " cls - Clear the console.\n" " fpause - Force DF to pause.\n" " die - Force DF to close immediately\n" + " keybinding - Modify bindings of commands to keys\n" "Plugin management (useful for developers):\n" //" belongs COMMAND - Tell which plugin a command belongs to.\n" " plug [PLUGIN|v] - List plugin state and description.\n" @@ -202,6 +217,27 @@ void fIOthread(void * iodata) " reload PLUGIN|all - Reload a plugin or all loaded plugins.\n" ); } + else if (parts.size() == 1) + { + Plugin *plug = plug_mgr->getPluginByCommand(parts[0]); + if (plug) { + for (int j = 0; j < plug->size();j++) + { + const PluginCommand & pcmd = (plug->operator[](j)); + if (pcmd.name != parts[0]) + continue; + + if (pcmd.isHotkeyCommand()) + con.color(Console::COLOR_CYAN); + con.print("%s: %s\n",pcmd.name.c_str(), pcmd.description.c_str()); + con.reset_color(); + if (!pcmd.usage.empty()) + con << "Usage:\n" << pcmd.usage << flush; + return; + } + } + con.printerr("Unknown command: %s\n", parts[0].c_str()); + } else { con.printerr("not implemented yet\n"); @@ -301,7 +337,10 @@ void fIOthread(void * iodata) else for (int j = 0; j < plug->size();j++) { const PluginCommand & pcmd = (plug->operator[](j)); + if (pcmd.isHotkeyCommand()) + con.color(Console::COLOR_CYAN); con.print(" %-22s - %s\n",pcmd.name.c_str(), pcmd.description.c_str()); + con.reset_color(); } } else @@ -329,7 +368,10 @@ void fIOthread(void * iodata) for (int j = 0; j < plug->size();j++) { const PluginCommand & pcmd = (plug->operator[](j)); + if (pcmd.isHotkeyCommand()) + con.color(Console::COLOR_CYAN); con.print(" %-22s- %s\n",pcmd.name.c_str(), pcmd.description.c_str()); + con.reset_color(); } } } @@ -344,6 +386,49 @@ void fIOthread(void * iodata) con.print("%s\n", plug->getName().c_str()); } } + else if(first == "keybinding") + { + if (parts.size() >= 3 && (parts[0] == "set" || parts[0] == "add")) + { + std::string keystr = parts[1]; + if (parts[0] == "set") + core->ClearKeyBindings(keystr); + for (int i = parts.size()-1; i >= 2; i--) + { + if (!core->AddKeyBinding(keystr, parts[i])) { + con.printerr("Invalid key spec: %s\n", keystr.c_str()); + break; + } + } + } + else if (parts.size() >= 2 && parts[0] == "clear") + { + for (unsigned i = 1; i < parts.size(); i++) + { + if (!core->ClearKeyBindings(parts[i])) { + con.printerr("Invalid key spec: %s\n", parts[i].c_str()); + break; + } + } + } + else if (parts.size() == 2 && parts[0] == "list") + { + std::vector list = core->ListKeyBindings(parts[1]); + if (list.empty()) + con << "No bindings." << endl; + for (unsigned i = 0; i < list.size(); i++) + con << " " << list[i] << endl; + } + else + { + con << "Usage:" << endl + << " keybinding list " << endl + << " keybinding clear ..." << endl + << " keybinding set \"cmdline\" \"cmdline\"..." << endl + << " keybinding add \"cmdline\" \"cmdline\"..." << endl + << "Later adds, and earlier items within one command have priority." << endl; + } + } else if(first == "fpause") { World * w = core->getWorld(); @@ -384,6 +469,70 @@ void fIOthread(void * iodata) */ } } + } +} + +static void loadInitFile(Core *core, PluginManager *plug_mgr, string fname) +{ + ifstream init(fname); + if (init.bad()) + return; + + int tmp = 0; + string command; + while (getline(init, command)) + { + if (!command.empty()) + runInteractiveCommand(core, plug_mgr, tmp, command); + } +} + +// A thread function... for the interactive console. +void fIOthread(void * iodata) +{ + IODATA * iod = ((IODATA*) iodata); + Core * core = iod->core; + PluginManager * plug_mgr = ((IODATA*) iodata)->plug_mgr; + + CommandHistory main_history; + main_history.load("dfhack.history"); + + Console & con = core->con; + if(plug_mgr == 0 || core == 0) + { + con.printerr("Something horrible happened in Core's constructor...\n"); + return; + } + + loadInitFile(core, plug_mgr, "dfhack.init"); + + con.print("DFHack is ready. Have a nice day!\n" + "Type in '?' or 'help' for general help, 'ls' to see all commands.\n"); + + int clueless_counter = 0; + while (true) + { + string command = ""; + int ret = con.lineedit("[DFHack]# ",command, main_history); + if(ret == -2) + { + cerr << "Console is shutting down properly." << endl; + return; + } + else if(ret == -1) + { + cerr << "Console caught an unspecified error." << endl; + continue; + } + else if(ret) + { + // a proper, non-empty command was entered + main_history.add(command); + main_history.save("dfhack.history"); + } + + runInteractiveCommand(core, plug_mgr, clueless_counter, command); + if(clueless_counter == 3) { con.print("Do 'help' or '?' for the list of available commands.\n"); @@ -408,11 +557,12 @@ Core::Core() StackMutex = 0; core_cond = 0; // set up hotkey capture - memset(hotkey_states,0,sizeof(hotkey_states)); hotkey_set = false; HotkeyMutex = 0; HotkeyCond = 0; misc_data_mutex=0; + last_world_data_ptr = NULL; + top_viewscreen = NULL; }; void Core::fatal (std::string output, bool deactivate) @@ -497,7 +647,7 @@ bool Core::Init() } // initialize data defs - virtual_identity::Init(); + virtual_identity::Init(this); InitDataDefGlobals(this); // create mutex for syncing with interactive tasks @@ -605,8 +755,36 @@ int Core::Update() if(errorstate) return -1; + // detect if the game was loaded or unloaded in the meantime + void *new_wdata = NULL; + if (df::global::world) { + df::world_data *wdata = df::global::world->world_data; + // when the game is unloaded, world_data isn't deleted, but its contents are + if (wdata && !wdata->sites.empty()) + new_wdata = wdata; + } + + if (new_wdata != last_world_data_ptr) { + last_world_data_ptr = new_wdata; + plug_mgr->OnStateChange(new_wdata ? SC_GAME_LOADED : SC_GAME_UNLOADED); + } + + // detect if the viewscreen changed + if (df::global::gview) + { + df::viewscreen *screen = &df::global::gview->view; + while (screen->child) + screen = screen->child; + if (screen != top_viewscreen) + { + top_viewscreen = screen; + plug_mgr->OnStateChange(SC_VIEWSCREEN_CHANGED); + } + } + // notify all the plugins that a game tick is finished plug_mgr->OnUpdate(); + // wake waiting tools // do not allow more tools to join in while we process stuff here StackMutex->lock(); @@ -695,39 +873,168 @@ int Core::SDL_Event(SDL::Event* ev, int orig_return) if(ev && ev->type == SDL::ET_KEYDOWN || ev->type == SDL::ET_KEYUP) { SDL::KeyboardEvent * ke = (SDL::KeyboardEvent *)ev; - bool shift = ke->ksym.mod & SDL::KMOD_SHIFT; - // consuming F1 .. F8 - int idx = ke->ksym.sym - SDL::K_F1; - if(idx < 0 || idx > 7) - return orig_return; - idx += 8*shift; - // now we have the real index... - if(ke->state == SDL::BTN_PRESSED && !hotkey_states[idx]) + + if(ke->state == SDL::BTN_PRESSED && !hotkey_states[ke->ksym.sym]) { - hotkey_states[idx] = 1; - Gui * g = getGui(); - if(g->hotkeys && g->df_interface && g->df_menu_state) - { - t_viewscreen * ws = g->GetCurrentScreen(); - // FIXME: put hardcoded values into memory.xml - if(ws->getClassName() == "viewscreen_dwarfmodest" && *g->df_menu_state == 0x23) - return orig_return; - else - { - t_hotkey & hotkey = (*g->hotkeys)[idx]; - setHotkeyCmd(hotkey.name); - } - } + hotkey_states[ke->ksym.sym] = true; + + int mod = 0; + if (ke->ksym.mod & SDL::KMOD_SHIFT) mod |= 1; + if (ke->ksym.mod & SDL::KMOD_CTRL) mod |= 2; + if (ke->ksym.mod & SDL::KMOD_ALT) mod |= 4; + + SelectHotkey(ke->ksym.sym, mod); } else if(ke->state == SDL::BTN_RELEASED) { - hotkey_states[idx] = 0; + hotkey_states[ke->ksym.sym] = false; } } return orig_return; // do stuff with the events... } +bool Core::SelectHotkey(int sym, int modifiers) +{ + // Find the topmost viewscreen + if (!df::global::gview || !df::global::ui) + return false; + + df::viewscreen *screen = &df::global::gview->view; + while (screen->child) + screen = screen->child; + + std::string cmd; + + { + tthread::lock_guard lock(*HotkeyMutex); + + // Check the internal keybindings + std::vector &bindings = key_bindings[sym]; + for (int i = bindings.size()-1; i >= 0; --i) { + if (bindings[i].modifiers != modifiers) + continue; + if (!plug_mgr->CanInvokeHotkey(bindings[i].command[0], screen)) + continue; + cmd = bindings[i].cmdline; + break; + } + + if (cmd.empty()) { + // Check the hotkey keybindings + int idx = sym - SDL::K_F1; + if(idx >= 0 && idx < 8) + { + if (modifiers & 1) + idx += 8; + + if (strict_virtual_cast(screen) && + df::global::ui->main.mode != ui_sidebar_mode::Hotkeys) + { + cmd = df::global::ui->main.hotkeys[idx].name; + } + } + } + } + + if (!cmd.empty()) { + setHotkeyCmd(cmd); + return true; + } + else + return false; +} + +static bool parseKeySpec(std::string keyspec, int *psym, int *pmod) +{ + *pmod = 0; + + // ugh, ugly + for (;;) { + if (keyspec.size() > 6 && keyspec.substr(0, 6) == "Shift-") { + *pmod |= 1; + keyspec = keyspec.substr(6); + } else if (keyspec.size() > 5 && keyspec.substr(0, 5) == "Ctrl-") { + *pmod |= 2; + keyspec = keyspec.substr(5); + } else if (keyspec.size() > 4 && keyspec.substr(0, 4) == "Alt-") { + *pmod |= 4; + keyspec = keyspec.substr(4); + } else + break; + } + + if (keyspec.size() == 1 && keyspec[0] >= 'A' && keyspec[0] <= 'Z') { + *psym = SDL::K_a + (keyspec[0]-'A'); + return true; + } else if (keyspec.size() == 2 && keyspec[0] == 'F' && keyspec[1] >= '1' && keyspec[1] <= '9') { + *psym = SDL::K_F1 + (keyspec[1]-'1'); + return true; + } else + return false; +} + +bool Core::ClearKeyBindings(std::string keyspec) +{ + int sym, mod; + if (!parseKeySpec(keyspec, &sym, &mod)) + return false; + + tthread::lock_guard lock(*HotkeyMutex); + + std::vector &bindings = key_bindings[sym]; + for (int i = bindings.size()-1; i >= 0; --i) { + if (bindings[i].modifiers == mod) + bindings.erase(bindings.begin()+i); + } + + return true; +} + +bool Core::AddKeyBinding(std::string keyspec, std::string cmdline) +{ + int sym; + KeyBinding binding; + if (!parseKeySpec(keyspec, &sym, &binding.modifiers)) + return false; + + cheap_tokenise(cmdline, binding.command); + if (binding.command.empty()) + return false; + + tthread::lock_guard lock(*HotkeyMutex); + + // Don't add duplicates + std::vector &bindings = key_bindings[sym]; + for (int i = bindings.size()-1; i >= 0; --i) { + if (bindings[i].modifiers == binding.modifiers && + bindings[i].cmdline == cmdline) + return true; + } + + binding.cmdline = cmdline; + bindings.push_back(binding); + return true; +} + +std::vector Core::ListKeyBindings(std::string keyspec) +{ + int sym, mod; + std::vector rv; + if (!parseKeySpec(keyspec, &sym, &mod)) + return rv; + + tthread::lock_guard lock(*HotkeyMutex); + + std::vector &bindings = key_bindings[sym]; + for (int i = bindings.size()-1; i >= 0; --i) { + if (bindings[i].modifiers == mod) + rv.push_back(bindings[i].cmdline); + } + + return rv; +} + //////////////// // ClassNamCheck //////////////// diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp index 2f1f9c238..6c40ec819 100644 --- a/library/DataDefs.cpp +++ b/library/DataDefs.cpp @@ -28,12 +28,14 @@ distribution. #include #include -#include "dfhack/Process.h" -#include "dfhack/Core.h" -#include "dfhack/VersionInfo.h" +#include "MemAccess.h" +#include "Core.h" +#include "VersionInfo.h" #include "tinythread.h" // must be last due to MS stupidity -#include "dfhack/DataDefs.h" +#include "DataDefs.h" + +#include "MiscUtils.h" using namespace DFHack; @@ -78,31 +80,62 @@ virtual_identity *virtual_identity::get(virtual_ptr instance_ptr) for (virtual_identity *p = list; p; p = p->next) { if (strcmp(name.c_str(), p->getOriginalName()) != 0) continue; + + if (p->vtable_ptr && p->vtable_ptr != vtable) { + std::cerr << "Conflicting vtable ptr for class '" << p->getName() + << "': found 0x" << std::hex << unsigned(vtable) + << ", previous 0x" << unsigned(p->vtable_ptr) << std::dec << std::endl; + abort(); + } else if (!p->vtable_ptr) { + std::cerr << "class '" << p->getName() << "': vtable = 0x" + << std::hex << unsigned(vtable) << std::dec << std::endl; + } + known[vtable] = p; p->vtable_ptr = vtable; return p; } + std::cerr << "UNKNOWN CLASS '" << name << "': vtable = 0x" + << std::hex << unsigned(vtable) << std::dec << std::endl; + known[vtable] = NULL; return NULL; } -bool virtual_identity::check_instance(virtual_ptr instance_ptr, bool allow_subclasses) +bool virtual_identity::is_subclass(virtual_identity *actual) { - virtual_identity *actual = get(instance_ptr); - - if (actual == this) return true; - if (!allow_subclasses || !actual) return false; - - do { - actual = actual->parent; + for (; actual; actual = actual->parent) if (actual == this) return true; - } while (actual); return false; } -void virtual_identity::Init() +void virtual_identity::adjust_vtable(virtual_ptr obj, virtual_identity *main) +{ + if (vtable_ptr) { + *(void**)obj = vtable_ptr; + return; + } + + if (main && main != this && is_subclass(main)) + return; + + std::cerr << "Attempt to create class '" << getName() << "' without known vtable." << std::endl; + abort(); +} + +virtual_ptr virtual_identity::clone(virtual_ptr obj) +{ + virtual_identity *id = get(obj); + if (!id) return NULL; + virtual_ptr copy = id->instantiate(); + if (!copy) return NULL; + id->do_copy(copy, obj); + return copy; +} + +void virtual_identity::Init(Core *core) { if (!known_mutex) known_mutex = new tthread::mutex(); @@ -119,19 +152,66 @@ void virtual_identity::Init() p->parent->has_children = true; } } + + // Read pre-filled vtable ptrs + OffsetGroup *ptr_table = core->vinfo->getGroup("vtable"); + for (virtual_identity *p = list; p; p = p->next) { + void * tmp; + if (ptr_table->getSafeAddress(p->getName(),tmp)) + p->vtable_ptr = tmp; + } +} + +std::string DFHack::bitfieldToString(const void *p, int size, const bitfield_item_info *items) +{ + std::string res; + const char *data = (const char*)p; + + for (int i = 0; i < size*8; i++) { + unsigned v; + + if (items[i].size > 1) { + unsigned pdv = *(unsigned*)&data[i/8]; + v = (pdv >> (i%8)) & ((1 << items[i].size)-1); + } else { + v = (data[i/8]>>(i%8)) & 1; + } + + if (v) { + if (!res.empty()) + res += ' '; + + if (items[i].name) + res += items[i].name; + else + res += stl_sprintf("UNK_%d", i); + + if (items[i].size > 1) + res += stl_sprintf("=%u", v); + } + + if (items[i].size > 1) + i += items[i].size-1; + } + + return res; } -#define GLOBAL(name,tname) \ - df::tname *df::global::name = NULL; +#define SIMPLE_GLOBAL(name,tname) \ + tname *df::global::name = NULL; +#define GLOBAL(name,tname) SIMPLE_GLOBAL(name,df::tname) DF_KNOWN_GLOBALS #undef GLOBAL +#undef SIMPLE_GLOBAL void DFHack::InitDataDefGlobals(Core *core) { OffsetGroup *global_table = core->vinfo->getGroup("global"); - uint32_t tmp; + void * tmp; -#define GLOBAL(name,tname) \ - if (global_table->getSafeAddress(#name,tmp)) df::global::name = (df::tname*)tmp; +#define SIMPLE_GLOBAL(name,tname) \ + if (global_table->getSafeAddress(#name,tmp)) df::global::name = (tname*)tmp; +#define GLOBAL(name,tname) SIMPLE_GLOBAL(name,df::tname) DF_KNOWN_GLOBALS #undef GLOBAL +#undef SIMPLE_GLOBAL } diff --git a/library/DataStatics.cpp b/library/DataStatics.cpp index e3a448eac..f47c0fe05 100644 --- a/library/DataStatics.cpp +++ b/library/DataStatics.cpp @@ -1,10 +1,10 @@ #include "Internal.h" -#include "dfhack/DataDefs.h" -#include "dfhack/MiscUtils.h" +#include "DataDefs.h" +#include "MiscUtils.h" -#include "dfhack/df/world.h" -#include "dfhack/df/world_data.h" -#include "dfhack/df/ui.h" +#include "df/world.h" +#include "df/world_data.h" +#include "df/ui.h" namespace { template @@ -14,4 +14,5 @@ namespace { } // Instantiate all the static objects -#include "dfhack/df/static.inc" +#include "df/static.inc" +#include "df/static.enums.inc" diff --git a/library/DataStaticsCtor.cpp b/library/DataStaticsCtor.cpp new file mode 100644 index 000000000..2e4e84baa --- /dev/null +++ b/library/DataStaticsCtor.cpp @@ -0,0 +1,6 @@ +#include "Internal.h" +#include "DataDefs.h" +#include "MiscUtils.h" + +// Object constructors +#include "df/static.ctors.inc" diff --git a/library/FakeSDL-linux.cpp b/library/Hooks-linux.cpp similarity index 98% rename from library/FakeSDL-linux.cpp rename to library/Hooks-linux.cpp index 59ae1bbd4..69bb9f228 100644 --- a/library/FakeSDL-linux.cpp +++ b/library/Hooks-linux.cpp @@ -39,8 +39,8 @@ distribution. #include #include "DFHack.h" -#include "dfhack/Core.h" -#include "dfhack/FakeSDL.h" +#include "Core.h" +#include "Hooks.h" #include /* diff --git a/library/FakeSDL-windows.cpp b/library/Hooks-windows.cpp similarity index 99% rename from library/FakeSDL-windows.cpp rename to library/Hooks-windows.cpp index d388b75d5..51e197722 100644 --- a/library/FakeSDL-windows.cpp +++ b/library/Hooks-windows.cpp @@ -28,12 +28,12 @@ distribution. #include #include #include -#include "dfhack/Core.h" -#include "dfhack/FakeSDL.h" +#include "Core.h" +#include "Hooks.h" #include #include "tinythread.h" -#include "dfhack/modules/Graphic.h" +#include "modules/Graphic.h" /* * Plugin loading functions diff --git a/library/MiscUtils.cpp b/library/MiscUtils.cpp new file mode 100644 index 000000000..72e3eae28 --- /dev/null +++ b/library/MiscUtils.cpp @@ -0,0 +1,97 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "Internal.h" +#include "Export.h" +#include "Core.h" +#include "MiscUtils.h" + +#ifndef LINUX_BUILD + #include +#else + #include + #include +#endif + +#include + +std::string stl_sprintf(const char *fmt, ...) { + va_list lst; + va_start(lst, fmt); + std::string rv = stl_vsprintf(fmt, lst); + va_end(lst); + return rv; +} + +std::string stl_vsprintf(const char *fmt, va_list args) { + std::vector buf; + buf.resize(4096); + for (;;) { + int rsz = vsnprintf(&buf[0], buf.size(), fmt, args); + + if (rsz < 0) + buf.resize(buf.size()*2); + else if (unsigned(rsz) > buf.size()) + buf.resize(rsz+1); + else + return std::string(&buf[0], rsz); + } +} + +#ifdef LINUX_BUILD // Linux +uint64_t GetTimeMs64() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + uint64_t ret = tv.tv_usec; + + // Convert from micro seconds (10^-6) to milliseconds (10^-3) + ret /= 1000; + // Adds the seconds (10^0) after converting them to milliseconds (10^-3) + ret += (tv.tv_sec * 1000); + return ret; +} + + +#else // Windows +uint64_t GetTimeMs64() +{ + FILETIME ft; + LARGE_INTEGER li; + + // Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) + // and copy it to a LARGE_INTEGER structure. + GetSystemTimeAsFileTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + + uint64_t ret = li.QuadPart; + // Convert from file time to UNIX epoch time. + ret -= 116444736000000000LL; + // From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals + ret /= 10000; + + return ret; +} +#endif \ No newline at end of file diff --git a/library/PluginManager.cpp b/library/PluginManager.cpp index 7a7bb0981..9acd05aa4 100644 --- a/library/PluginManager.cpp +++ b/library/PluginManager.cpp @@ -23,10 +23,13 @@ distribution. */ #include "Internal.h" -#include "dfhack/Core.h" -#include "dfhack/Process.h" -#include "dfhack/PluginManager.h" -#include "dfhack/Console.h" +#include "Core.h" +#include "MemAccess.h" +#include "PluginManager.h" +#include "Console.h" + +#include "DataDefs.h" + using namespace DFHack; #include @@ -135,6 +138,7 @@ Plugin::Plugin(Core * core, const std::string & filepath, const std::string & _f plugin_shutdown = 0; plugin_status = 0; plugin_onupdate = 0; + plugin_onstatechange = 0; state = PS_UNLOADED; access = new RefLock(); } @@ -192,6 +196,7 @@ bool Plugin::load() plugin_status = (command_result (*)(Core *, std::string &)) LookupPlugin(plug, "plugin_status"); plugin_onupdate = (command_result (*)(Core *)) LookupPlugin(plug, "plugin_onupdate"); plugin_shutdown = (command_result (*)(Core *)) LookupPlugin(plug, "plugin_shutdown"); + plugin_onstatechange = (command_result (*)(Core *, state_change_event)) LookupPlugin(plug, "plugin_onstatechange"); //name = _PlugName(); plugin_lib = plug; if(plugin_init(&c,commands) == CR_OK) @@ -232,7 +237,7 @@ bool Plugin::unload() ClosePlugin(plugin_lib); state = PS_UNLOADED; access->unlock(); - return false; + return true; } else { @@ -271,13 +276,63 @@ command_result Plugin::invoke( std::string & command, std::vector { for (int i = 0; i < commands.size();i++) { - if(commands[i].name == command) + PluginCommand &cmd = commands[i]; + if(cmd.name == command) { // running interactive things from some other source than the console would break it - if(!interactive_ && commands[i].interactive) + if(!interactive_ && cmd.interactive) cr = CR_WOULD_BREAK; + else if (cmd.guard) + { + // Execute hotkey commands in a way where they can + // expect their guard conditions to be matched, + // so as to avoid duplicating checks. + // This means suspending the core beforehand. + CoreSuspender suspend(&c); + df::viewscreen *top = c.getTopViewscreen(); + + if (!cmd.guard(&c, top)) + { + c.con.printerr("Could not invoke %s: unsuitable UI state.\n", command.c_str()); + cr = CR_WRONG_USAGE; + } + else + { + cr = cmd.function(&c, parameters); + } + } else - cr = commands[i].function(&c, parameters); + { + cr = cmd.function(&c, parameters); + } + if (cr == CR_WRONG_USAGE && !cmd.usage.empty()) + c.con << "Usage:\n" << cmd.usage << flush; + break; + } + } + } + access->lock_sub(); + return cr; +} + +bool Plugin::can_invoke_hotkey( std::string & command, df::viewscreen *top ) +{ + Core & c = Core::getInstance(); + bool cr = false; + access->lock_add(); + if(state == PS_LOADED) + { + for (int i = 0; i < commands.size();i++) + { + PluginCommand &cmd = commands[i]; + if(cmd.name == command) + { + if (cmd.interactive) + cr = false; + else if (cmd.guard) + cr = cmd.guard(&c, top); + else + cr = default_hotkey(&c, top); break; } } @@ -299,6 +354,19 @@ command_result Plugin::on_update() return cr; } +command_result Plugin::on_state_change(state_change_event event) +{ + Core & c = Core::getInstance(); + command_result cr = CR_NOT_IMPLEMENTED; + access->lock_add(); + if(state == PS_LOADED && plugin_onstatechange) + { + cr = plugin_onstatechange(&c, event); + } + access->lock_sub(); + return cr; +} + Plugin::plugin_state Plugin::getState() const { return state; @@ -348,19 +416,27 @@ Plugin *PluginManager::getPluginByName (const std::string & name) return 0; } +Plugin *PluginManager::getPluginByCommand(const std::string &command) +{ + tthread::lock_guard lock(*cmdlist_mutex); + map ::iterator iter = belongs.find(command); + if (iter != belongs.end()) + return iter->second; + else + return NULL; +} + // FIXME: handle name collisions... command_result PluginManager::InvokeCommand( std::string & command, std::vector & parameters, bool interactive) { - command_result cr = CR_NOT_IMPLEMENTED; - Core * c = &Core::getInstance(); - cmdlist_mutex->lock(); - map ::iterator iter = belongs.find(command); - if(iter != belongs.end()) - { - cr = iter->second->invoke(command, parameters, interactive); - } - cmdlist_mutex->unlock(); - return cr; + Plugin *plugin = getPluginByCommand(command); + return plugin ? plugin->invoke(command, parameters, interactive) : CR_NOT_IMPLEMENTED; +} + +bool PluginManager::CanInvokeHotkey(std::string &command, df::viewscreen *top) +{ + Plugin *plugin = getPluginByCommand(command); + return plugin ? plugin->can_invoke_hotkey(command, top) : false; } void PluginManager::OnUpdate( void ) @@ -370,6 +446,15 @@ void PluginManager::OnUpdate( void ) all_plugins[i]->on_update(); } } + +void PluginManager::OnStateChange( state_change_event event ) +{ + for(int i = 0; i < all_plugins.size(); i++) + { + all_plugins[i]->on_state_change(event); + } +} + // FIXME: doesn't check name collisions! void PluginManager::registerCommands( Plugin * p ) { diff --git a/library/Process-linux.cpp b/library/Process-linux.cpp index 5fc110cc2..1a2669286 100644 --- a/library/Process-linux.cpp +++ b/library/Process-linux.cpp @@ -36,10 +36,10 @@ distribution. using namespace std; #include -#include "dfhack/Process.h" -#include "dfhack/VersionInfoFactory.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/Error.h" +#include "MemAccess.h" +#include "VersionInfoFactory.h" +#include "VersionInfo.h" +#include "Error.h" #include using namespace DFHack; @@ -111,8 +111,8 @@ Process::~Process() string Process::doReadClassName (void * vptr) { //FIXME: BAD!!!!! - int typeinfo = Process::readDWord((uint32_t)vptr - 0x4); - int typestring = Process::readDWord(typeinfo + 0x4); + char * typeinfo = Process::readPtr(((char *)vptr - 0x4)); + char * typestring = Process::readPtr(typeinfo + 0x4); string raw = readCString(typestring); size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers size_t end = raw.length(); @@ -138,8 +138,8 @@ void Process::getMemRanges( vector & ranges ) (char*)&permissions, &offset, &device1, &device2, &node, (char*)&temp.name); - temp.start = start; - temp.end = end; + temp.start = (void *) start; + temp.end = (void *) end; temp.read = permissions[0] == 'r'; temp.write = permissions[1] == 'w'; temp.execute = permissions[2] == 'x'; @@ -214,7 +214,7 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange) if(trgrange.read)protect|=PROT_READ; if(trgrange.write)protect|=PROT_WRITE; if(trgrange.execute)protect|=PROT_EXEC; - result=mprotect((void *)range.start, range.end-range.start,protect); + result=mprotect((void *)range.start, (size_t)range.end-(size_t)range.start,protect); return result==0; } \ No newline at end of file diff --git a/library/Process-windows.cpp b/library/Process-windows.cpp index 88b77891e..b02e3011f 100644 --- a/library/Process-windows.cpp +++ b/library/Process-windows.cpp @@ -91,10 +91,10 @@ extern "C" __declspec(dllimport) NTSTATUS __stdcall RtlDestroyQueryDebugBuffer( #include using namespace std; -#include "dfhack/VersionInfo.h" -#include "dfhack/VersionInfoFactory.h" -#include "dfhack/Error.h" -#include "dfhack/Process.h" +#include "VersionInfo.h" +#include "VersionInfoFactory.h" +#include "Error.h" +#include "MemAccess.h" using namespace DFHack; namespace DFHack { @@ -112,7 +112,7 @@ namespace DFHack uint32_t my_pid; IMAGE_NT_HEADERS pe_header; IMAGE_SECTION_HEADER * sections; - uint32_t base; + char * base; }; } Process::Process(VersionInfoFactory * factory) @@ -134,7 +134,7 @@ Process::Process(VersionInfoFactory * factory) } // got base ;) - d->base = (uint32_t)hmod; + d->base = (char *)hmod; // read from this process try @@ -161,7 +161,7 @@ Process::Process(VersionInfoFactory * factory) identified = true; // give the process a data model and memory layout fixed for the base of first module my_descriptor = new VersionInfo(*vinfo); - my_descriptor->RebaseAll(d->base); + my_descriptor->RebaseAll((uint32_t)d->base); // keep track of created memory_info object so we can destroy it later my_descriptor->setParentProcess(this); for(size_t i = 0; i < threads_ids.size();i++) @@ -236,7 +236,7 @@ struct HeapBlock ULONG reserved; }; */ -void HeapNodes(DWORD pid, map & heaps) +void HeapNodes(DWORD pid, map & heaps) { // Create debug buffer PDEBUG_BUFFER db = RtlCreateQueryDebugBuffer(0, FALSE); @@ -247,7 +247,7 @@ void HeapNodes(DWORD pid, map & heaps) // Go through each of the heap nodes and dispaly the information for (unsigned int i = 0; i < heapNodeCount; i++) { - heaps[heapInfo[i].Base] = i; + heaps[(char *)heapInfo[i].Base] = i; } // Clean up the buffer RtlDestroyQueryDebugBuffer( db ); @@ -257,9 +257,9 @@ void HeapNodes(DWORD pid, map & heaps) void Process::getMemRanges( vector & ranges ) { MEMORY_BASIC_INFORMATION MBI; - map heaps; + map heaps; uint64_t movingStart = 0; - map nameMap; + map nameMap; // get page size SYSTEM_INFO si; @@ -277,18 +277,18 @@ void Process::getMemRanges( vector & ranges ) if( !(MBI.State & MEM_COMMIT) /*|| !(MBI.Type & MEM_PRIVATE)*/ ) continue; t_memrange temp; - temp.start = (uint64_t) MBI.BaseAddress; - temp.end = ((uint64_t)MBI.BaseAddress + (uint64_t)MBI.RegionSize); + temp.start = (char *) MBI.BaseAddress; + temp.end = ((char *)MBI.BaseAddress + (uint64_t)MBI.RegionSize); temp.read = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READONLY || MBI.Protect & PAGE_READWRITE; temp.write = MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READWRITE; temp.execute = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_EXECUTE; temp.valid = true; if(!GetModuleBaseName(d->my_handle, (HMODULE) temp.start, temp.name, 1024)) { - if(nameMap.count(temp.start)) + if(nameMap.count((char *)temp.start)) { // potential buffer overflow... - strcpy(temp.name, nameMap[temp.start].c_str()); + strcpy(temp.name, nameMap[(char *)temp.start].c_str()); } else { @@ -298,9 +298,9 @@ void Process::getMemRanges( vector & ranges ) else { // could be a heap? - if(heaps.count(temp.start)) + if(heaps.count((char *)temp.start)) { - sprintf(temp.name,"HEAP %d",heaps[temp.start]); + sprintf(temp.name,"HEAP %d",heaps[(char*)temp.start]); } else temp.name[0]=0; } @@ -320,7 +320,7 @@ void Process::getMemRanges( vector & ranges ) nm.append(temp.name); nm.append(" : "); nm.append(sectionName); - nameMap[temp.start + d->sections[i].VirtualAddress] = nm; + nameMap[(char *)temp.start + d->sections[i].VirtualAddress] = nm; } } else @@ -333,14 +333,14 @@ void Process::getMemRanges( vector & ranges ) uint32_t Process::getBase() { if(d) - return d->base; + return (uint32_t) d->base; return 0x400000; } string Process::doReadClassName (void * vptr) { - int rtti = readDWord((uint32_t)vptr - 0x4); - int typeinfo = readDWord(rtti + 0xC); + char * rtti = readPtr((char *)vptr - 0x4); + char * typeinfo = readPtr(rtti + 0xC); string raw = readCString(typeinfo + 0xC); // skips the .?AV raw.resize(raw.length() - 2);// trim @@ from end return raw; @@ -367,7 +367,7 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange) if(trgrange.read && trgrange.write && trgrange.execute)newprotect=PAGE_EXECUTE_READWRITE; DWORD oldprotect=0; bool result; - result=VirtualProtect((LPVOID)range.start,range.end-range.start,newprotect,&oldprotect); + result=VirtualProtect((LPVOID)range.start,(char *)range.end-(char *)range.start,newprotect,&oldprotect); return result; } diff --git a/library/TileTypes.cpp b/library/TileTypes.cpp index 295e269c6..31a82eb55 100644 --- a/library/TileTypes.cpp +++ b/library/TileTypes.cpp @@ -23,8 +23,8 @@ distribution. */ #include "Internal.h" -#include "dfhack/TileTypes.h" -#include "dfhack/Export.h" +#include "TileTypes.h" +#include "Export.h" namespace DFHack { diff --git a/library/VersionInfo.cpp b/library/VersionInfo.cpp index c90654580..6bda6d669 100644 --- a/library/VersionInfo.cpp +++ b/library/VersionInfo.cpp @@ -31,9 +31,9 @@ distribution. #include using namespace std; -#include "dfhack/VersionInfo.h" -#include "dfhack/Error.h" -#include "dfhack/Process.h" +#include "VersionInfo.h" +#include "Error.h" +#include "MemAccess.h" using namespace DFHack; //Inital amount of space in levels vector (since we usually know the number, efficient!) @@ -158,6 +158,8 @@ namespace DFHack { typedef pair nullableUint32; typedef map ::iterator uint32_Iter; + typedef pair nullableBytePtr; + typedef map ::iterator byteptr_Iter; typedef pair nullableInt32; typedef map ::iterator int32_Iter; typedef pair nullableString; @@ -166,7 +168,7 @@ namespace DFHack class OffsetGroupPrivate { public: - map addresses; + map addresses; map hexvals; map offsets; map strings; @@ -183,7 +185,7 @@ void OffsetGroup::createOffset(const string & key) void OffsetGroup::createAddress(const string & key) { - OGd->addresses[key] = nullableUint32(NOT_SET, 0); + OGd->addresses[key] = nullableBytePtr(NOT_SET, (char*) 0); } void OffsetGroup::createHexValue(const string & key) @@ -227,10 +229,10 @@ void OffsetGroup::setOffsetValidity (const string & key, const INVAL_TYPE inval) void OffsetGroup::setAddress (const string & key, const string & value, const INVAL_TYPE inval) { - uint32_Iter it = OGd->addresses.find(key); + byteptr_Iter it = OGd->addresses.find(key); if(it != OGd->addresses.end()) { - uint32_t address = strtol(value.c_str(), NULL, 16); + char * address = (char *) strtol(value.c_str(), NULL, 16); if((*it).second.second == address) std::cout << "Pointless address setting: " << this->getFullName() + key << endl; (*it).second.second = address; @@ -244,7 +246,7 @@ void OffsetGroup::setAddressValidity (const string & key, const INVAL_TYPE inval { if(inval != NOT_SET) { - uint32_Iter it = OGd->addresses.find(key); + byteptr_Iter it = OGd->addresses.find(key); if(it != OGd->addresses.end()) { (*it).second.first = inval; @@ -305,9 +307,9 @@ void OffsetGroup::setStringValidity (const string & key, const INVAL_TYPE inval) } // Get named address -uint32_t OffsetGroup::getAddress (const string & key) +char * OffsetGroup::getAddress (const string & key) { - uint32_Iter iter = OGd->addresses.find(key); + byteptr_Iter iter = OGd->addresses.find(key); if(iter != OGd->addresses.end()) { @@ -321,9 +323,9 @@ uint32_t OffsetGroup::getAddress (const string & key) } // Get named offset, return bool instead of throwing exceptions -bool OffsetGroup::getSafeAddress (const string & key, uint32_t & out) +bool OffsetGroup::getSafeAddress (const string & key, void * & out) { - uint32_Iter iter = OGd->addresses.find(key); + byteptr_Iter iter = OGd->addresses.find(key); if(iter != OGd->addresses.end() && (*iter).second.first == IS_VALID) { out = (*iter).second.second; @@ -410,7 +412,7 @@ OffsetGroup * OffsetGroup::createGroup(const std::string &name) void OffsetGroup::RebaseAddresses(int32_t offset) { - for(uint32_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) + for(byteptr_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) { if(iter->second.first) OGd->addresses[iter->first].second = iter->second.second + offset; @@ -470,18 +472,19 @@ std::string OffsetGroup::getFullName() std::string OffsetGroup::PrintOffsets(int indentation) { + byteptr_Iter addriter; uint32_Iter iter; ostringstream ss; indentr i(indentation); - typedef pair > horrible; + typedef pair > horrible; vector < horrible > addrsorter; - for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) + for(addriter = OGd->addresses.begin(); addriter != OGd->addresses.end(); addriter++) { - if(!(*iter).second.first) - addrsorter.push_back( make_pair( 0, *iter ) ); + if(!(*addriter).second.first) + addrsorter.push_back( make_pair( (void *)0, *addriter ) ); else { - addrsorter.push_back( make_pair( (*iter).second.second, *iter ) ); + addrsorter.push_back( make_pair( (*addriter).second.second, *addriter ) ); } } std::sort(addrsorter.begin(), addrsorter.end(), compare_pair_first<>()); @@ -569,7 +572,7 @@ void OffsetGroup::setInvalid(INVAL_TYPE invalidity) if(invalidity == NOT_SET) return; - uint32_Iter iter; + byteptr_Iter iter; for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) { if((*iter).second.first) @@ -581,17 +584,18 @@ void OffsetGroup::setInvalid(INVAL_TYPE invalidity) if((*iter2).second.first) (*iter2).second.first = invalidity; } - for(iter = OGd->hexvals.begin(); iter != OGd->hexvals.end(); iter++) - { - if((*iter).second.first) - (*iter).second.first = invalidity; - } - strings_Iter iter3; - for(iter3 = OGd->strings.begin(); iter3 != OGd->strings.end(); iter3++) + uint32_Iter iter3; + for(iter3 = OGd->hexvals.begin(); iter3 != OGd->hexvals.end(); iter3++) { if((*iter3).second.first) (*iter3).second.first = invalidity; } + strings_Iter iter5; + for(iter5 = OGd->strings.begin(); iter5 != OGd->strings.end(); iter5++) + { + if((*iter5).second.first) + (*iter5).second.first = invalidity; + } groups_Iter iter4; for(iter4 = OGd->groups.begin(); iter4 != OGd->groups.end(); iter4++) { @@ -603,7 +607,7 @@ std::vector OffsetGroup::getKeys() const std::vector ret; OffsetKey K; K.keytype=IS_ADDRESS; - for(uint32_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) + for(byteptr_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) { K.key=iter->first; K.inval=iter->second.first; @@ -1015,7 +1019,7 @@ void VersionInfo::setClassChild (t_class * parent, const char * name, const char // FIXME: This in now DEPRECATED! -bool VersionInfo::resolveObjectToClassID(const uint32_t address, int32_t & classid) +bool VersionInfo::resolveObjectToClassID(const char * address, int32_t & classid) { uint32_t vtable = d->p->readDWord(address); // try to find the vtable in our cache @@ -1205,7 +1209,7 @@ string VersionInfo::getTrait (const uint32_t traitIdx, const uint32_t traitValue if(d->traits.size() > traitIdx) { int diff = absolute(traitValue-50); - if(diff < 10) + if(diff <= 10) { return string(""); } @@ -1294,4 +1298,4 @@ std::string VersionInfo::PrintOffsets() ss << i << "" << endl; ss << endl; return ss.str(); -} \ No newline at end of file +} diff --git a/library/VersionInfoFactory.cpp b/library/VersionInfoFactory.cpp index b2ec00d96..bb8c7c533 100644 --- a/library/VersionInfoFactory.cpp +++ b/library/VersionInfoFactory.cpp @@ -31,9 +31,9 @@ distribution. #include using namespace std; -#include "dfhack/VersionInfoFactory.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/Error.h" +#include "VersionInfoFactory.h" +#include "VersionInfo.h" +#include "Error.h" using namespace DFHack; #include diff --git a/library/Virtual.cpp b/library/Virtual.cpp index bafdc0cc5..6706f93be 100644 --- a/library/Virtual.cpp +++ b/library/Virtual.cpp @@ -4,9 +4,9 @@ #include #include -#include "dfhack/Process.h" -#include "dfhack/Core.h" -#include "dfhack/Virtual.h" +#include "MemAccess.h" +#include "Core.h" +#include "Virtual.h" using namespace DFHack; std::string t_virtual::getClassName() const diff --git a/library/include/dfhack/BitArray.h b/library/include/BitArray.h similarity index 98% rename from library/include/dfhack/BitArray.h rename to library/include/BitArray.h index 7e4b8a915..77e2a3ac1 100644 --- a/library/include/dfhack/BitArray.h +++ b/library/include/BitArray.h @@ -23,8 +23,8 @@ distribution. */ #pragma once -#include "dfhack/Pragma.h" -#include "dfhack/Export.h" +#include "Pragma.h" +#include "Export.h" #include #include #include diff --git a/library/include/dfhack/Console.h b/library/include/Console.h similarity index 98% rename from library/include/dfhack/Console.h rename to library/include/Console.h index e4e2c44f7..70385d829 100644 --- a/library/include/dfhack/Console.h +++ b/library/include/Console.h @@ -23,8 +23,8 @@ distribution. */ #pragma once -#include "dfhack/Pragma.h" -#include "dfhack/Export.h" +#include "Pragma.h" +#include "Export.h" #include #include #include diff --git a/library/include/dfhack/Core.h b/library/include/Core.h similarity index 86% rename from library/include/dfhack/Core.h rename to library/include/Core.h index 64eae5d3e..a368e360d 100644 --- a/library/include/dfhack/Core.h +++ b/library/include/Core.h @@ -24,15 +24,15 @@ distribution. #pragma once -#include "dfhack/Pragma.h" -#include "dfhack/Export.h" -#include "dfhack/FakeSDL.h" +#include "Pragma.h" +#include "Export.h" +#include "Hooks.h" #include #include #include #include -#include "dfhack/Console.h" -#include "dfhack/modules/Graphic.h" +#include "Console.h" +#include "modules/Graphic.h" struct WINDOW; @@ -43,6 +43,11 @@ namespace tthread class thread; } +namespace df +{ + struct viewscreen; +} + namespace DFHack { class Process; @@ -134,6 +139,13 @@ namespace DFHack /// returns a named pointer. void *GetData(std::string key); + bool ClearKeyBindings(std::string keyspec); + bool AddKeyBinding(std::string keyspec, std::string cmdline); + std::vector ListKeyBindings(std::string keyspec); + + bool isWorldLoaded() { return (last_world_data_ptr != NULL); } + df::viewscreen *getTopViewscreen() { return top_viewscreen; } + DFHack::Process * p; DFHack::VersionInfo * vinfo; DFHack::Console con; @@ -178,12 +190,25 @@ namespace DFHack } s_mods; std::vector allModules; DFHack::PluginManager * plug_mgr; + // hotkey-related stuff - int hotkey_states[16]; + struct KeyBinding { + int modifiers; + std::vector command; + std::string cmdline; + }; + + std::map > key_bindings; + std::map hotkey_states; std::string hotkey_cmd; bool hotkey_set; tthread::mutex * HotkeyMutex; tthread::condition_variable * HotkeyCond; + + bool SelectHotkey(int key, int modifiers); + + void *last_world_data_ptr; // for state change tracking + df::viewscreen *top_viewscreen; // Very important! bool started; diff --git a/library/include/DFHack.h b/library/include/DFHack.h index 938decbc8..ac5d78cf0 100644 --- a/library/include/DFHack.h +++ b/library/include/DFHack.h @@ -47,34 +47,34 @@ distribution. #include // DFHack core classes and types -#include "dfhack/Error.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" -#include "dfhack/Types.h" +#include "Error.h" +#include "VersionInfo.h" +#include "MemAccess.h" +#include "Types.h" // DFHack modules -#include "dfhack/modules/Buildings.h" -#include "dfhack/modules/Engravings.h" -#include "dfhack/modules/Materials.h" -#include "dfhack/modules/Constructions.h" -#include "dfhack/modules/Units.h" -#include "dfhack/modules/Translation.h" -#include "dfhack/modules/World.h" -#include "dfhack/modules/Items.h" -#include "dfhack/modules/Vegetation.h" -#include "dfhack/modules/Maps.h" -#include "dfhack/modules/Gui.h" +#include "modules/Buildings.h" +#include "modules/Engravings.h" +#include "modules/Materials.h" +#include "modules/Constructions.h" +#include "modules/Units.h" +#include "modules/Translation.h" +#include "modules/World.h" +#include "modules/Items.h" +#include "modules/Vegetation.h" +#include "modules/Maps.h" +#include "modules/Gui.h" /* * This is a header full of ugly, volatile things. * Only for use of official DFHack tools! */ #ifdef DFHACK_WANT_MISCUTILS - #include "dfhack/MiscUtils.h" + #include "MiscUtils.h" #endif // define this to get the static tiletype->properties mapping #ifdef DFHACK_WANT_TILETYPES - #include "dfhack/TileTypes.h" + #include "TileTypes.h" #endif #endif diff --git a/library/include/dfhack/DataDefs.h b/library/include/DataDefs.h similarity index 62% rename from library/include/dfhack/DataDefs.h rename to library/include/DataDefs.h index 4308ea3ed..ff61d08f5 100644 --- a/library/include/dfhack/DataDefs.h +++ b/library/include/DataDefs.h @@ -28,8 +28,8 @@ distribution. #include #include -#include "dfhack/Core.h" -#include "dfhack/BitArray.h" +#include "Core.h" +#include "BitArray.h" // Stop some MS stupidity #ifdef interface @@ -62,8 +62,6 @@ namespace DFHack protected: virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent); - bool check_instance(virtual_ptr instance_ptr, bool allow_subclasses); - static void *get_vtable(virtual_ptr instance_ptr) { return *(void**)instance_ptr; } public: @@ -73,8 +71,10 @@ namespace DFHack virtual_identity *getParent() { return parent; } const std::vector &getChildren() { return children; } + public: static virtual_identity *get(virtual_ptr instance_ptr); - + + bool is_subclass(virtual_identity *subtype); bool is_instance(virtual_ptr instance_ptr) { if (!instance_ptr) return false; if (vtable_ptr) { @@ -82,16 +82,28 @@ namespace DFHack if (vtable == vtable_ptr) return true; if (!has_children) return false; } - return check_instance(instance_ptr, true); + return is_subclass(get(instance_ptr)); } bool is_direct_instance(virtual_ptr instance_ptr) { if (!instance_ptr) return false; return vtable_ptr ? (vtable_ptr == get_vtable(instance_ptr)) - : check_instance(instance_ptr, false); + : (this == get(instance_ptr)); } - static void Init(); + public: + bool can_instantiate() { return (vtable_ptr != NULL); } + virtual_ptr instantiate() { return can_instantiate() ? do_instantiate() : NULL; } + static virtual_ptr clone(virtual_ptr obj); + + protected: + virtual virtual_ptr do_instantiate() = 0; + virtual void do_copy(virtual_ptr tgt, virtual_ptr src) = 0; + public: + static void Init(Core *core); + + // Strictly for use in virtual class constructors + void adjust_vtable(virtual_ptr obj, virtual_identity *main); }; template @@ -99,27 +111,59 @@ namespace DFHack return T::_identity.is_instance(ptr) ? static_cast(ptr) : NULL; } +#define VIRTUAL_CAST_VAR(var,type,input) type *var = virtual_cast(input) + template inline T *strict_virtual_cast(virtual_ptr ptr) { return T::_identity.is_direct_instance(ptr) ? static_cast(ptr) : NULL; } +#define STRICT_VIRTUAL_CAST_VAR(var,type,input) type *var = strict_virtual_cast(input) + void InitDataDefGlobals(Core *core); template T *ifnull(T *a, T *b) { return a ? a : b; } + + template + inline T next_enum_item_(T v) { + v = T(int(v) + 1); + return isvalid(v) ? v : start; + } + + struct bitfield_item_info { + const char *name; + int size; + }; + + DFHACK_EXPORT std::string bitfieldToString(const void *p, int size, const bitfield_item_info *items); + + template + inline std::string bitfieldToString(const T &val) { + return bitfieldToString(&val.whole, sizeof(val.whole), val.get_items()); + } } namespace df { + using DFHack::virtual_ptr; + using DFHack::virtual_identity; using DFHack::virtual_class; + using DFHack::bitfield_item_info; using DFHack::BitArray; template - class class_virtual_identity : public DFHack::virtual_identity { + class class_virtual_identity : public virtual_identity { public: class_virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent) : virtual_identity(dfhack_name, original_name, parent) {}; + + T *instantiate() { return static_cast(virtual_identity::instantiate()); } + T *clone(T* obj) { return static_cast(virtual_identity::clone(obj)); } + + protected: + virtual virtual_ptr do_instantiate() { return new T(); } + virtual void do_copy(virtual_ptr tgt, virtual_ptr src) { *static_cast(tgt) = *static_cast(src); } }; template @@ -146,17 +190,33 @@ namespace df #define ENUM_FIRST_ITEM(enum) (df::enums::enum::_first_item_of_##enum) #define ENUM_LAST_ITEM(enum) (df::enums::enum::_last_item_of_##enum) +#define ENUM_NEXT_ITEM(enum,val) \ + (DFHack::next_enum_item_(val)) +#define FOR_ENUM_ITEMS(enum,iter) \ + for(df::enum iter = ENUM_FIRST_ITEM(enum); iter < ENUM_LAST_ITEM(enum); iter = df::enum(1+int(iter))) + namespace df { #define DF_KNOWN_GLOBALS \ + GLOBAL(cursor,cursor) \ + GLOBAL(selection_rect,selection_rect) \ GLOBAL(world,world) \ GLOBAL(ui,ui) \ GLOBAL(gview,interface) \ GLOBAL(init,init) \ - GLOBAL(d_init,d_init) - -#define GLOBAL(name,tname) \ - struct tname; \ + GLOBAL(d_init,d_init) \ + SIMPLE_GLOBAL(job_next_id,int) \ + SIMPLE_GLOBAL(ui_look_cursor,int) \ + SIMPLE_GLOBAL(ui_workshop_job_cursor,int) \ + SIMPLE_GLOBAL(ui_workshop_in_add,bool) \ + GLOBAL(ui_sidebar_menus,ui_sidebar_menus) \ + GLOBAL(ui_build_selector,ui_build_selector) \ + GLOBAL(ui_look_list,ui_look_list) + +#define SIMPLE_GLOBAL(name,tname) \ namespace global { extern DFHACK_EXPORT tname *name; } +#define GLOBAL(name,tname) \ + struct tname; SIMPLE_GLOBAL(name,tname) DF_KNOWN_GLOBALS #undef GLOBAL +#undef SIMPLE_GLOBAL } diff --git a/library/include/dfhack/Error.h b/library/include/Error.h similarity index 99% rename from library/include/dfhack/Error.h rename to library/include/Error.h index 946cc2d4c..1a25d1cbb 100644 --- a/library/include/dfhack/Error.h +++ b/library/include/Error.h @@ -27,8 +27,8 @@ distribution. #ifndef ERROR_H_INCLUDED #define ERROR_H_INCLUDED -#include "dfhack/Export.h" -#include "dfhack/Pragma.h" +#include "Export.h" +#include "Pragma.h" #include #include #include diff --git a/library/include/dfhack/Export.h b/library/include/Export.h similarity index 100% rename from library/include/dfhack/Export.h rename to library/include/Export.h diff --git a/library/include/dfhack/FakeSDL.h b/library/include/Hooks.h similarity index 66% rename from library/include/dfhack/FakeSDL.h rename to library/include/Hooks.h index 0f3ced545..f01d58c07 100644 --- a/library/include/dfhack/FakeSDL.h +++ b/library/include/Hooks.h @@ -28,39 +28,20 @@ distribution. * Some much needed SDL fakery. */ -#include "dfhack/Pragma.h" -#include "dfhack/Export.h" +#include "Pragma.h" +#include "Export.h" #include #include // function and variable pointer... we don't try to understand what SDL does here - typedef void * fPtr; typedef void * vPtr; struct WINDOW; namespace SDL { union Event; - //struct Thread; - //struct Mutex; - //struct Cond; - //struct Library; } -/* -// mutex stuff -DFhackCExport SDL::Mutex * SDL_CreateMutex(void); -DFhackCExport int SDL_mutexP(SDL::Mutex *); -DFhackCExport int SDL_mutexV(SDL::Mutex *); -DFhackCExport void SDL_DestroyMutex(SDL::Mutex *); -// thread stuff -DFhackCExport SDL::Thread *SDL_CreateThread(int (*fn)(void *), void *data); -DFhackCExport uint32_t SDL_ThreadID(); -// condition variables -DFhackCExport SDL::Cond *SDL_CreateCond(void); -DFhackCExport void SDL_DestroyCond(SDL::Cond *cond); -DFhackCExport int SDL_CondSignal(SDL::Cond *cond); -DFhackCExport int SDL_CondWait(SDL::Cond *cond, SDL::Mutex * mut); -*/ + // these functions are here because they call into DFHack::Core and therefore need to // be declared as friend functions/known DFhackCExport int SDL_NumJoysticks(void); @@ -69,4 +50,3 @@ DFhackCExport int SDL_PollEvent(SDL::Event* event); DFhackCExport int SDL_Init(uint32_t flags); DFhackCExport int wgetch(WINDOW * win); -// Other crud is in the OS-specific core files. diff --git a/library/private/Internal.h b/library/include/Internal.h similarity index 90% rename from library/private/Internal.h rename to library/include/Internal.h index 34cc40901..12b7852a1 100644 --- a/library/private/Internal.h +++ b/library/include/Internal.h @@ -24,9 +24,6 @@ distribution. #pragma once -#ifndef DFCOMMONINTERNAL_H_INCLUDED -#define DFCOMMONINTERNAL_H_INCLUDED - // this makes everything that includes this file export symbols when using DFHACK_EXPORT (see DFExport.h) #ifndef BUILD_DFHACK_LIB #define BUILD_DFHACK_LIB @@ -38,10 +35,7 @@ distribution. #endif // one file for telling the MSVC compiler where it can shove its pointless warnings -#include "dfhack/Pragma.h" +#include "Pragma.h" // C99 integer types #include - -#endif // DFCOMMONINTERNAL_H_INCLUDED - diff --git a/library/include/dfhack/Process.h b/library/include/MemAccess.h similarity index 82% rename from library/include/dfhack/Process.h rename to library/include/MemAccess.h index 1bd2b9710..531b83353 100644 --- a/library/include/dfhack/Process.h +++ b/library/include/MemAccess.h @@ -28,8 +28,8 @@ distribution. #ifndef PROCESS_H_INCLUDED #define PROCESS_H_INCLUDED -#include "dfhack/Pragma.h" -#include "dfhack/Export.h" +#include "Pragma.h" +#include "Export.h" #include #include #include @@ -72,8 +72,8 @@ namespace DFHack */ struct DFHACK_EXPORT t_memrange { - uint64_t start; - uint64_t end; + void * start; + void * end; // memory range name (if any) char name[1024]; // permission to read @@ -84,7 +84,7 @@ namespace DFHack bool execute : 1; // is a shared region bool shared : 1; - inline bool isInRange( uint64_t address) + inline bool isInRange( void * address) { if (address >= start && address < end) return true; return false; @@ -104,99 +104,110 @@ namespace DFHack Process(VersionInfoFactory * known_versions); ~Process(); /// read a 8-byte integer - uint64_t readQuad(const uint32_t address) + uint64_t readQuad(const void * address) { return *(uint64_t *)address; } /// read a 8-byte integer - void readQuad(const uint32_t address, uint64_t & value) + void readQuad(const void * address, uint64_t & value) { value = *(uint64_t *)address; }; /// write a 8-byte integer - void writeQuad(const uint32_t address, const uint64_t value) + void writeQuad(const void * address, const uint64_t value) { (*(uint64_t *)address) = value; }; /// read a 4-byte integer - uint32_t readDWord(const uint32_t address) + uint32_t readDWord(const void * address) { return *(uint32_t *)address; } /// read a 4-byte integer - void readDWord(const uint32_t address, uint32_t & value) + void readDWord(const void * address, uint32_t & value) { value = *(uint32_t *)address; }; /// write a 4-byte integer - void writeDWord(const uint32_t address, const uint32_t value) + void writeDWord(const void * address, const uint32_t value) { (*(uint32_t *)address) = value; }; + /// read a pointer + char * readPtr(const void * address) + { + return *(char **)address; + } + /// read a pointer + void readPtr(const void * address, char * & value) + { + value = *(char **)address; + }; + /// read a float - float readFloat(const uint32_t address) + float readFloat(const void * address) { return *(float*)address; } /// write a float - void readFloat(const uint32_t address, float & value) + void readFloat(const void * address, float & value) { value = *(float*)address; }; /// read a 2-byte integer - uint16_t readWord(const uint32_t address) + uint16_t readWord(const void * address) { return *(uint16_t *)address; } /// read a 2-byte integer - void readWord(const uint32_t address, uint16_t & value) + void readWord(const void * address, uint16_t & value) { value = *(uint16_t *)address; }; /// write a 2-byte integer - void writeWord(const uint32_t address, const uint16_t value) + void writeWord(const void * address, const uint16_t value) { (*(uint16_t *)address) = value; }; /// read a byte - uint8_t readByte(const uint32_t address) + uint8_t readByte(const void * address) { return *(uint8_t *)address; } /// read a byte - void readByte(const uint32_t address, uint8_t & value) + void readByte(const void * address, uint8_t & value) { value = *(uint8_t *)address; }; /// write a byte - void writeByte(const uint32_t address, const uint8_t value) + void writeByte(const void * address, const uint8_t value) { (*(uint8_t *)address) = value; }; /// read an arbitrary amount of bytes - void read( uint32_t address, uint32_t length, uint8_t* buffer) + void read(void * address, uint32_t length, uint8_t* buffer) { memcpy(buffer, (void *) address, length); }; /// write an arbitrary amount of bytes - void write(uint32_t address, uint32_t length, uint8_t* buffer) + void write(void * address, uint32_t length, uint8_t* buffer) { memcpy((void *) address, buffer, length); }; /// read an STL string - const std::string readSTLString (uint32_t offset) + const std::string readSTLString (void * offset) { std::string * str = (std::string *) offset; return *str; }; /// read an STL string - size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) + size_t readSTLString (void * offset, char * buffer, size_t bufcapacity) { if(!bufcapacity || bufcapacity == 1) return 0; @@ -209,7 +220,7 @@ namespace DFHack * write an STL string * @return length written */ - size_t writeSTLString(const uint32_t address, const std::string writeString) + size_t writeSTLString(const void * address, const std::string writeString) { std::string * str = (std::string *) address; str->assign(writeString); @@ -219,7 +230,7 @@ namespace DFHack * attempt to copy a string from source address to target address. may truncate or leak, depending on platform * @return length copied */ - size_t copySTLString(const uint32_t address, const uint32_t target) + size_t copySTLString(const void * address, const uint32_t target) { std::string * strsrc = (std::string *) address; std::string * str = (std::string *) target; @@ -239,7 +250,7 @@ namespace DFHack } /// read a null-terminated C string - const std::string readCString (uint32_t offset) + const std::string readCString (void * offset) { return std::string((char *) offset); }; diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h new file mode 100644 index 000000000..5897994e3 --- /dev/null +++ b/library/include/MiscUtils.h @@ -0,0 +1,228 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#pragma once +#include "Export.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +template +void print_bits ( T val, DFHack::Console& out ) +{ + stringstream strs; + T n_bits = sizeof ( val ) * CHAR_BIT; + int cnt; + for ( unsigned i = 0; i < n_bits; ++i ) + { + cnt = i/10; + strs << cnt << " "; + } + strs << endl; + for ( unsigned i = 0; i < n_bits; ++i ) + { + cnt = i%10; + strs << cnt << " "; + } + strs << endl; + for ( unsigned i = 0; i < n_bits; ++i ) + { + strs << "--"; + } + strs << endl; + for ( unsigned i = 0; i < n_bits; ++i ) + { + strs<< !!( val & 1 ) << " "; + val >>= 1; + } + strs << endl; + out.print(strs.str().c_str()); +} + +/* + * Binary search in vectors. + */ + +template +int linear_index(const std::vector &vec, FT key) +{ + for (unsigned i = 0; i < vec.size(); i++) + if (vec[i] == key) + return i; + return -1; +} + +template +int linear_index(const std::vector &vec, const FT &key) +{ + for (unsigned i = 0; i < vec.size(); i++) + if (vec[i] && *vec[i] == key) + return i; + return -1; +} + +template +int binsearch_index(const std::vector &vec, FT key, bool exact = true) +{ + // Returns the index of the value >= the key + int min = -1, max = (int)vec.size(); + const FT *p = vec.data(); + for (;;) + { + int mid = (min + max)>>1; + if (mid == min) + return exact ? -1 : max; + FT midv = p[mid]; + if (midv == key) + return mid; + else if (midv < key) + min = mid; + else + max = mid; + } +} + +template +int linear_index(const std::vector &vec, FT CT::*field, FT key) +{ + for (unsigned i = 0; i < vec.size(); i++) + if (vec[i]->*field == key) + return i; + return -1; +} + +template +int binsearch_index(const std::vector &vec, FT CT::*field, FT key, bool exact = true) +{ + // Returns the index of the value >= the key + int min = -1, max = (int)vec.size(); + CT *const *p = vec.data(); + for (;;) + { + int mid = (min + max)>>1; + if (mid == min) + return exact ? -1 : max; + FT midv = p[mid]->*field; + if (midv == key) + return mid; + else if (midv < key) + min = mid; + else + max = mid; + } +} + +template +inline int binsearch_index(const std::vector &vec, typename CT::key_field_type key, bool exact = true) +{ + return CT::binsearch_index(vec, key, exact); +} + +template +inline int binsearch_index(const std::vector &vec, typename CT::key_pointer_type key, bool exact = true) +{ + return CT::binsearch_index(vec, key, exact); +} + +template +inline bool vector_contains(const std::vector &vec, KT key) +{ + return binsearch_index(vec, key) >= 0; +} + +template +inline bool vector_contains(const std::vector &vec, FT CT::*field, FT key) +{ + return binsearch_index(vec, field, key) >= 0; +} + +template +unsigned insert_into_vector(std::vector &vec, FT key, bool *inserted = NULL) +{ + unsigned pos = (unsigned)binsearch_index(vec, key, false); + bool to_ins = (pos >= vec.size() || vec[pos] != key); + if (inserted) *inserted = to_ins; + if (to_ins) + vec.insert(vec.begin()+pos,key); + return pos; +} + +template +unsigned insert_into_vector(std::vector &vec, FT CT::*field, CT *obj, bool *inserted = NULL) +{ + unsigned pos = (unsigned)binsearch_index(vec, field, obj->*field, false); + bool to_ins = (pos >= vec.size() || vec[pos] != obj); + if (inserted) *inserted = to_ins; + if (to_ins) + vec.insert(vec.begin()+pos,obj); + return pos; +} + +template +CT *binsearch_in_vector(const std::vector &vec, KT value) +{ + int idx = binsearch_index(vec, value); + return idx < 0 ? NULL : vec[idx]; +} + +template +CT *binsearch_in_vector(const std::vector &vec, FT CT::*field, FT value) +{ + int idx = binsearch_index(vec, field, value); + return idx < 0 ? NULL : vec[idx]; +} + +/* + * List + */ + +template +Link *linked_list_append(Link *head, Link *tail) +{ + while (head->next) + head = head->next; + head->next = tail; + tail->prev = head; + return tail; +} + +/* + * MISC + */ + +/** + * Returns the amount of milliseconds elapsed since the UNIX epoch. + * Works on both windows and linux. + * source: http://stackoverflow.com/questions/1861294/how-to-calculate-execution-time-of-a-code-snippet-in-c + */ +DFHACK_EXPORT uint64_t GetTimeMs64(); + +DFHACK_EXPORT std::string stl_sprintf(const char *fmt, ...); +DFHACK_EXPORT std::string stl_vsprintf(const char *fmt, va_list args); diff --git a/library/include/dfhack/Module.h b/library/include/Module.h similarity index 98% rename from library/include/dfhack/Module.h rename to library/include/Module.h index c583ab17c..7433fce49 100644 --- a/library/include/dfhack/Module.h +++ b/library/include/Module.h @@ -27,7 +27,7 @@ distribution. #ifndef MODULE_H_INCLUDED #define MODULE_H_INCLUDED -#include "dfhack/Export.h" +#include "Export.h" namespace DFHack { /** diff --git a/library/private/ModuleFactory.h b/library/include/ModuleFactory.h similarity index 100% rename from library/private/ModuleFactory.h rename to library/include/ModuleFactory.h diff --git a/library/include/dfhack/PluginManager.h b/library/include/PluginManager.h similarity index 67% rename from library/include/dfhack/PluginManager.h rename to library/include/PluginManager.h index fef1aea50..726734baa 100644 --- a/library/include/dfhack/PluginManager.h +++ b/library/include/PluginManager.h @@ -24,55 +24,80 @@ distribution. #pragma once -#include "dfhack/Export.h" +#include "Export.h" +#include "Hooks.h" #include #include #include -#include "FakeSDL.h" struct DFLibrary; namespace tthread { class mutex; class condition_variable; } +namespace df +{ + struct viewscreen; +} namespace DFHack { class Core; class PluginManager; + struct virtual_identity; + enum command_result { CR_WOULD_BREAK = -2, CR_NOT_IMPLEMENTED = -1, CR_FAILURE = 0, - CR_OK = 1 + CR_OK = 1, + CR_WRONG_USAGE = 2 }; - struct PluginCommand + enum state_change_event { + SC_GAME_LOADED, + SC_GAME_UNLOADED, + SC_VIEWSCREEN_CHANGED + }; + struct DFHACK_EXPORT PluginCommand + { + typedef command_result (*command_function)(Core *, std::vector &); + typedef bool (*command_hotkey_guard)(Core *, df::viewscreen *); + /// create a command with a name, description, function pointer to its code /// and saying if it needs an interactive terminal /// Most commands shouldn't require an interactive terminal! PluginCommand(const char * _name, const char * _description, - command_result (*function_)(Core *, std::vector &), - bool interactive_ = false + command_function function_, + bool interactive_ = false, + const char * usage_ = "" ) + : name(_name), description(_description), + function(function_), interactive(interactive_), + guard(NULL), usage(usage_) { - name = _name; - description = _description; - function = function_; - interactive = interactive_; } - PluginCommand (const PluginCommand & rhs) + + PluginCommand(const char * _name, + const char * _description, + command_function function_, + command_hotkey_guard guard_, + const char * usage_ = "") + : name(_name), description(_description), + function(function_), interactive(false), + guard(guard_), usage(usage_) { - name = rhs.name; - description = rhs.description; - function = rhs.function; - interactive = rhs.interactive; } + + bool isHotkeyCommand() const { return guard != NULL; } + std::string name; std::string description; - command_result (*function)(Core *, std::vector &); + command_function function; bool interactive; + command_hotkey_guard guard; + std::string usage; }; class Plugin { @@ -87,11 +112,13 @@ namespace DFHack Plugin(DFHack::Core* core, const std::string& filepath, const std::string& filename, PluginManager * pm); ~Plugin(); command_result on_update(); + command_result on_state_change(state_change_event event); public: bool load(); bool unload(); bool reload(); command_result invoke( std::string & command, std::vector & parameters, bool interactive ); + bool can_invoke_hotkey( std::string & command, df::viewscreen *top ); plugin_state getState () const; const PluginCommand& operator[] (std::size_t index) const { @@ -117,6 +144,7 @@ namespace DFHack command_result (*plugin_status)(Core *, std::string &); command_result (*plugin_shutdown)(Core *); command_result (*plugin_onupdate)(Core *); + command_result (*plugin_onstatechange)(Core *, state_change_event); }; class DFHACK_EXPORT PluginManager { @@ -126,12 +154,15 @@ namespace DFHack PluginManager(Core * core); ~PluginManager(); void OnUpdate( void ); + void OnStateChange( state_change_event event ); void registerCommands( Plugin * p ); void unregisterCommands( Plugin * p ); // PUBLIC METHODS public: Plugin *getPluginByName (const std::string & name); + Plugin *getPluginByCommand (const std::string &command); command_result InvokeCommand( std::string & command, std::vector & parameters, bool interactive = true ); + bool CanInvokeHotkey(std::string &command, df::viewscreen *top); Plugin* operator[] (std::size_t index) { if(index >= all_plugins.size()) @@ -149,5 +180,10 @@ namespace DFHack std::vector all_plugins; std::string plugin_path; }; + + // Predefined hotkey guards + DFHACK_EXPORT bool default_hotkey(Core *, df::viewscreen *); + DFHACK_EXPORT bool dwarfmode_hotkey(Core *, df::viewscreen *); + DFHACK_EXPORT bool cursor_hotkey(Core *, df::viewscreen *); } diff --git a/library/include/dfhack/Pragma.h b/library/include/Pragma.h similarity index 100% rename from library/include/dfhack/Pragma.h rename to library/include/Pragma.h diff --git a/library/include/dfhack/SDL_fakes/events.h b/library/include/SDL_events.h similarity index 99% rename from library/include/dfhack/SDL_fakes/events.h rename to library/include/SDL_events.h index b8b8b1eb6..0457dbca1 100644 --- a/library/include/dfhack/SDL_fakes/events.h +++ b/library/include/SDL_events.h @@ -24,7 +24,7 @@ // Needed for processing its event types without polluting our namespaces with C garbage #pragma once -#include "keyboard.h" +#include "SDL_keyboard.h" namespace SDL { diff --git a/library/include/dfhack/SDL_fakes/keyboard.h b/library/include/SDL_keyboard.h similarity index 98% rename from library/include/dfhack/SDL_fakes/keyboard.h rename to library/include/SDL_keyboard.h index a49cf2517..f0d325f57 100644 --- a/library/include/dfhack/SDL_fakes/keyboard.h +++ b/library/include/SDL_keyboard.h @@ -24,7 +24,7 @@ // Needed for processing its event types without polluting our namespaces with C garbage #pragma once -#include "keysym.h" +#include "SDL_keysym.h" #include namespace SDL diff --git a/library/include/dfhack/SDL_fakes/keysym.h b/library/include/SDL_keysym.h similarity index 100% rename from library/include/dfhack/SDL_fakes/keysym.h rename to library/include/SDL_keysym.h diff --git a/library/include/dfhack/TileTypes.h b/library/include/TileTypes.h similarity index 99% rename from library/include/dfhack/TileTypes.h rename to library/include/TileTypes.h index 0fba4a696..8fe53a74e 100644 --- a/library/include/dfhack/TileTypes.h +++ b/library/include/TileTypes.h @@ -27,8 +27,8 @@ distribution. #ifndef TILETYPES_H_INCLUDED #define TILETYPES_H_INCLUDED -#include "dfhack/Pragma.h" -#include "dfhack/Export.h" +#include "Pragma.h" +#include "Export.h" namespace DFHack { diff --git a/library/include/dfhack/Types.h b/library/include/Types.h similarity index 97% rename from library/include/dfhack/Types.h rename to library/include/Types.h index 2ec35692f..9ebae4c73 100644 --- a/library/include/dfhack/Types.h +++ b/library/include/Types.h @@ -25,8 +25,8 @@ distribution. #pragma once -#include "dfhack/Pragma.h" -#include "dfhack/Export.h" +#include "Pragma.h" +#include "Export.h" namespace DFHack { diff --git a/library/include/dfhack/VersionInfo.h b/library/include/VersionInfo.h similarity index 96% rename from library/include/dfhack/VersionInfo.h rename to library/include/VersionInfo.h index 9d13c5dab..02d526730 100644 --- a/library/include/dfhack/VersionInfo.h +++ b/library/include/VersionInfo.h @@ -28,9 +28,9 @@ distribution. #ifndef MEMINFO_H_INCLUDED #define MEMINFO_H_INCLUDED -#include "dfhack/Pragma.h" -#include "dfhack/Export.h" -#include "dfhack/Types.h" +#include "Pragma.h" +#include "Export.h" +#include "Types.h" #include #include #include @@ -88,13 +88,13 @@ namespace DFHack OffsetGroup * createGroup ( const std::string & name ); int32_t getOffset (const std::string & key); - uint32_t getAddress (const std::string & key); + char * getAddress (const std::string & key); uint32_t getHexValue (const std::string & key); std::string getString (const std::string & key); OffsetGroup * getGroup ( const std::string & name ); bool getSafeOffset (const std::string & key, int32_t & out); - bool getSafeAddress (const std::string & key, uint32_t & out); + bool getSafeAddress (const std::string & key, void * & out); void setOffset (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID); void setOffsetValidity(const std::string& key, const DFHack::INVAL_TYPE inval = IS_VALID); @@ -189,7 +189,7 @@ namespace DFHack * uses memory reading directly, needs suspend. input = address of the object * fails if it's unable to read from memory */ - bool resolveObjectToClassID (const uint32_t address, int32_t & classID); + bool resolveObjectToClassID (const char * address, int32_t & classID); /** * Get a ClassID when you know the classname. can fail if the class is not in the cache diff --git a/library/include/dfhack/VersionInfoFactory.h b/library/include/VersionInfoFactory.h similarity index 97% rename from library/include/dfhack/VersionInfoFactory.h rename to library/include/VersionInfoFactory.h index 0803a2c7f..acfa36bd3 100644 --- a/library/include/dfhack/VersionInfoFactory.h +++ b/library/include/VersionInfoFactory.h @@ -28,8 +28,8 @@ distribution. #ifndef MEMINFO_MANAGER_H_INCLUDED #define MEMINFO_MANAGER_H_INCLUDED -#include "dfhack/Pragma.h" -#include "dfhack/Export.h" +#include "Pragma.h" +#include "Export.h" class TiXmlElement; namespace DFHack diff --git a/library/include/dfhack/Virtual.h b/library/include/Virtual.h similarity index 100% rename from library/include/dfhack/Virtual.h rename to library/include/Virtual.h diff --git a/library/include/dfhack/df/.gitignore b/library/include/df/.gitignore similarity index 62% rename from library/include/dfhack/df/.gitignore rename to library/include/df/.gitignore index 11c5ffbb1..7cd9ae481 100644 --- a/library/include/dfhack/df/.gitignore +++ b/library/include/df/.gitignore @@ -1,2 +1,3 @@ *.h *.inc +*.xml diff --git a/library/include/dfhack/MiscUtils.h b/library/include/dfhack/MiscUtils.h deleted file mode 100644 index adae44377..000000000 --- a/library/include/dfhack/MiscUtils.h +++ /dev/null @@ -1,269 +0,0 @@ -/* -https://github.com/peterix/dfhack -Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -/* -#include -#include -#include - -void DumpObjStr0Vector (const char * name, DFHack::Process *p, uint32_t addr) -{ - cout << "----==== " << name << " ====----" << endl; - DFHack::DfVector vect(p,addr); - for(uint32_t i = 0; i < vect.size();i++) - { - uint32_t addr = vect[i]; - cout << p->readSTLString(addr) << endl; - } - cout << endl; -} -void DumpObjVtables (const char * name, DFHack::Process *p, uint32_t addr) -{ - cout << "----==== " << name << " ====----" << endl; - DFHack::DfVector vect(p,addr); - for(uint32_t i = 0; i < vect.size();i++) - { - uint32_t addr = vect[i]; - uint32_t vptr = p->readDWord(addr); - cout << p->readClassName(vptr) << endl; - } - cout << endl; -} -void DumpDWordVector (const char * name, DFHack::Process *p, uint32_t addr) -{ - cout << "----==== " << name << " ====----" << endl; - DFHack::DfVector vect(p,addr); - for(uint32_t i = 0; i < vect.size();i++) - { - uint32_t number = vect[i]; - cout << number << endl; - } - cout << endl; -} -*/ -/* -address = absolute address of dump start -length = length in lines. 1 line = 16 bytes -*/ -/* -void hexdump (DFHack::Context *DF, uint32_t address, uint32_t length) -{ - char *buf = new char[length]; - DF->ReadRaw(address, length, (uint8_t *) buf); - uint32_t i = 0; - while (i < length) - { - // leading offset - if(i%16 == 0) - cout << "0x" << hex << setw(8) << address + i << "| "; - // bytes - for(int k = 0; k < 4; k++) - { - cout << hex << setw(2) << int(static_cast(buf[i])) << " "; - i++; - if(i == length) break; - } - if(i%16 == 0 || i>= length) - { - cout << endl; - } - else if(i%4 == 0) - { - cout << " "; - } - } - delete buf; -} - -void interleave_hex (DFHack::Context* DF, vector < uint32_t > & addresses, uint32_t length) -{ - vector bufs; - - for(uint32_t counter = 0; counter < addresses.size(); counter ++) - { - char * buf = new char[length * 16]; - DF->ReadRaw(addresses[counter], length * 16, (uint8_t *) buf); - bufs.push_back(buf); - } - cout << setfill('0'); - - // output a header - cout << "line offset "; - for (uint32_t obj = 0; obj < addresses.size(); obj++) - { - cout << "0x" << hex << setw(9) << addresses[obj] << " "; - } - cout << endl; - - for(uint32_t offs = 0 ; offs < length * 16; offs += 4) - { - if((!(offs % 16)) && offs != 0) - { - cout << endl; - } - cout << setfill(' '); - cout << dec << setw(4) << offs/4 << " "; - cout << setfill('0'); - cout << "0x" << hex << setw(4) << offs << " "; - for (uint32_t object = 0; object < bufs.size(); object++) - { - // bytes - for(int k = 0; k < 4; k++) - { - uint8_t data = bufs[object][offs + k]; - cout << hex << setw(2) << int(static_cast(data)) << " "; - } - cout << " "; - } - cout << endl; - } - for(uint32_t counter = 0; counter < addresses.size(); counter ++) - { - delete bufs[counter]; - } -} -*/ -template -void print_bits ( T val, DFHack::Console& out ) -{ - stringstream strs; - T n_bits = sizeof ( val ) * CHAR_BIT; - int cnt; - for ( unsigned i = 0; i < n_bits; ++i ) - { - cnt = i/10; - strs << cnt << " "; - } - strs << endl; - for ( unsigned i = 0; i < n_bits; ++i ) - { - cnt = i%10; - strs << cnt << " "; - } - strs << endl; - for ( unsigned i = 0; i < n_bits; ++i ) - { - strs << "--"; - } - strs << endl; - for ( unsigned i = 0; i < n_bits; ++i ) - { - strs<< !!( val & 1 ) << " "; - val >>= 1; - } - strs << endl; - out.print(strs.str().c_str()); -} - -/* -// this is probably completely bogus -std::string PrintSplatterType (int16_t mat1, int32_t mat2, vector &creature_types) -{ - std::string ret; - switch (mat1) - { - case 0: - return "Rock"; - case 1: - return "Amber"; - case 2: - return "Coral"; - case 3: - return "Green Glass"; - case 4: - return "Clear Glass"; - case 5: - return "Crystal Glass"; - case 6: - return "Water"; - case 7: - return "Coal"; - case 8: - return "Potash"; - case 9: - return "Ash"; - case 10: - return "Pearlash"; - case 11: - return "Lye"; - case 12: - return "Mud"; - case 13: - return "Vomit"; - case 14: - return "Salt"; - case 15: - return "Filth"; - case 16: - return "Frozen? Filth"; - case 18: - return "Grime"; - case 0xF2: - return "Very Specific Blood (references a named creature)"; - case 0x2A: - case 0x2B: - if(mat2 != -1) - { - ret += creature_types[mat2].id; - ret += " "; - } - ret += "Blood"; - return ret; - default: - return "Unknown"; - } -} -*/ - -//FIXME: Error 8 error C4519: default template arguments are only allowed on a class template -template -CT *binsearch_in_vector(std::vector &vec, FT CT::*field, AT value) { - int min = -1, max = (int)vec.size(); - CT **p = vec.data(); - FT key = (FT)value; - for (;;) { - int mid = (min + max)>>1; - if (mid == min) - return NULL; - FT midv = p[mid]->*field; - if (midv == key) - return p[mid]; - else if (midv < key) - min = mid; - else - max = mid; - } -} diff --git a/library/include/dfhack/Vector.h b/library/include/dfhack/Vector.h deleted file mode 100644 index ec5840a0f..000000000 --- a/library/include/dfhack/Vector.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -https://github.com/peterix/dfhack -Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#pragma once - -#ifndef DFVECTOR_H_INCLUDED -#define DFVECTOR_H_INCLUDED - -#include "dfhack/Pragma.h" -#include "dfhack/Export.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" - -#include -#include - -namespace DFHack -{ - template - class DFHACK_EXPORT DfVector - { - private: - std::vector * real_vec; - public: - DfVector(uint32_t address) - { - real_vec = (std::vector *) address; - }; - ~DfVector() - { - }; - // get offset of the specified index - inline const T& operator[] (uint32_t index) - { - // FIXME: vector out of bounds exception - //assert(index < size); - return real_vec->at(index); - }; - // get offset of the specified index - inline const T& at (uint32_t index) - { - //assert(index < size); - return real_vec->at(index); - }; - // update value at index - bool set(uint32_t index, T value) - { - if (index >= real_vec->size()) - return false; - real_vec->at(index) = value; - return true; - } - // remove value - bool remove(uint32_t index) - { - if (index >= real_vec->size()) - return false; - // Remove the item - real_vec->erase(real_vec->begin() + index); - return true; - } - // get vector size - inline uint32_t size () - { - return real_vec->size(); - }; - // get vector start - inline const T * start () - { - return real_vec->data(); - }; - }; -} -#endif // DFVECTOR_H_INCLUDED diff --git a/library/include/dfhack/extra/stopwatch.h b/library/include/dfhack/extra/stopwatch.h deleted file mode 100644 index 5ef7d11a8..000000000 --- a/library/include/dfhack/extra/stopwatch.h +++ /dev/null @@ -1,47 +0,0 @@ -// Returns the amount of milliseconds elapsed since the UNIX epoch. -// Works on both windows and linux. -// source: http://stackoverflow.com/questions/1861294/how-to-calculate-execution-time-of-a-code-snippet-in-c - -#ifndef LINUX_BUILD - #include -#else - #include - #include -#endif - -#ifdef LINUX_BUILD // Linux -uint64_t GetTimeMs64() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - uint64_t ret = tv.tv_usec; - - // Convert from micro seconds (10^-6) to milliseconds (10^-3) - ret /= 1000; - // Adds the seconds (10^0) after converting them to milliseconds (10^-3) - ret += (tv.tv_sec * 1000); - return ret; -} - - -#else // Windows -uint64_t GetTimeMs64() -{ - FILETIME ft; - LARGE_INTEGER li; - - // Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) - // and copy it to a LARGE_INTEGER structure. - GetSystemTimeAsFileTime(&ft); - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - - uint64_t ret = li.QuadPart; - // Convert from file time to UNIX epoch time. - ret -= 116444736000000000LL; - // From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals - ret /= 10000; - - return ret; -} -#endif diff --git a/library/include/dfhack/extra/termutil.h b/library/include/dfhack/extra/termutil.h deleted file mode 100644 index 702e6ba5b..000000000 --- a/library/include/dfhack/extra/termutil.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -https://github.com/peterix/dfhack -Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ -#pragma once - -#ifndef TERMUTIL_H -#define TERMUTIL_H - -#ifdef LINUX_BUILD -// FIXME: is this ever true? -bool TemporaryTerminal () -{ - return false; -} -#else -#include -#include -#include -bool TemporaryTerminal () -{ - CONSOLE_SCREEN_BUFFER_INFO csbi; - HANDLE hStdOutput; - hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - if (!GetConsoleScreenBufferInfo(hStdOutput, &csbi)) - { - printf("GetConsoleScreenBufferInfo failed: %d\n", GetLastError()); - return false; - } - return ((!csbi.dwCursorPosition.X) && (!csbi.dwCursorPosition.Y)); -}; - -#endif // LINUX_BUILD - -#endif \ No newline at end of file diff --git a/library/include/dfhack/modules/Buildings.h b/library/include/modules/Buildings.h similarity index 83% rename from library/include/dfhack/modules/Buildings.h rename to library/include/modules/Buildings.h index 112a4d927..8089fd4b1 100644 --- a/library/include/dfhack/modules/Buildings.h +++ b/library/include/modules/Buildings.h @@ -29,8 +29,8 @@ distribution. * \defgroup grp_buildings Building module parts - also includes zones and stockpiles * @ingroup grp_modules */ -#include "dfhack/Export.h" -#include "dfhack/Module.h" +#include "Export.h" +#include "Module.h" #ifdef __cplusplus namespace DFHack @@ -42,8 +42,6 @@ namespace DFHack */ struct t_building { - uint32_t origin; - uint32_t vtable; uint32_t x1; uint32_t y1; uint32_t x2; @@ -51,7 +49,8 @@ namespace DFHack uint32_t z; t_matglossPair material; uint32_t type; - // FIXME: not complete, we need building presence bitmaps for stuff like farm plots and stockpiles, orientation (N,E,S,W) and state (open/closed) + int32_t custom_type; + void * origin; }; #ifdef __cplusplus @@ -70,10 +69,9 @@ namespace DFHack bool Read (const uint32_t index, t_building & building); bool Finish(); - // read a vector of names + // read mapping from custom_type value to building RAW name + // custom_type of -1 implies ordinary building bool ReadCustomWorkshopTypes(std::map & btypes); - // returns -1 on error, >= 0 for real value - int32_t GetCustomWorkshopType(t_building & building); private: struct Private; diff --git a/library/include/dfhack/modules/Constructions.h b/library/include/modules/Constructions.h similarity index 97% rename from library/include/dfhack/modules/Constructions.h rename to library/include/modules/Constructions.h index 046d8a074..85c9175dc 100644 --- a/library/include/dfhack/modules/Constructions.h +++ b/library/include/modules/Constructions.h @@ -28,8 +28,8 @@ distribution. /* * DF constructions */ -#include "dfhack/Export.h" -#include "dfhack/Module.h" +#include "Export.h" +#include "Module.h" /** * \defgroup grp_constructions Construction module parts @@ -74,7 +74,7 @@ namespace DFHack uint32_t unk6; /// Address of the read object in DF memory. Added by DFHack. - uint32_t origin; + t_construction * origin; }; #pragma pack (pop) class DFContextShared; diff --git a/library/include/dfhack/modules/Engravings.h b/library/include/modules/Engravings.h similarity index 97% rename from library/include/dfhack/modules/Engravings.h rename to library/include/modules/Engravings.h index 0dfbb3f43..ffd050229 100644 --- a/library/include/dfhack/modules/Engravings.h +++ b/library/include/modules/Engravings.h @@ -28,8 +28,8 @@ distribution. /* * DF engravings */ -#include "dfhack/Export.h" -#include "dfhack/Module.h" +#include "Export.h" +#include "Module.h" /** * \defgroup grp_engraving Engraving module parts @@ -97,7 +97,7 @@ namespace DFHack struct dfh_engraving { t_engraving s; - uint32_t origin; + t_engraving * origin; }; /** * The Engravings module - allows reading engravings :D diff --git a/library/include/dfhack/modules/Graphic.h b/library/include/modules/Graphic.h similarity index 95% rename from library/include/dfhack/modules/Graphic.h rename to library/include/modules/Graphic.h index f9d6a88ec..6c003b4bc 100644 --- a/library/include/dfhack/modules/Graphic.h +++ b/library/include/modules/Graphic.h @@ -1,6 +1,6 @@ /* https://github.com/peterix/dfhack -Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) +Copyright (c) 2009-2011 Petr Mr�zek (peterix@gmail.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -31,8 +31,8 @@ distribution. #define CL_MOD_GRAPHIC #include -#include "dfhack/Export.h" -#include "dfhack/Module.h" +#include "Export.h" +#include "Module.h" namespace DFHack { diff --git a/library/include/dfhack/modules/Gui.h b/library/include/modules/Gui.h similarity index 97% rename from library/include/dfhack/modules/Gui.h rename to library/include/modules/Gui.h index 96f4beb9e..3d3fe81c7 100644 --- a/library/include/dfhack/modules/Gui.h +++ b/library/include/modules/Gui.h @@ -26,10 +26,10 @@ distribution. #ifndef CL_MOD_GUI #define CL_MOD_GUI -#include "dfhack/Export.h" -#include "dfhack/Module.h" -#include "dfhack/Virtual.h" -#include "dfhack/BitArray.h" +#include "Export.h" +#include "Module.h" +#include "Virtual.h" +#include "BitArray.h" #include /** diff --git a/library/include/dfhack/modules/Items.h b/library/include/modules/Items.h similarity index 99% rename from library/include/dfhack/modules/Items.h rename to library/include/modules/Items.h index f6efcc8ab..4deba6cdb 100644 --- a/library/include/dfhack/modules/Items.h +++ b/library/include/modules/Items.h @@ -26,12 +26,12 @@ distribution. /* * Items! */ -#include "dfhack/Export.h" -#include "dfhack/Module.h" -#include "dfhack/Types.h" -#include "dfhack/Virtual.h" -#include "dfhack/modules/Materials.h" -#include "dfhack/Process.h" +#include "Export.h" +#include "Module.h" +#include "Types.h" +#include "Virtual.h" +#include "modules/Materials.h" +#include "MemAccess.h" /** * \defgroup grp_items Items module and its types * @ingroup grp_modules diff --git a/library/include/dfhack/extra/MapExtras.h b/library/include/modules/MapCache.h similarity index 99% rename from library/include/dfhack/extra/MapExtras.h rename to library/include/modules/MapCache.h index 9f03d1917..ad6b91e96 100644 --- a/library/include/dfhack/extra/MapExtras.h +++ b/library/include/modules/MapCache.h @@ -26,8 +26,8 @@ distribution. #ifndef MAPEXTRAS_H #define MAPEXTRAS_H -#include "dfhack/modules/Maps.h" -#include "dfhack/TileTypes.h" +#include "modules/Maps.h" +#include "TileTypes.h" #include #include namespace MapExtras diff --git a/library/include/dfhack/modules/Maps.h b/library/include/modules/Maps.h similarity index 99% rename from library/include/dfhack/modules/Maps.h rename to library/include/modules/Maps.h index cc0c17ac3..9d60f33e5 100644 --- a/library/include/dfhack/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -30,12 +30,12 @@ distribution. #ifndef CL_MOD_MAPS #define CL_MOD_MAPS -#include "dfhack/Export.h" -#include "dfhack/Module.h" -#include "dfhack/modules/Vegetation.h" +#include "Export.h" +#include "Module.h" +#include "modules/Vegetation.h" #include -#include "dfhack/Virtual.h" -#include "dfhack/BitArray.h" +#include "Virtual.h" +#include "BitArray.h" #include "Materials.h" /** @@ -149,7 +149,7 @@ namespace DFHack /// placeholder bool discovered; /// this is NOT part of the DF feature, but an address of the feature as seen by DFhack. - uint32_t origin; + void * origin; }; diff --git a/library/include/dfhack/modules/Materials.h b/library/include/modules/Materials.h similarity index 88% rename from library/include/dfhack/modules/Materials.h rename to library/include/modules/Materials.h index 48280e7f0..25becc400 100644 --- a/library/include/dfhack/modules/Materials.h +++ b/library/include/modules/Materials.h @@ -29,16 +29,105 @@ distribution. * \defgroup grp_materials Materials module - used for reading raws mostly * @ingroup grp_modules */ -#include "dfhack/Export.h" -#include "dfhack/Module.h" -#include "dfhack/Types.h" -#include "dfhack/BitArray.h" +#include "Export.h" +#include "Module.h" +#include "Types.h" +#include "BitArray.h" + +#include "DataDefs.h" +#include "df/material.h" #include #include +namespace df +{ + struct item; + struct inorganic_raw; + struct plant_raw; + struct creature_raw; + struct historical_figure; + struct material_vec_ref; + struct job_item; + + union job_material_category; + union job_item_flags1; + union job_item_flags2; + union job_item_flags3; +} + namespace DFHack { + struct DFHACK_EXPORT MaterialInfo { + static const int NUM_BUILTIN = 19; + static const int GROUP_SIZE = 200; + static const int CREATURE_BASE = NUM_BUILTIN; + static const int FIGURE_BASE = NUM_BUILTIN + GROUP_SIZE; + static const int PLANT_BASE = NUM_BUILTIN + GROUP_SIZE*2; + static const int END_BASE = NUM_BUILTIN + GROUP_SIZE*3; + + int16_t type; + int32_t index; + + df::material *material; + + enum Mode { + Builtin, + Inorganic, + Creature, + Plant + }; + Mode mode; + + int16_t subtype; + df::inorganic_raw *inorganic; + df::creature_raw *creature; + df::plant_raw *plant; + + df::historical_figure *figure; + + public: + MaterialInfo(int16_t type = -1, int32_t index = -1) { decode(type, index); } + template MaterialInfo(T *ptr) { decode(ptr); } + + bool isValid() const { return material != NULL; } + + bool decode(int16_t type, int32_t index = -1); + bool decode(df::item *item); + bool decode(const df::material_vec_ref &vr, int idx); + + template bool decode(T *ptr) { + // Assume and exploit a certain naming convention + return ptr ? decode(ptr->mat_type, ptr->mat_index) : decode(-1); + } + + bool find(const std::string &token, const std::string &subtoken = std::string()); + bool findBuiltin(const std::string &token); + bool findInorganic(const std::string &token); + bool findPlant(const std::string &token, const std::string &subtoken); + bool findCreature(const std::string &token, const std::string &subtoken); + + std::string toString(uint16_t temp = 10015, bool named = true); + + bool isAnyCloth(); + + void getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &mask); + void getMatchBits(df::job_item_flags2 &ok, df::job_item_flags2 &mask); + void getMatchBits(df::job_item_flags3 &ok, df::job_item_flags3 &mask); + + df::craft_material_class getCraftClass(); + + bool matches(const df::job_material_category &cat); + bool matches(const df::job_item &item); + }; + + inline bool operator== (const MaterialInfo &a, const MaterialInfo &b) { + return a.type == b.type && a.index == b.index; + } + inline bool operator!= (const MaterialInfo &a, const MaterialInfo &b) { + return a.type != b.type || a.index != b.index; + } + typedef int32_t t_materialIndex; typedef int16_t t_materialType, t_itemType, t_itemSubtype; diff --git a/library/include/dfhack/modules/Notes.h b/library/include/modules/Notes.h similarity index 95% rename from library/include/dfhack/modules/Notes.h rename to library/include/modules/Notes.h index 8339c1cdc..14bb9db84 100644 --- a/library/include/dfhack/modules/Notes.h +++ b/library/include/modules/Notes.h @@ -5,8 +5,8 @@ * \defgroup grp_notes In game notes (and routes) * @ingroup grp_notes */ -#include "dfhack/Export.h" -#include "dfhack/Module.h" +#include "Export.h" +#include "Module.h" #include #include diff --git a/library/include/dfhack/modules/Translation.h b/library/include/modules/Translation.h similarity index 96% rename from library/include/dfhack/modules/Translation.h rename to library/include/modules/Translation.h index e21102d50..843d1afb9 100644 --- a/library/include/dfhack/modules/Translation.h +++ b/library/include/modules/Translation.h @@ -30,9 +30,9 @@ distribution. * @ingroup grp_modules */ -#include "dfhack/Export.h" -#include "dfhack/Module.h" -#include "dfhack/Types.h" +#include "Export.h" +#include "Module.h" +#include "Types.h" namespace DFHack { diff --git a/library/include/dfhack/modules/Units.h b/library/include/modules/Units.h similarity index 99% rename from library/include/dfhack/modules/Units.h rename to library/include/modules/Units.h index 886b2eeb9..d373b0a16 100644 --- a/library/include/dfhack/modules/Units.h +++ b/library/include/modules/Units.h @@ -28,9 +28,9 @@ distribution. /* * Creatures */ -#include "dfhack/Export.h" -#include "dfhack/Module.h" -#include "dfhack/modules/Items.h" +#include "Export.h" +#include "Module.h" +#include "modules/Items.h" /** * \defgroup grp_units Unit module parts * @ingroup grp_modules diff --git a/library/include/dfhack/modules/Vegetation.h b/library/include/modules/Vegetation.h similarity index 96% rename from library/include/dfhack/modules/Vegetation.h rename to library/include/modules/Vegetation.h index 91e6cac8c..c52d728d4 100644 --- a/library/include/dfhack/modules/Vegetation.h +++ b/library/include/modules/Vegetation.h @@ -30,9 +30,9 @@ distribution. * @ingroup grp_modules */ -#include "dfhack/Export.h" -#include "dfhack/Module.h" -#include "dfhack/Types.h" +#include "Export.h" +#include "Module.h" +#include "Types.h" namespace DFHack { /** diff --git a/library/include/dfhack/modules/Vermin.h b/library/include/modules/Vermin.h similarity index 93% rename from library/include/dfhack/modules/Vermin.h rename to library/include/modules/Vermin.h index 5fa345df0..324714f5d 100644 --- a/library/include/dfhack/modules/Vermin.h +++ b/library/include/modules/Vermin.h @@ -5,8 +5,8 @@ * \defgroup grp_vermin Wild vermin (ants, bees, etc) * @ingroup grp_vermin */ -#include "dfhack/Export.h" -#include "dfhack/Module.h" +#include "Export.h" +#include "Module.h" #ifdef __cplusplus namespace DFHack @@ -18,7 +18,7 @@ namespace DFHack */ struct t_spawnPoint { - uint32_t origin; + void * origin; int16_t race; uint16_t type; uint16_t x; @@ -76,7 +76,7 @@ namespace DFHack private: Vermin* v; - std::vector * p_sp; + std::vector * p_sp; friend class Vermin; }; diff --git a/library/include/dfhack/modules/World.h b/library/include/modules/World.h similarity index 98% rename from library/include/dfhack/modules/World.h rename to library/include/modules/World.h index 7203d775f..01ad231d0 100644 --- a/library/include/dfhack/modules/World.h +++ b/library/include/modules/World.h @@ -31,8 +31,8 @@ distribution. * @ingroup grp_modules */ -#include "dfhack/Export.h" -#include "dfhack/Module.h" +#include "Export.h" +#include "Module.h" #include namespace DFHack diff --git a/library/include/dfhack/modules/kitchen.h b/library/include/modules/kitchen.h similarity index 93% rename from library/include/dfhack/modules/kitchen.h rename to library/include/modules/kitchen.h index bb4e313c6..b169dfb3f 100644 --- a/library/include/dfhack/modules/kitchen.h +++ b/library/include/modules/kitchen.h @@ -26,13 +26,13 @@ distribution. /* * kitchen settings */ -#include "dfhack/Export.h" -#include "dfhack/Module.h" -#include "dfhack/Types.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/modules/Materials.h" -#include "dfhack/modules/Items.h" -#include +#include "Export.h" +#include "Module.h" +#include "Types.h" +#include "VersionInfo.h" +#include "modules/Materials.h" +#include "modules/Items.h" +#include "Core.h" /** * \defgroup grp_kitchen Kitchen settings * @ingroup grp_modules diff --git a/library/private/wdirent.h b/library/include/wdirent.h similarity index 100% rename from library/private/wdirent.h rename to library/include/wdirent.h diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp index 4083ac5d1..6f2b4a3f3 100644 --- a/library/modules/Buildings.cpp +++ b/library/modules/Buildings.cpp @@ -30,16 +30,26 @@ distribution. #include using namespace std; -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" -#include "dfhack/Vector.h" -#include "dfhack/Types.h" -#include "dfhack/Error.h" -#include "dfhack/modules/Buildings.h" +#include "VersionInfo.h" +#include "MemAccess.h" +#include "Types.h" +#include "Error.h" +#include "modules/Buildings.h" #include "ModuleFactory.h" -#include "dfhack/Core.h" +#include "Core.h" using namespace DFHack; +#include "DataDefs.h" +#include "df/world.h" +#include "df/world_raws.h" +#include "df/building_def.h" +#include "df/building.h" +#include "df/building_workshopst.h" + +using namespace df::enums; +using df::global::world; +using df::building_def; + //raw struct t_building_df40d { @@ -58,17 +68,10 @@ struct t_building_df40d struct Buildings::Private { - uint32_t buildings_vector; - uint32_t custom_workshop_vector; - uint32_t building_custom_workshop_type; - uint32_t custom_workshop_type; - uint32_t custom_workshop_name; - int32_t custom_workshop_id; - DfVector * p_bld; Process * owner; bool Inited; - bool hasCustomWorkshops; bool Started; + int32_t custom_workshop_id; }; Module* DFHack::createBuildings() @@ -80,37 +83,10 @@ Buildings::Buildings() { Core & c = Core::getInstance(); d = new Private; - d->p_bld = NULL; - d->Inited = d->Started = d->hasCustomWorkshops = false; - VersionInfo * mem = c.vinfo; + d->Started = false; d->owner = c.p; - OffsetGroup * OG_build = mem->getGroup("Buildings"); d->Inited = true; - try - { - d->buildings_vector = OG_build->getAddress ("buildings_vector"); - } - catch(DFHack::Error::AllMemdef &e) - { - cerr << "Buildings not available... " << e.what() << endl; - d->Inited = false; - } - if(d->Inited) - { - try - { - d->custom_workshop_vector = OG_build->getAddress("custom_workshop_vector"); - d->building_custom_workshop_type = OG_build->getOffset("building_custom_workshop_type"); - d->custom_workshop_type = OG_build->getOffset("custom_workshop_type"); - d->custom_workshop_name = OG_build->getOffset("custom_workshop_name"); - mem->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id); - d->hasCustomWorkshops = true; - } - catch(DFHack::Error::AllMemdef &e) - { - cerr << "Custom workshops not available. Memory Definition: " << e.what() << endl; - } - } + c.vinfo->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id); } Buildings::~Buildings() @@ -124,8 +100,7 @@ bool Buildings::Start(uint32_t & numbuildings) { if(!d->Inited) return false; - d->p_bld = new DfVector (d->buildings_vector); - numbuildings = d->p_bld->size(); + numbuildings = world->buildings.all.size(); d->Started = true; return true; } @@ -134,37 +109,26 @@ bool Buildings::Read (const uint32_t index, t_building & building) { if(!d->Started) return false; - t_building_df40d bld_40d; - - // read pointer from vector at position - uint32_t temp = d->p_bld->at (index); - //d->p_bld->read(index,(uint8_t *)&temp); - - //read building from memory - d->owner->read (temp, sizeof (t_building_df40d), (uint8_t *) &bld_40d); + df::building *bld_40d = world->buildings.all[index]; // transform int32_t type = -1; - d->owner->getDescriptor()->resolveObjectToClassID (temp, type); - building.origin = temp; - building.vtable = bld_40d.vtable; - building.x1 = bld_40d.x1; - building.x2 = bld_40d.x2; - building.y1 = bld_40d.y1; - building.y2 = bld_40d.y2; - building.z = bld_40d.z; - building.material = bld_40d.material; + d->owner->getDescriptor()->resolveObjectToClassID ( (char *)bld_40d, type); + building.x1 = bld_40d->x1; + building.x2 = bld_40d->x2; + building.y1 = bld_40d->y1; + building.y2 = bld_40d->y2; + building.z = bld_40d->z; + building.material.index = bld_40d->mat_index; + building.material.type = bld_40d->mat_type; building.type = type; + building.custom_type = bld_40d->getCustomType(); + building.origin = (void *) &bld_40d; return true; } bool Buildings::Finish() { - if(d->p_bld) - { - delete d->p_bld; - d->p_bld = NULL; - } d->Started = false; return true; } @@ -173,39 +137,20 @@ bool Buildings::ReadCustomWorkshopTypes(map & btypes) { if(!d->Inited) return false; - if(!d->hasCustomWorkshops) - return false; + Core & c = Core::getInstance(); Process * p = d->owner; - DfVector p_matgloss (d->custom_workshop_vector); - uint32_t size = p_matgloss.size(); + vector & bld_def = world->raws.buildings.all; + uint32_t size = bld_def.size(); btypes.clear(); - for (uint32_t i = 0; i < size;i++) + c.con.print("Probing vector at 0x%x for custom workshops.\n", &bld_def); + for (auto iter = bld_def.begin(); iter != bld_def.end();iter++) { - string out = p->readSTLString (p_matgloss[i] + d->custom_workshop_name); - uint32_t type = p->readDWord (p_matgloss[i] + d->custom_workshop_type); - #ifdef DEBUG - cout << out << ": " << type << endl; - #endif - btypes[type] = out; + building_def * temp = *iter; + btypes[temp->id] = temp->code; + c.con.print("%d : %s\n",temp->id, temp->code.c_str()); } return true; } -int32_t Buildings::GetCustomWorkshopType(t_building & building) -{ - if(!d->Inited) - return false; - if(!d->hasCustomWorkshops) - return false; - int32_t type = (int32_t)building.type; - int32_t ret = -1; - if(type != -1 && type == d->custom_workshop_id) - { - // read the custom workshop subtype - ret = (int32_t) d->owner->readDWord(building.origin + d->building_custom_workshop_type); - } - return ret; -} - diff --git a/library/modules/Constructions.cpp b/library/modules/Constructions.cpp index 079f37398..1ae5f8337 100644 --- a/library/modules/Constructions.cpp +++ b/library/modules/Constructions.cpp @@ -31,22 +31,18 @@ distribution. using namespace std; -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" -#include "dfhack/Vector.h" -#include "dfhack/Types.h" -#include "dfhack/modules/Constructions.h" +#include "VersionInfo.h" +#include "MemAccess.h" +#include "Types.h" +#include "modules/Constructions.h" #include "ModuleFactory.h" -#include "dfhack/Core.h" +#include "Core.h" using namespace DFHack; struct Constructions::Private { - uint32_t construction_vector; - // translation - DfVector * p_cons; - + vector * p_cons; Process * owner; bool Inited; bool Started; @@ -62,10 +58,9 @@ Constructions::Constructions() Core & c = Core::getInstance(); d = new Private; d->owner = c.p; - d->p_cons = 0; d->Inited = d->Started = false; VersionInfo * mem = c.vinfo; - d->construction_vector = mem->getGroup("Constructions")->getAddress ("vector"); + d->p_cons = (decltype(d->p_cons)) mem->getGroup("Constructions")->getAddress ("vector"); d->Inited = true; } @@ -78,7 +73,6 @@ Constructions::~Constructions() bool Constructions::Start(uint32_t & numconstructions) { - d->p_cons = new DfVector (d->construction_vector); numconstructions = d->p_cons->size(); d->Started = true; return true; @@ -89,24 +83,14 @@ bool Constructions::Read (const uint32_t index, t_construction & construction) { if(!d->Started) return false; - // read pointer from vector at position - uint32_t temp = d->p_cons->at (index); - - //read construction from memory - d->owner->read (temp, sizeof (t_construction), (uint8_t *) &construction); - - // transform - construction.origin = temp; + t_construction * orig = d->p_cons->at(index); + construction = *orig; + construction.origin = orig; return true; } bool Constructions::Finish() { - if(d->p_cons) - { - delete d->p_cons; - d->p_cons = NULL; - } d->Started = false; return true; } diff --git a/library/modules/Engravings.cpp b/library/modules/Engravings.cpp index 8e436b849..49588517e 100644 --- a/library/modules/Engravings.cpp +++ b/library/modules/Engravings.cpp @@ -30,21 +30,19 @@ distribution. #include using namespace std; -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" -#include "dfhack/Vector.h" -#include "dfhack/Types.h" -#include "dfhack/modules/Engravings.h" +#include "VersionInfo.h" +#include "MemAccess.h" +#include "Types.h" +#include "modules/Engravings.h" #include "ModuleFactory.h" -#include "dfhack/Core.h" +#include "Core.h" using namespace DFHack; struct Engravings::Private { uint32_t engraving_vector; - // translation - DfVector * p_engr; + vector * p_engr; Process * owner; bool Inited; @@ -61,9 +59,8 @@ Engravings::Engravings() Core & c = Core::getInstance(); d = new Private; d->owner = c.p; - d->p_engr = 0; d->Inited = d->Started = false; - d->engraving_vector = c.vinfo->getGroup("Engravings")->getAddress ("vector"); + d->p_engr = (decltype(d->p_engr)) c.vinfo->getGroup("Engravings")->getAddress ("vector"); d->Inited = true; } @@ -76,7 +73,8 @@ Engravings::~Engravings() bool Engravings::Start(uint32_t & numengravings) { - d->p_engr = new DfVector (d->engraving_vector); + if(!d->Inited) + return false; numengravings = d->p_engr->size(); d->Started = true; return true; @@ -88,13 +86,10 @@ bool Engravings::Read (const uint32_t index, dfh_engraving & engraving) if(!d->Started) return false; // read pointer from vector at position - uint32_t temp = d->p_engr->at (index); - - //read construction from memory - d->owner->read (temp, sizeof (t_engraving), (uint8_t *) &(engraving.s)); + engraving.s = *d->p_engr->at (index); // transform - engraving.origin = temp; + engraving.origin = d->p_engr->at (index); return true; } @@ -108,11 +103,6 @@ bool Engravings::Write (const dfh_engraving & engraving) bool Engravings::Finish() { - if(d->p_engr) - { - delete d->p_engr; - d->p_engr = NULL; - } d->Started = false; return true; } diff --git a/library/modules/Graphic.cpp b/library/modules/Graphic.cpp index 25ec34f7d..2d288a1ef 100644 --- a/library/modules/Graphic.cpp +++ b/library/modules/Graphic.cpp @@ -1,6 +1,6 @@ /* https://github.com/peterix/dfhack -Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) +Copyright (c) 2009-2011 Petr Mr�zek (peterix@gmail.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -33,13 +33,12 @@ distribution. #include using namespace std; -#include "dfhack/modules/Graphic.h" -#include "dfhack/Error.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" -#include "dfhack/Vector.h" +#include "modules/Graphic.h" +#include "Error.h" +#include "VersionInfo.h" +#include "MemAccess.h" #include "ModuleFactory.h" -#include +#include "Core.h" using namespace DFHack; diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index 46f0ad2ea..1a970deeb 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -30,15 +30,51 @@ distribution. #include using namespace std; -#include "dfhack/modules/Gui.h" -#include "dfhack/Process.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/Types.h" -#include "dfhack/Error.h" +#include "modules/Gui.h" +#include "MemAccess.h" +#include "VersionInfo.h" +#include "Types.h" +#include "Error.h" #include "ModuleFactory.h" -#include "dfhack/Core.h" +#include "Core.h" +#include "PluginManager.h" using namespace DFHack; +#include "DataDefs.h" +#include "df/cursor.h" +#include "df/viewscreen_dwarfmodest.h" + +// Predefined common guard functions + +bool DFHack::default_hotkey(Core *, df::viewscreen *top) +{ + // Default hotkey guard function + for (;top ;top = top->parent) + if (strict_virtual_cast(top)) + return true; + return false; +} + +bool DFHack::dwarfmode_hotkey(Core *, df::viewscreen *top) +{ + // Require the main dwarf mode screen + return !!strict_virtual_cast(top); +} + +bool DFHack::cursor_hotkey(Core *c, df::viewscreen *top) +{ + if (!dwarfmode_hotkey(c, top)) + return false; + + // Also require the cursor. + if (!df::global::cursor || df::global::cursor->x == -30000) + return false; + + return true; +} + +// + Module* DFHack::createGui() { return new Gui(); @@ -55,16 +91,23 @@ struct Gui::Private } bool Started; - uint32_t window_x_offset; - uint32_t window_y_offset; - uint32_t window_z_offset; - uint32_t cursor_xyz_offset; - uint32_t designation_xyz_offset; - uint32_t mouse_xy_offset; - uint32_t window_dims_offset; + int32_t * window_x_offset; + int32_t * window_y_offset; + int32_t * window_z_offset; + struct xyz + { + int32_t x; + int32_t y; + int32_t z; + } * cursor_xyz_offset, * designation_xyz_offset; + struct xy + { + int32_t x; + int32_t y; + } * mouse_xy_offset, * window_dims_offset; bool StartedScreen; - uint32_t screen_tiles_ptr_offset; + void * screen_tiles_ptr_offset; Process * owner; }; @@ -121,19 +164,33 @@ Gui::Gui() try { OG_Position = mem->getGroup("Position"); - d->window_x_offset = OG_Position->getAddress ("window_x"); - d->window_y_offset = OG_Position->getAddress ("window_y"); - d->window_z_offset = OG_Position->getAddress ("window_z"); - d->cursor_xyz_offset = OG_Position->getAddress ("cursor_xyz"); - d->window_dims_offset = OG_Position->getAddress ("window_dims"); + d->window_x_offset = (int32_t *) OG_Position->getAddress ("window_x"); + d->window_y_offset = (int32_t *) OG_Position->getAddress ("window_y"); + d->window_z_offset = (int32_t *) OG_Position->getAddress ("window_z"); + d->cursor_xyz_offset = (Private::xyz *) OG_Position->getAddress ("cursor_xyz"); + d->window_dims_offset = (Private::xy *) OG_Position->getAddress ("window_dims"); d->Started = true; } catch(Error::All &){}; - OG_Position->getSafeAddress("mouse_xy", d->mouse_xy_offset); - OG_Position->getSafeAddress("designation_xyz", d->designation_xyz_offset); try { - d->screen_tiles_ptr_offset = OG_Position->getAddress ("screen_tiles_pointer"); + d->mouse_xy_offset = (Private::xy *) OG_Position->getAddress ("mouse_xy"); + } + catch(Error::All &) + { + d->mouse_xy_offset = 0; + }; + try + { + d->designation_xyz_offset = (Private::xyz *) OG_Position->getAddress ("designation_xyz"); + } + catch(Error::All &) + { + d->designation_xyz_offset = 0; + }; + try + { + d->screen_tiles_ptr_offset = (void *) OG_Position->getAddress ("screen_tiles_pointer"); d->StartedScreen = true; } catch(Error::All &){}; @@ -263,10 +320,10 @@ bool Gui::getScreenTiles (int32_t width, int32_t height, t_screen screen[]) { if(!d->StartedScreen) return false; - uint32_t screen_addr = d->owner->readDWord(d->screen_tiles_ptr_offset); + void * screen_addr = (void *) d->owner->readDWord(d->screen_tiles_ptr_offset); uint8_t* tiles = new uint8_t[width*height*4/* + 80 + width*height*4*/]; - d->owner->read (screen_addr, (width*height*4/* + 80 + width*height*4*/), (uint8_t *) tiles); + d->owner->read (screen_addr, (width*height*4/* + 80 + width*height*4*/), tiles); for(int32_t iy=0; iy using namespace std; -#include "dfhack/Types.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" -#include "dfhack/Vector.h" -#include "dfhack/modules/Materials.h" -#include "dfhack/modules/Items.h" -#include "dfhack/modules/Units.h" +#include "Types.h" +#include "VersionInfo.h" +#include "MemAccess.h" +#include "modules/Materials.h" +#include "modules/Items.h" +#include "modules/Units.h" #include "ModuleFactory.h" -#include -#include +#include "Core.h" +#include "Virtual.h" using namespace DFHack; @@ -58,7 +57,7 @@ class Items::Private std::map idLookupTable; uint32_t refVectorOffset; uint32_t idFieldOffset; - uint32_t itemVectorAddress; + void * itemVectorAddress; ClassNameCheck isOwnerRefClass; ClassNameCheck isContainerRefClass; diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 5b68b384f..4d3dc1506 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -33,13 +33,12 @@ distribution. #include using namespace std; -#include "dfhack/modules/Maps.h" -#include "dfhack/Error.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" -#include "dfhack/Vector.h" +#include "modules/Maps.h" +#include "Error.h" +#include "VersionInfo.h" +#include "MemAccess.h" #include "ModuleFactory.h" -#include +#include "Core.h" #define MAPS_GUARD if(!d->Started) throw DFHack::Error::ModuleNotInitialized(); @@ -96,7 +95,7 @@ struct Maps::Private FEATURES */ // FIXME: replace with a struct pointer, eventually. needs to be mapped out first - uint32_t world_data; + char * world_data; uint32_t local_f_start; // offset from world_data // FIXME: replace by virtual function call uint32_t local_material; @@ -122,7 +121,7 @@ struct Maps::Private set unknown_veins; // map between feature address and the read object - map local_feature_store; + map local_feature_store; map > m_local_feature; vector v_global_feature; @@ -508,13 +507,13 @@ bool Maps::StartFeatures() Process * p = d->owner; Private::t_offsets &off = d->offsets; - uint32_t base = 0; - uint32_t global_feature_vector = 0; + char * base = 0; + char * global_feature_vector = 0; - uint32_t world = p->readDWord(off.world_data); + char * world = p->readPtr( (void *) off.world_data); if(!world) return false; - base = p->readDWord(world + off.local_f_start); - global_feature_vector = p->readDWord(off.world_data) + off.global_vector; + base = p->readPtr(world + off.local_f_start); + global_feature_vector = p->readPtr(off.world_data) + off.global_vector; // deref pointer to the humongo-structure if(!base) @@ -549,22 +548,21 @@ bool Maps::StartFeatures() // base = pointer to local feature structure (inside world data struct) // bigregion is 16x16 regions. for each bigregion in X dimension: - uint32_t mega_column = p->readDWord(base + bigregion_x * 4); + char * mega_column = p->readPtr(base + bigregion_x * 4); // 16B structs, second DWORD of the struct is a pointer - uint32_t loc_f_array16x16 = p->readDWord(mega_column + offset_elem + (sizeof_elem * bigregion_y)); + char * loc_f_array16x16 = p->readPtr(mega_column + offset_elem + (sizeof_elem * bigregion_y)); if(loc_f_array16x16) { - uint32_t feat_vector = loc_f_array16x16 + sizeof_16vec * sub_x + sizeof_vec * sub_y; - DfVector p_features(feat_vector); - uint32_t size = p_features.size(); + vector * p_features = (vector *) (loc_f_array16x16 + sizeof_16vec * sub_x + sizeof_vec * sub_y); + uint32_t size = p_features->size(); DFCoord pc(blockX,blockY); std::vector tempvec; for(uint32_t i = 0; i < size; i++) { - uint32_t cur_ptr = p_features[i]; + char * cur_ptr = p_features->at(i); - map ::iterator it; + map ::iterator it; it = d->local_feature_store.find(cur_ptr); // do we already have the feature? if(it != d->local_feature_store.end()) @@ -579,7 +577,7 @@ bool Maps::StartFeatures() // create, add to store t_feature tftemp; tftemp.discovered = false; //= p->readDWord(cur_ptr + 4); - tftemp.origin = cur_ptr; + tftemp.origin = (t_feature *) cur_ptr; string name = p->readClassName((void *)p->readDWord( cur_ptr )); if(name == "feature_init_deep_special_tubest") { @@ -611,17 +609,15 @@ bool Maps::StartFeatures() const uint32_t global_feature_funcptr = off.global_funcptr; const uint32_t glob_main_mat_offset = off.global_material; const uint32_t glob_sub_mat_offset = off.global_submaterial; - DfVector p_features (global_feature_vector); - + vector * p_features = (vector *) global_feature_vector; d->v_global_feature.clear(); - uint32_t size = p_features.size(); + uint32_t size = p_features->size(); d->v_global_feature.reserve(size); for(uint32_t i = 0; i < size; i++) { t_feature temp; - uint32_t feat_ptr = p->readDWord(p_features[i] + global_feature_funcptr ); + char * feat_ptr = p->readPtr(p_features->at(i) + global_feature_funcptr ); temp.origin = feat_ptr; - //temp.discovered = p->readDWord( feat_ptr + 4 ); // maybe, placeholder temp.discovered = false; // FIXME: use the memory_info cache mechanisms @@ -887,8 +883,8 @@ bool Maps::RemoveBlockEvent(uint32_t x, uint32_t y, uint32_t z, t_virtual * whic } /* - * Layer geology - */ +* Layer geology +*/ bool Maps::ReadGeology (vector < vector >& assign) { MAPS_GUARD @@ -896,17 +892,18 @@ bool Maps::ReadGeology (vector < vector >& assign) Process *p = d->owner; // get needed addresses and offsets. Now this is what I call crazy. uint16_t worldSizeX, worldSizeY; - uint32_t regions, geoblocks_vector_addr; + char *regions; + char *geoblocks_vector_addr; Private::t_offsets &off = d->offsets; // get world size - uint32_t world = p->readDWord(off.world_data); + char * world = p->readPtr(off.world_data); p->readWord (world + off.world_size_x, worldSizeX); p->readWord (world + off.world_size_y, worldSizeY); - regions = p->readDWord ( world + off.world_regions); // ptr2_region_array + regions = p->readPtr ( world + off.world_regions); // ptr2_region_array geoblocks_vector_addr = world + off.world_geoblocks_vector; // read the geoblock vector - DfVector geoblocks (geoblocks_vector_addr); + vector & geoblocks = *(vector *)(geoblocks_vector_addr); // iterate over 8 surrounding regions + local region for (int i = eNorthWest; i < eBiomeCount; i++) @@ -925,8 +922,8 @@ bool Maps::ReadGeology (vector < vector >& assign) /// regions are a 2d array. consists of pointers to arrays of regions /// regions are of region_size size // get pointer to column of regions - uint32_t geoX; - p->readDWord (regions + bioRX*4, geoX); + char * geoX; + p->readPtr (regions + bioRX*4, geoX); // get index into geoblock vector uint16_t geoindex; @@ -935,11 +932,11 @@ bool Maps::ReadGeology (vector < vector >& assign) /// geology blocks are assigned to regions from a vector // get the geoblock from the geoblock vector using the geoindex // read the matgloss pointer from the vector into temp - uint32_t geoblock_off = geoblocks[geoindex]; + char * geoblock_off = geoblocks[geoindex]; /// geology blocks have a vector of layer descriptors // get the vector with pointer to layers - DfVector geolayers (geoblock_off + off.geolayer_geoblock_offset); // let's hope + vector & geolayers = *(vector *)(geoblock_off + off.geolayer_geoblock_offset); // make sure we don't load crap assert (geolayers.size() > 0 && geolayers.size() <= 16); @@ -949,7 +946,7 @@ bool Maps::ReadGeology (vector < vector >& assign) for (uint32_t j = 0;j < geolayers.size();j++) { // read pointer to a layer - uint32_t geol_offset = geolayers[j]; + char * geol_offset = geolayers[j]; // read word at pointer + 2, store in our geology vectors d->v_geology[i].push_back (p->readWord (geol_offset + off.type_inside_geolayer)); } diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index 0c4b6f46b..92149342f 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -31,16 +31,367 @@ distribution. #include using namespace std; -#include "dfhack/Types.h" -#include "dfhack/modules/Materials.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" -#include "dfhack/Vector.h" -#include +#include "Types.h" +#include "modules/Materials.h" +#include "VersionInfo.h" +#include "MemAccess.h" +#include "Error.h" #include "ModuleFactory.h" -#include +#include "Core.h" + +#include "MiscUtils.h" + +#include "df/world.h" +#include "df/ui.h" +#include "df/item.h" +#include "df/inorganic_raw.h" +#include "df/plant_raw.h" +#include "df/plant_raw_flags.h" +#include "df/creature_raw.h" +#include "df/historical_figure.h" + +#include "df/job_item.h" +#include "df/job_material_category.h" +#include "df/matter_state.h" +#include "df/material_vec_ref.h" using namespace DFHack; +using namespace df::enums; + +bool MaterialInfo::decode(df::item *item) +{ + if (!item) + return decode(-1); + else + return decode(item->getActualMaterial(), item->getActualMaterialIndex()); +} + +bool MaterialInfo::decode(const df::material_vec_ref &vr, int idx) +{ + if (idx < 0 || idx >= vr.mat_type.size() || idx >= vr.mat_index.size()) + return decode(-1); + else + return decode(vr.mat_type[idx], vr.mat_index[idx]); +} + +bool MaterialInfo::decode(int16_t type, int32_t index) +{ + this->type = type; + this->index = index; + + material = NULL; + mode = Builtin; subtype = 0; + inorganic = NULL; plant = NULL; creature = NULL; + figure = NULL; + + df::world_raws &raws = df::global::world->raws; + + if (type < 0 || type >= sizeof(raws.mat_table.builtin)/sizeof(void*)) + return false; + + if (index < 0) + { + material = raws.mat_table.builtin[type]; + } + else if (type == 0) + { + mode = Inorganic; + inorganic = df::inorganic_raw::find(index); + if (!inorganic) + return false; + material = &inorganic->material; + } + else if (type < CREATURE_BASE) + { + material = raws.mat_table.builtin[type]; + } + else if (type < FIGURE_BASE) + { + mode = Creature; + subtype = type-CREATURE_BASE; + creature = df::creature_raw::find(index); + if (!creature || subtype >= creature->material.size()) + return false; + material = creature->material[subtype]; + } + else if (type < PLANT_BASE) + { + mode = Creature; + subtype = type-FIGURE_BASE; + figure = df::historical_figure::find(index); + if (!figure) + return false; + creature = df::creature_raw::find(figure->race); + if (!creature || subtype >= creature->material.size()) + return false; + material = creature->material[subtype]; + } + else if (type < END_BASE) + { + mode = Plant; + subtype = type-PLANT_BASE; + plant = df::plant_raw::find(index); + if (!plant || subtype >= plant->material.size()) + return false; + material = plant->material[subtype]; + } + else + { + material = raws.mat_table.builtin[type]; + } + + return (material != NULL); +} + +bool MaterialInfo::find(const std::string &token, const std::string &subtoken) +{ + if (findBuiltin(token)) + return true; + if (subtoken.empty()) + { + if (findInorganic(token)) + return true; + } + else + { + if (findPlant(token, subtoken)) + return true; + if (findCreature(token, subtoken)) + return true; + } + return false; +} + +bool MaterialInfo::findBuiltin(const std::string &token) +{ + df::world_raws &raws = df::global::world->raws; + for (int i = 1; i < NUM_BUILTIN; i++) + if (raws.mat_table.builtin[i]->id == token) + return decode(i, -1); + return decode(-1); +} + +bool MaterialInfo::findInorganic(const std::string &token) +{ + df::world_raws &raws = df::global::world->raws; + for (unsigned i = 0; i < raws.inorganics.size(); i++) + { + df::inorganic_raw *p = raws.inorganics[i]; + if (p->id == token) + return decode(0, i); + } + return decode(-1); +} + +bool MaterialInfo::findPlant(const std::string &token, const std::string &subtoken) +{ + df::world_raws &raws = df::global::world->raws; + for (unsigned i = 0; i < raws.plants.all.size(); i++) + { + df::plant_raw *p = raws.plants.all[i]; + if (p->id != token) + continue; + + for (unsigned j = 0; j < p->material.size(); j++) + if (p->material[j]->id == subtoken) + return decode(PLANT_BASE+j, i); + + break; + } + return decode(-1); +} + +bool MaterialInfo::findCreature(const std::string &token, const std::string &subtoken) +{ + df::world_raws &raws = df::global::world->raws; + for (unsigned i = 0; i < raws.creatures.all.size(); i++) + { + df::creature_raw *p = raws.creatures.all[i]; + if (p->creature_id != token) + continue; + + for (unsigned j = 0; j < p->material.size(); j++) + if (p->material[j]->id == subtoken) + return decode(CREATURE_BASE+j, i); + + break; + } + return decode(-1); +} + +std::string MaterialInfo::toString(uint16_t temp, bool named) +{ + if (type == -1) + return "NONE"; + if (!material) + return stl_sprintf("INVALID %d:%d", type, index); + + df::matter_state state = matter_state::Solid; + if (temp >= material->heat.melting_point) + state = matter_state::Liquid; + if (temp >= material->heat.boiling_point) + state = matter_state::Gas; + + std::string name = material->state_name[state]; + if (!material->prefix.empty()) + name = material->prefix + " " + name; + + if (named && figure) + name += stl_sprintf(" of HF %d", index); + return name; +} + +df::craft_material_class MaterialInfo::getCraftClass() +{ + if (!material) + return craft_material_class::None; + + if (type == 0 && index == -1) + return craft_material_class::Stone; + + FOR_ENUM_ITEMS(material_flags, i) + { + df::craft_material_class ccv = ENUM_ATTR(material_flags, type, i); + if (ccv == craft_material_class::None) + continue; + if (material->flags.is_set(i)) + return ccv; + } + + return craft_material_class::None; +} + +bool MaterialInfo::isAnyCloth() +{ + using namespace df::enums::material_flags; + + return material && ( + material->flags.is_set(THREAD_PLANT) || + material->flags.is_set(SILK) || + material->flags.is_set(YARN) + ); +} + +bool MaterialInfo::matches(const df::job_material_category &cat) +{ + if (!material) + return false; + + using namespace df::enums::material_flags; +#define TEST(bit,flag) if (cat.bits.bit && material->flags.is_set(flag)) return true; + TEST(plant, STRUCTURAL_PLANT_MAT); + TEST(wood, WOOD); + TEST(cloth, THREAD_PLANT); + TEST(silk, SILK); + TEST(leather, LEATHER); + TEST(bone, BONE); + TEST(shell, SHELL); + TEST(wood2, WOOD); + TEST(soap, SOAP); + TEST(tooth, TOOTH); + TEST(horn, HORN); + TEST(pearl, PEARL); + TEST(yarn, YARN); +#undef TEST + return false; +} + +bool MaterialInfo::matches(const df::job_item &item) +{ + if (!isValid()) return false; + + df::job_item_flags1 ok1, mask1; + getMatchBits(ok1, mask1); + + df::job_item_flags2 ok2, mask2; + getMatchBits(ok2, mask2); + + df::job_item_flags3 ok3, mask3; + getMatchBits(ok3, mask3); + + return ((item.flags1.whole & mask1.whole) == (item.flags1.whole & ok1.whole)) && + ((item.flags2.whole & mask2.whole) == (item.flags2.whole & ok2.whole)) && + ((item.flags3.whole & mask3.whole) == (item.flags3.whole & ok3.whole)); +} + +void MaterialInfo::getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &mask) +{ + ok.whole = mask.whole = 0; + if (!isValid()) return; + +#define MAT_FLAG(name) material->flags.is_set(df::enums::material_flags::name) +#define FLAG(field, name) (field && field->flags.is_set(name)) +#define TEST(bit, check) \ + mask.bits.bit = true; ok.bits.bit = !!(check); + + bool structural = MAT_FLAG(STRUCTURAL_PLANT_MAT); + + TEST(millable, structural && FLAG(plant, plant_raw_flags::MILL)); + TEST(sharpenable, MAT_FLAG(IS_STONE)); + TEST(distillable, structural && FLAG(plant, plant_raw_flags::DRINK)); + TEST(processable, structural && FLAG(plant, plant_raw_flags::THREAD)); + TEST(bag, isAnyCloth()); + TEST(cookable, MAT_FLAG(EDIBLE_COOKED)); + TEST(extract_bearing_plant, structural && FLAG(plant, plant_raw_flags::EXTRACT_STILL_VIAL)); + TEST(extract_bearing_fish, false); + TEST(extract_bearing_vermin, false); + TEST(processable_to_vial, structural && FLAG(plant, plant_raw_flags::EXTRACT_VIAL)); + TEST(processable_to_bag, structural && FLAG(plant, plant_raw_flags::LEAVES)); + TEST(processable_to_barrel, structural && FLAG(plant, plant_raw_flags::EXTRACT_BARREL)); + TEST(solid, !(MAT_FLAG(ALCOHOL_PLANT) || + MAT_FLAG(ALCOHOL_CREATURE) || + MAT_FLAG(LIQUID_MISC_PLANT) || + MAT_FLAG(LIQUID_MISC_CREATURE) || + MAT_FLAG(LIQUID_MISC_OTHER))); + TEST(tameable_vermin, false); + TEST(sharpenable, MAT_FLAG(IS_GLASS)); + TEST(milk, linear_index(material->reaction_product.id, std::string("CHEESE_MAT")) >= 0); + //04000000 - "milkable" - vtable[107],1,1 +} + +void MaterialInfo::getMatchBits(df::job_item_flags2 &ok, df::job_item_flags2 &mask) +{ + ok.whole = mask.whole = 0; + if (!isValid()) return; + + bool is_cloth = isAnyCloth(); + + TEST(dye, MAT_FLAG(IS_DYE)); + TEST(dyeable, is_cloth); + TEST(dyed, is_cloth); + TEST(sewn_imageless, is_cloth); + TEST(glass_making, MAT_FLAG(CRYSTAL_GLASSABLE)); + + TEST(fire_safe, material->heat.melting_point > 11000); + TEST(magma_safe, material->heat.melting_point > 12000); + TEST(deep_material, FLAG(inorganic, df::enums::inorganic_flags::DEEP_ANY)); + TEST(non_economic, inorganic && !(df::global::ui && df::global::ui->economic_stone[index])); + + TEST(plant, plant); + TEST(silk, MAT_FLAG(SILK)); + TEST(leather, MAT_FLAG(LEATHER)); + TEST(bone, MAT_FLAG(BONE)); + TEST(shell, MAT_FLAG(SHELL)); + TEST(totemable, false); + TEST(horn, MAT_FLAG(HORN)); + TEST(pearl, MAT_FLAG(PEARL)); + TEST(soap, MAT_FLAG(SOAP)); + TEST(ivory_tooth, MAT_FLAG(TOOTH)); + //TEST(hair_wool, MAT_FLAG(YARN)); + TEST(yarn, MAT_FLAG(YARN)); +} + +void MaterialInfo::getMatchBits(df::job_item_flags3 &ok, df::job_item_flags3 &mask) +{ + ok.whole = mask.whole = 0; + if (!isValid()) return; + + TEST(hard, MAT_FLAG(ITEMS_HARD)); +} + +#undef MAT_FLAG +#undef FLAG +#undef TEST Module* DFHack::createMaterials() { @@ -52,8 +403,8 @@ class Materials::Private public: Process * owner; OffsetGroup * OG_Materials; - uint32_t vector_races; - uint32_t vector_other; + void * vector_races; + void * vector_other; }; Materials::Materials() @@ -67,10 +418,10 @@ Materials::Materials() df_inorganic = 0; OffsetGroup *OG_Materials = d->OG_Materials = c.vinfo->getGroup("Materials"); { - OG_Materials->getSafeAddress("inorganics",(uint32_t &)df_inorganic); - OG_Materials->getSafeAddress("organics_all",(uint32_t &)df_organic); - OG_Materials->getSafeAddress("organics_plants",(uint32_t &)df_plants); - OG_Materials->getSafeAddress("organics_trees",(uint32_t &)df_trees); + OG_Materials->getSafeAddress("inorganics",(void * &)df_inorganic); + OG_Materials->getSafeAddress("organics_all",(void * &)df_organic); + OG_Materials->getSafeAddress("organics_plants",(void * &)df_plants); + OG_Materials->getSafeAddress("organics_trees",(void * &)df_trees); d->vector_races = OG_Materials->getAddress("creature_type_vector"); } } @@ -111,16 +462,16 @@ bool t_matglossInorganic::isGem() } // good for now -inline bool ReadNamesOnly(Process* p, uint32_t address, vector & names) +inline bool ReadNamesOnly(Process* p, void * address, vector & names) { - DfVector p_matgloss (address); - uint32_t size = p_matgloss.size(); + vector * p_names = (vector *) address; + uint32_t size = p_names->size(); names.clear(); names.reserve (size); for (uint32_t i = 0; i < size;i++) { t_matgloss mat; - mat.id = *(std::string *)p_matgloss[i]; + mat.id = *p_names->at(i); names.push_back(mat); } return true; @@ -159,21 +510,21 @@ bool Materials::CopyInorganicMaterials (std::vector & inorg bool Materials::CopyOrganicMaterials (std::vector & organic) { if(df_organic) - return ReadNamesOnly(d->owner, (uint32_t) df_organic, organic ); + return ReadNamesOnly(d->owner, (void *) df_organic, organic ); else return false; } bool Materials::CopyWoodMaterials (std::vector & tree) { if(df_trees) - return ReadNamesOnly(d->owner, (uint32_t) df_trees, tree ); + return ReadNamesOnly(d->owner, (void *) df_trees, tree ); else return false; } bool Materials::CopyPlantMaterials (std::vector & plant) { if(df_plants) - return ReadNamesOnly(d->owner, (uint32_t) df_plants, plant ); + return ReadNamesOnly(d->owner, (void *) df_plants, plant ); else return false; } @@ -185,7 +536,7 @@ bool Materials::ReadCreatureTypes (void) bool Materials::ReadOthers(void) { Process * p = d->owner; - uint32_t matBase = d->OG_Materials->getAddress ("other"); + char * matBase = d->OG_Materials->getAddress ("other"); uint32_t i = 0; std::string * ptr; @@ -194,7 +545,7 @@ bool Materials::ReadOthers(void) while(1) { t_matglossOther mat; - ptr = (std::string *) p->readDWord(matBase + i*4); + ptr = (std::string *) p->readPtr(matBase + i*4); if(ptr==0) break; mat.id = *ptr; @@ -208,7 +559,7 @@ bool Materials::ReadDescriptorColors (void) { Process * p = d->owner; OffsetGroup * OG_Descriptors = p->getDescriptor()->getGroup("Materials")->getGroup("descriptors"); - DfVector p_colors (OG_Descriptors->getAddress ("colors_vector")); + vector & p_colors = *(vector *) OG_Descriptors->getAddress ("colors_vector"); uint32_t size = p_colors.size(); color.clear(); @@ -237,7 +588,7 @@ bool Materials::ReadCreatureTypesEx (void) uint32_t sizeof_string = OG_string->getHexValue ("sizeof"); OffsetGroup * OG_Mats = mem->getGroup("Materials"); - DfVector p_races (OG_Mats->getAddress ("creature_type_vector")); + vector & p_races = *(vector *) OG_Mats->getAddress ("creature_type_vector"); OffsetGroup * OG_Creature = OG_Mats->getGroup("creature"); uint32_t castes_vector_offset = OG_Creature->getOffset ("caste_vector"); @@ -287,13 +638,13 @@ bool Materials::ReadCreatureTypesEx (void) mat.tilecolor.back = p->readWord( p_races[i] + tile_color_offset + 2 ); mat.tilecolor.bright = p->readWord( p_races[i] + tile_color_offset + 4 ); - DfVector p_castes(p_races[i] + castes_vector_offset); + vector & p_castes = *(vector *) (p_races[i] + castes_vector_offset); sizecas = p_castes.size(); for (uint32_t j = 0; j < sizecas;j++) { /* caste name */ t_creaturecaste caste; - uint32_t caste_start = p_castes[j]; + char * caste_start = p_castes[j]; caste.id = p->readSTLString (caste_start); caste.singular = p->readSTLString (caste_start + sizeof_string); caste.plural = p->readSTLString (caste_start + 2 * sizeof_string); @@ -303,13 +654,13 @@ bool Materials::ReadCreatureTypesEx (void) { /* color mod reading */ // Caste + offset > color mod vector - DfVector p_colormod(caste_start + caste_colormod_offset); + vector & p_colormod = *(vector *) (caste_start + caste_colormod_offset); sizecolormod = p_colormod.size(); caste.ColorModifier.resize(sizecolormod); for(uint32_t k = 0; k < sizecolormod;k++) { // color mod [0] -> color list - DfVector p_colorlist(p_colormod[k]); + vector & p_colorlist = *(vector *) (p_colormod[k]); sizecolorlist = p_colorlist.size(); caste.ColorModifier[k].colorlist.resize(sizecolorlist); for(uint32_t l = 0; l < sizecolorlist; l++) @@ -320,7 +671,7 @@ bool Materials::ReadCreatureTypesEx (void) caste.ColorModifier[k].enddate = p->readDWord( p_colormod[k] + color_modifier_enddate_offset ); } /* body parts */ - DfVector p_bodypart(caste_start + caste_bodypart_offset); + vector & p_bodypart = *(vector *) (caste_start + caste_bodypart_offset); caste.bodypart.empty(); sizebp = p_bodypart.size(); for(uint32_t k = 0; k < sizebp; k++) @@ -338,7 +689,7 @@ bool Materials::ReadCreatureTypesEx (void) } mat.castes.push_back(caste); } - DfVector p_extract(p_races[i] + extract_vector_offset); + vector & p_extract = *(vector *) (p_races[i] + extract_vector_offset); for(uint32_t j = 0; j < p_extract.size(); j++) { t_creatureextract extract; diff --git a/library/modules/Notes.cpp b/library/modules/Notes.cpp index 293077a5d..bcfe6aa68 100644 --- a/library/modules/Notes.cpp +++ b/library/modules/Notes.cpp @@ -29,13 +29,13 @@ distribution. #include using namespace std; -#include "dfhack/VersionInfo.h" -#include "dfhack/Types.h" -#include "dfhack/Error.h" -#include "dfhack/Process.h" +#include "VersionInfo.h" +#include "Types.h" +#include "Error.h" +#include "MemAccess.h" #include "ModuleFactory.h" -#include "dfhack/Core.h" -#include "dfhack/modules/Notes.h" +#include "Core.h" +#include "modules/Notes.h" using namespace DFHack; Module* DFHack::createNotes() diff --git a/library/modules/Translation.cpp b/library/modules/Translation.cpp index 57fcd8757..6df7c7f24 100644 --- a/library/modules/Translation.cpp +++ b/library/modules/Translation.cpp @@ -30,13 +30,12 @@ distribution. #include using namespace std; -#include "dfhack/modules/Translation.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" -#include "dfhack/Vector.h" -#include "dfhack/Types.h" +#include "modules/Translation.h" +#include "VersionInfo.h" +#include "MemAccess.h" +#include "Types.h" #include "ModuleFactory.h" -#include +#include "Core.h" using namespace DFHack; Module* DFHack::createTranslation() @@ -46,8 +45,8 @@ Module* DFHack::createTranslation() struct Translation::Private { - uint32_t genericAddress; - uint32_t transAddress; + void * genericAddress; + void * transAddress; uint32_t word_table_offset; uint32_t sizeof_string; @@ -97,15 +96,15 @@ bool Translation::Start() return false; Process * p = c.p; Finish(); - DfVector genericVec (d->genericAddress); - DfVector transVec (d->transAddress); + vector & genericVec = *(vector *) d->genericAddress; + vector & transVec = *(vector *) d->transAddress; DFDict & translations = d->dicts.translations; DFDict & foreign_languages = d->dicts.foreign_languages; translations.resize(10); for (uint32_t i = 0;i < genericVec.size();i++) { - uint32_t genericNamePtr = genericVec.at(i); + char * genericNamePtr = genericVec[i]; for(int j=0; j<10;j++) { string word = p->readSTLString (genericNamePtr + j * d->sizeof_string); @@ -116,11 +115,11 @@ bool Translation::Start() foreign_languages.resize(transVec.size()); for (uint32_t i = 0; i < transVec.size();i++) { - uint32_t transPtr = transVec.at(i); - DfVector trans_names_vec (transPtr + d->word_table_offset); + char * transPtr = transVec.at(i); + vector & trans_names_vec = *(vector *) (transPtr + d->word_table_offset); for (uint32_t j = 0;j < trans_names_vec.size();j++) { - uint32_t transNamePtr = trans_names_vec.at(j); + void * transNamePtr = trans_names_vec[j]; string name = p->readSTLString (transNamePtr); foreign_languages[i].push_back (name); } diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 9a6a09065..2d68be559 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -34,18 +34,17 @@ distribution. using namespace std; -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" -#include "dfhack/Vector.h" -#include "dfhack/Error.h" -#include "dfhack/Types.h" +#include "VersionInfo.h" +#include "MemAccess.h" +#include "Error.h" +#include "Types.h" // we connect to those -#include "dfhack/modules/Materials.h" -#include "dfhack/modules/Units.h" -#include "dfhack/modules/Translation.h" +#include "modules/Materials.h" +#include "modules/Units.h" +#include "modules/Translation.h" #include "ModuleFactory.h" -#include +#include "Core.h" using namespace DFHack; @@ -54,8 +53,8 @@ struct Units::Private bool Inited; bool Started; - uint32_t dwarf_race_index_addr; - uint32_t dwarf_civ_id_addr; + void * dwarf_race_index_addr; + void * dwarf_civ_id_addr; bool IdMapReady; std::map IdMap; @@ -86,8 +85,8 @@ Units::Units() try { creatures = (vector *) OG_Creatures->getAddress ("vector"); - d->dwarf_race_index_addr = OG_Creatures->getAddress("current_race"); - d->dwarf_civ_id_addr = OG_Creatures->getAddress("current_civ"); + d->dwarf_race_index_addr = (void *) OG_Creatures->getAddress("current_race"); + d->dwarf_civ_id_addr = (void *) OG_Creatures->getAddress("current_civ"); } catch(Error::All&){}; d->Inited = true; diff --git a/library/modules/Vegetation.cpp b/library/modules/Vegetation.cpp index b581928a9..fe07d97b8 100644 --- a/library/modules/Vegetation.cpp +++ b/library/modules/Vegetation.cpp @@ -30,14 +30,13 @@ distribution. #include using namespace std; -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" -#include "dfhack/Vector.h" -#include "dfhack/Types.h" -#include "dfhack/modules/Vegetation.h" -#include "dfhack/modules/Translation.h" +#include "VersionInfo.h" +#include "MemAccess.h" +#include "Types.h" +#include "modules/Vegetation.h" +#include "modules/Translation.h" #include "ModuleFactory.h" -#include +#include "Core.h" using namespace DFHack; Module* DFHack::createVegetation() diff --git a/library/modules/Vermin.cpp b/library/modules/Vermin.cpp index 67fd623e4..215815eb0 100644 --- a/library/modules/Vermin.cpp +++ b/library/modules/Vermin.cpp @@ -29,18 +29,18 @@ distribution. #include using namespace std; -#include "dfhack/VersionInfo.h" -#include "dfhack/Types.h" -#include "dfhack/Error.h" -#include "dfhack/Process.h" -#include "dfhack/modules/Vermin.h" +#include "VersionInfo.h" +#include "Types.h" +#include "Error.h" +#include "MemAccess.h" +#include "modules/Vermin.h" #include "ModuleFactory.h" -#include "dfhack/Core.h" +#include "Core.h" using namespace DFHack; struct Vermin::Private { - uint32_t spawn_points_vector; + void * spawn_points_vector; uint32_t race_offset; uint32_t type_offset; uint32_t position_offset; @@ -106,7 +106,6 @@ SpawnPoints* Vermin::getSpawnPoints() cerr << "Couldn't get spawn points: Vermin module not inited" << endl; return NULL; } - return new SpawnPoints(this); } @@ -120,15 +119,11 @@ SpawnPoints::SpawnPoints(Vermin* v_) cerr << "Couldn't get spawn points: Vermin module not inited" << endl; return; } - - //p_sp = new DfVector (v->d->spawn_points_vector); - //p_sp = new vector (v->d->spawn_points_vector); - p_sp = (vector *) (v->d->spawn_points_vector); + p_sp = (vector *) (v->d->spawn_points_vector); } SpawnPoints::~SpawnPoints() { - // Do NOT delete p_sp; it's a pointer to memory the game owns. } size_t SpawnPoints::size() @@ -145,7 +140,7 @@ bool SpawnPoints::Read (const uint32_t index, t_spawnPoint & sp) return false; // read pointer from vector at position - uint32_t temp = (uint32_t) p_sp->at (index); + char * temp = p_sp->at (index); sp.origin = temp; sp.race = v->d->owner->readWord(temp + v->d->race_offset); @@ -166,7 +161,7 @@ bool SpawnPoints::Write (const uint32_t index, t_spawnPoint & sp) return false; // read pointer from vector at position - uint32_t temp = (uint32_t) p_sp->at (index); + char * temp = p_sp->at (index); v->d->owner->writeWord(temp + v->d->race_offset, sp.race); v->d->owner->writeWord(temp + v->d->type_offset, sp.type); diff --git a/library/modules/World.cpp b/library/modules/World.cpp index bb6c3bfaf..5d1292a9e 100644 --- a/library/modules/World.cpp +++ b/library/modules/World.cpp @@ -30,13 +30,13 @@ distribution. #include using namespace std; -#include "dfhack/modules/World.h" -#include "dfhack/Process.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/Types.h" -#include "dfhack/Error.h" +#include "modules/World.h" +#include "MemAccess.h" +#include "VersionInfo.h" +#include "Types.h" +#include "Error.h" #include "ModuleFactory.h" -#include +#include "Core.h" using namespace DFHack; @@ -54,22 +54,22 @@ struct World::Private bool Inited; bool PauseInited; - uint32_t pause_state_offset; + void * pause_state_offset; bool StartedTime; - uint32_t year_offset; - uint32_t tick_offset; + void * year_offset; + void * tick_offset; bool StartedWeather; - uint32_t weather_offset; + char * weather_offset; bool StartedMode; - uint32_t gamemode_offset; - uint32_t controlmode_offset; - uint32_t controlmodecopy_offset; + void * gamemode_offset; + void * controlmode_offset; + void * controlmodecopy_offset; bool StartedFolder; - uint32_t folder_name_offset; + void * folder_name_offset; Process * owner; }; diff --git a/library/modules/kitchen.cpp b/library/modules/kitchen.cpp index c98684e08..fbf11a079 100644 --- a/library/modules/kitchen.cpp +++ b/library/modules/kitchen.cpp @@ -9,17 +9,16 @@ #include using namespace std; -#include "dfhack/Types.h" -#include "dfhack/VersionInfo.h" -#include "dfhack/Process.h" -#include "dfhack/Vector.h" -#include "dfhack/modules/Materials.h" -#include "dfhack/modules/Items.h" -#include "dfhack/modules/Units.h" -#include "dfhack/modules/kitchen.h" +#include "Types.h" +#include "VersionInfo.h" +#include "MemAccess.h" +#include "modules/Materials.h" +#include "modules/Items.h" +#include "modules/Units.h" +#include "modules/kitchen.h" #include "ModuleFactory.h" -#include -#include +#include "Core.h" +#include "Virtual.h" namespace DFHack { @@ -44,9 +43,9 @@ namespace Kitchen std::vector& materialIndices; // the material index vector of the kitchen exclusion list std::vector& exclusionTypes; // the exclusion type vector of the kitchen excluions list - static uint32_t addr(const DFHack::Core& core, int index) + static void * addr(const DFHack::Core& core, int index) { - static uint32_t start = core.vinfo->getAddress("kitchen_limits"); + static char * start = core.vinfo->getAddress("kitchen_limits"); return start + sizeof(std::vector) * index; }; }; diff --git a/library/xml b/library/xml new file mode 160000 index 000000000..d03375ddb --- /dev/null +++ b/library/xml @@ -0,0 +1 @@ +Subproject commit d03375ddbd695fda2deb42dd13aa352efccebc60 diff --git a/library/xml/codegen.pl b/library/xml/codegen.pl deleted file mode 100755 index 05684732b..000000000 --- a/library/xml/codegen.pl +++ /dev/null @@ -1,944 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; - -use XML::LibXML; - -my $input_dir = $ARGV[0] || '.'; -my $output_dir = $ARGV[1] || 'codegen'; -my $main_namespace = $ARGV[2] || 'df'; -my $export_prefix = 'DFHACK_EXPORT '; - -my %types; -my %type_files; - -# Misc XML analysis - -our $typename; -our $filename; - -sub parse_address($;$) { - my ($str,$in_bits) = @_; - return undef unless defined $str; - - # Parse the format used by offset attributes in xml - $str =~ /^0x([0-9a-f]+)(?:\.([0-7]))?$/ - or die "Invalid address syntax: $str\n"; - my ($full, $bv) = ($1, $2); - die "Bits not allowed: $str\n" unless $in_bits; - return $in_bits ? (hex($full)*8 + ($bv||0)) : hex($full); -} - -sub check_bad_attrs($;$$) { - my ($tag, $allow_size, $allow_align) = @_; - - die "Cannot use size, alignment or offset for ".$tag->nodeName."\n" - if ((!$allow_size && defined $tag->getAttribute('size')) || - defined $tag->getAttribute('offset') || - (!$allow_align && defined $tag->getAttribute('alignment'))); -} - -sub check_name($) { - my ($name) = @_; - $name =~ /^[_a-zA-Z][_a-zA-Z0-9]*$/ - or die "Invalid identifier: $name\n"; - return $name; -} - -sub is_attr_true($$) { - my ($tag, $name) = @_; - return ($tag->getAttribute($name)||'') eq 'true'; -} - -sub type_header_def($) { - my ($name) = @_; - return uc($main_namespace).'_'.uc($name).'_H'; -} - -sub translate_lookup($) { - my ($str) = @_; - return undef unless $str && $str =~ /^\$global((\.[_a-zA-Z0-9]+)+)$/; - my @fields = split /\./, substr($1,1); - my $expr = "df::global::".shift(@fields); - for my $fn (@fields) { - $expr = "_toref($expr).$fn"; - } - return $expr; -} - -# Text generation with indentation - -our @lines; -our $indentation = 0; - -sub with_emit(&;$) { - # Executes the code block, and returns emitted lines - my ($blk, $start_indent) = @_; - local @lines; - local $indentation = ($start_indent||0); - $blk->(); - return @lines; -} - -sub emit(@) { - # Emit an indented line to be returned from with_emit - my $line = join('',map { defined($_) ? $_ : '' } @_); - $line = (' 'x$indentation).$line unless length($line) == 0; - push @lines, $line; -} - -sub indent(&) { - # Indent lines emitted from the block by one step - my ($blk) = @_; - local $indentation = $indentation+2; - $blk->(); -} - -sub outdent(&) { - # Unindent lines emitted from the block by one step - my ($blk) = @_; - local $indentation = ($indentation >= 2 ? $indentation-2 : 0); - $blk->(); -} - -sub emit_block(&;$$) { - # Emit a full {...} block with indentation - my ($blk, $prefix, $suffix) = @_; - $prefix ||= ''; - $suffix ||= ''; - emit $prefix,'{'; - &indent($blk); - emit '}',$suffix; -} - -# Static file output - -my @static_lines; -my %static_includes; - -sub with_emit_static(&) { - my ($blk) = @_; - $static_includes{$typename}++; - push @static_lines, &with_emit($blk,2); -} - -# Anonymous variable names - -our $anon_id = 0; -our $anon_prefix; - -sub ensure_name($) { - # If the name is empty, assign an auto-generated one - my ($name) = @_; - unless ($name) { - $name = $anon_prefix.(($anon_id == 0) ? '' : '_'.$anon_id); - $anon_id++; - } - return check_name($name); -} - -sub with_anon(&;$) { - # Establish a new anonymous namespace - my ($blk,$stem) = @_; - local $anon_id = $stem ? 0 : 1; - local $anon_prefix = ($stem||'anon'); - $blk->(); -} - -# Primitive types - -my @primitive_type_list = - qw(int8_t uint8_t int16_t uint16_t - int32_t uint32_t int64_t uint64_t - s-float - bool ptr-string stl-string flag-bit - pointer); - -my %primitive_aliases = ( - 'stl-string' => 'std::string', - 'ptr-string' => 'char*', - 'flag-bit' => 'void', - 'pointer' => 'void*', - 's-float' => 'float', -); - -my %primitive_types; -$primitive_types{$_}++ for @primitive_type_list; - -sub primitive_type_name($) { - my ($tag_name) = @_; - $primitive_types{$tag_name} - or die "Not primitive: $tag_name\n"; - return $primitive_aliases{$tag_name} || $tag_name; -} - -# Type references - -our %weak_refs; -our %strong_refs; - -sub register_ref($;$) { - # Register a reference to another type. - # Strong ones require the type to be included. - my ($ref, $is_strong) = @_; - - if ($ref) { - my $type = $types{$ref} - or die "Unknown type $ref referenced.\n"; - - if ($is_strong) { - $strong_refs{$ref}++; - } else { - $weak_refs{$ref}++; - } - } -} - -# Determines if referenced other types should be included or forward-declared -our $is_strong_ref = 1; - -sub with_struct_block(&$;$%) { - my ($blk, $tag, $name, %flags) = @_; - - my $kwd = (is_attr_true($tag,'is-union') ? "union" : "struct"); - my $exp = $flags{-export} ? $export_prefix : ''; - my $prefix = $kwd.' '.$exp.($name ? $name.' ' : ''); - - emit_block { - local $_; - local $is_strong_ref = 1; # reset the state - if ($flags{-no_anon}) { - $blk->(); - } else { - &with_anon($blk); - } - } $prefix, ";"; -} - -sub decode_type_name_ref($;%) { - # Interpret the type-name field of a tag - my ($tag,%flags) = @_; - my $force_type = $flags{-force_type}; - my $force_strong = $flags{-force_strong}; - my $tname = $tag->getAttribute($flags{-attr_name} || 'type-name') - or return undef; - - if ($primitive_types{$tname}) { - die "Cannot use type $tname as type-name of ".$tag->nodeName."\n" - if ($force_type && $force_type ne 'primitive'); - return primitive_type_name($tname); - } else { - register_ref $tname, ($force_strong||$is_strong_ref); - die "Cannot use type $tname as type-name of ".$tag->nodeName."\n" - if ($force_type && $force_type ne $types{$tname}->nodeName); - return $main_namespace.'::'.$tname; - } -} - -# CONDITIONALS - -sub is_conditional($) { - my ($tag) = @_; - return $tag->nodeName =~ /^(cond-if|cond-elseif)$/; -} - -sub translate_if_cond($) { - my ($tag) = @_; - - my @rules; - if (my $defvar = $tag->getAttribute('defined')) { - push @rules, "defined($defvar)"; - } - if (my $cmpvar = $tag->getAttribute('var')) { - if (my $cmpval = $tag->getAttribute('lt')) { - push @rules, "($cmpvar < $cmpval)"; - } - if (my $cmpval = $tag->getAttribute('le')) { - push @rules, "($cmpvar <= $cmpval)"; - } - if (my $cmpval = $tag->getAttribute('eq')) { - push @rules, "($cmpvar == $cmpval)"; - } - if (my $cmpval = $tag->getAttribute('ge')) { - push @rules, "($cmpvar >= $cmpval)"; - } - if (my $cmpval = $tag->getAttribute('gt')) { - push @rules, "($cmpvar > $cmpval)"; - } - if (my $cmpval = $tag->getAttribute('ne')) { - push @rules, "($cmpvar != $cmpval)"; - } - } - return '('.(join(' && ',@rules) || '1').')'; -} - -our $in_cond = 0; - -sub render_cond_if($$$;@) { - my ($tag, $in_elseif, $render_cb, @tail) = @_; - - local $in_cond = 1; - - { - local $indentation = 0; - my $op = ($in_elseif && $in_elseif >= 2) ? '#elif' : '#if'; - emit $op, ' ', translate_if_cond($tag); - } - - for my $child ($tag->findnodes('child::*')) { - &render_cond($child, $render_cb, @tail); - } - - unless ($in_elseif) { - local $indentation = 0; - emit "#endif"; - } -} - -sub render_cond($$;@) { - my ($tag, $render_cb, @tail) = @_; - - my $tag_name = $tag->nodeName; - if ($tag_name eq 'cond-if') { - render_cond_if($tag, 0, $render_cb, @tail); - } elsif ($tag_name eq 'cond-elseif') { - my $idx = 1; - for my $child ($tag->findnodes('child::*')) { - ($child->nodeName eq 'cond-if') - or die "Only cond-if tags may be inside a cond-switch: ".$child->nodeName."\n"; - render_cond_if($child, $idx++, $render_cb, @tail); - } - { - local $indentation = 0; - emit "#endif"; - } - } else { - local $_ = $tag; - $render_cb->($tag, @tail); - } -} - -# ENUM - -sub render_enum_core($$) { - my ($name,$tag) = @_; - - my $base = 0; - - emit_block { - my @items = $tag->findnodes('child::*'); - my $idx = 0; - - for my $item (@items) { - render_cond $item, sub { - my $tag = $_->nodeName; - return if $tag eq 'enum-attr'; - ($tag eq 'enum-item') - or die "Invalid enum member: ".$item->nodeName."\n"; - - my $name = ensure_name $_->getAttribute('name'); - my $value = $_->getAttribute('value'); - - $base = ($idx == 0 && !$in_cond) ? $value : undef if defined $value; - $idx++; - - emit $name, (defined($value) ? ' = '.$value : ''), ','; - }; - } - - emit "_last_item_of_$name"; - } "enum $name ", ";"; - - return $base; -} - -sub render_enum_tables($$$) { - my ($name,$tag,$base) = @_; - - # Enumerate enum attributes - - my %aidx = ('key' => 0); - my @anames = ('key'); - my @avals = ('NULL'); - my @atypes = ('const char*'); - my @atnames = (undef); - - for my $attr ($tag->findnodes('child::enum-attr')) { - my $name = $attr->getAttribute('name') or die "Unnamed enum-attr.\n"; - my $type = $attr->getAttribute('type-name'); - my $def = $attr->getAttribute('default-value'); - - die "Duplicate attribute $name.\n" if exists $aidx{$name}; - - check_name $name; - $aidx{$name} = scalar @anames; - push @anames, $name; - push @atnames, $type; - - if ($type) { - push @atypes, $type; - push @avals, (defined $def ? $def : "($type)0"); - } else { - push @atypes, 'const char*'; - push @avals, (defined $def ? "\"$def\"" : 'NULL'); - } - } - - # Emit accessor function prototypes - - emit "const $name _first_item_of_$name = ($name)$base;"; - - emit_block { - emit "return (value >= _first_item_of_$name && value < _last_item_of_$name);"; - } "inline bool is_valid($name value) "; - - for (my $i = 0; $i < @anames; $i++) { - emit "${export_prefix}$atypes[$i] get_$anames[$i]($name value);"; - } - - # Emit implementation - - with_emit_static { - emit_block { - emit_block { - # Emit the entry type - emit_block { - for (my $i = 0; $i < @anames; $i++) { - emit "$atypes[$i] $anames[$i];"; - } - } "struct _info_entry ", ";"; - - # Emit the info table - emit_block { - for my $item ($tag->findnodes('child::*')) { - render_cond $item, sub { - my $tag = $_->nodeName; - return if $tag eq 'enum-attr'; - - # Assemble item-specific attr values - my @evals = @avals; - my $name = $_->getAttribute('name'); - $evals[0] = "\"$name\"" if $name; - - for my $attr ($_->findnodes('child::item-attr')) { - my $name = $attr->getAttribute('name') or die "Unnamed item-attr.\n"; - my $value = $attr->getAttribute('value') or die "No-value item-attr.\n"; - my $idx = $aidx{$name} or die "Unknown item-attr: $name\n"; - - if ($atnames[$idx]) { - $evals[$idx] = $value; - } else { - $evals[$idx] = "\"$value\""; - } - } - - emit "{ ",join(', ',@evals)," },"; - }; - } - - emit "{ ",join(', ',@avals)," }"; - } "static const _info_entry _info[] = ", ";"; - - for (my $i = 0; $i < @anames; $i++) { - emit_block { - emit "return is_valid(value) ? _info[value - $base].$anames[$i] : $avals[$i];"; - } "$atypes[$i] get_$anames[$i]($name value) "; - } - } "namespace $name "; - } "namespace enums "; - }; -} - -sub render_enum_type { - my ($tag) = @_; - - emit_block { - emit_block { - my $base = render_enum_core($typename,$tag); - - if (defined $base) { - render_enum_tables($typename,$tag,$base); - } else { - print STDERR "Warning: complex enum: $typename\n"; - } - } "namespace $typename "; - } "namespace enums "; - - emit "using enums::",$typename,"::",$typename,";"; -} - -# BITFIELD - -sub get_primitive_base($;$) { - my ($tag, $default) = @_; - - my $base = $tag->getAttribute('base-type') || $default || 'uint32_t'; - $primitive_types{$base} or die "Must be primitive: $base\n"; - - return $base; -} - -sub render_bitfield_core { - my ($name, $tag) = @_; - - emit_block { - emit get_primitive_base($tag), ' whole;'; - - emit_block { - for my $item ($tag->findnodes('child::*')) { - render_cond $item, sub { - my ($item) = @_; - ($item->nodeName eq 'flag-bit') - or die "Invalid bitfield member:".$item->nodeName."\n"; - - check_bad_attrs($item); - my $name = ensure_name $item->getAttribute('name'); - my $size = $item->getAttribute('count') || 1; - emit "unsigned ", $name, " : ", $size, ";"; - }; - } - } "struct ", " bits;"; - } "union $name ", ";"; -} - -sub render_bitfield_type { - my ($tag) = @_; - render_bitfield_core($typename,$tag); -} - -# STRUCT - -my %struct_field_handlers; - -sub get_struct_fields($) { - # Retrieve subtags that are actual struct fields - my ($struct_tag) = @_; - local $_; - return grep { - my $tag = $_->nodeName; - die "Unknown field tag: $tag\n" - unless exists $struct_field_handlers{$tag}; - $struct_field_handlers{$tag}; - } $struct_tag->findnodes('child::*'); -} - -sub get_struct_field_type($) { - # Dispatch on the tag name, and retrieve the type prefix & suffix - my ($tag) = @_; - my $handler = $struct_field_handlers{$tag->nodeName} - or die "Unexpected tag: ".$tag->nodeName; - return $handler->($tag); -} - -sub do_render_struct_field($) { - my ($tag) = @_; - my $tag_name = $tag->nodeName; - my $field_name = $tag->getAttribute('name'); - - # Special case: anonymous compounds. - if ($tag_name eq 'compound' && !defined $field_name && - !defined $tag->getAttribute('type-name')) - { - check_bad_attrs($tag); - with_struct_block { - render_struct_field($_) for get_struct_fields($tag); - } $tag, undef, -no_anon => 1; - return; - } - - # Otherwise, create the name if necessary, and render - my $name = ensure_name $field_name; - with_anon { - my ($prefix, $postfix) = get_struct_field_type($tag); - emit $prefix, ' ', $name, $postfix, ';'; - } "T_$name"; -} - -sub render_struct_field($) { - my ($tag) = @_; - render_cond $tag, \&do_render_struct_field; -} - -sub emit_typedef($$) { - # Convert a prefix/postfix pair into a single name - my ($pre, $post) = @_; - my $name = ensure_name undef; - emit 'typedef ', $pre, ' ', $name, $post, ';'; - return $name; -} - -sub get_container_item_type($$;$) { - # Interpret the type-name and nested fields for a generic container type - my ($tag,$strong_ref,$allow_void) = @_; - - check_bad_attrs($tag); - - my $prefix; - my $postfix = ''; - local $is_strong_ref = $strong_ref; - - unless ($prefix = decode_type_name_ref($tag)) { - my @fields = get_struct_fields($tag); - - if (scalar(@fields) == 1 && !is_conditional($fields[0])) { - ($prefix, $postfix) = get_struct_field_type($fields[0]); - } elsif (scalar(@fields) == 0) { - $allow_void or die "Empty container: ".$tag->nodeName."\n"; - $prefix = $allow_void; - } else { - $prefix = ensure_name undef; - with_struct_block { - render_struct_field($_) for @fields; - } $tag, $prefix; - } - } - - return ($prefix,$postfix) if wantarray; - return emit_typedef($prefix, $postfix) if $postfix; - return $prefix; -} - -sub get_primitive_field_type { - # Primitive type handler - my ($tag,$fname) = @_; - check_bad_attrs($tag); - my $name = $tag->nodeName; - return (primitive_type_name($name), ""); -} - -sub get_static_string_type { - # Static string handler - my ($tag, $fname) = @_; - check_bad_attrs($tag, 1); - my $count = $tag->getAttribute('size') || 0; - return ('char', "[$count]"); -} - -sub get_padding_type { - # Padding handler. Supports limited alignment. - my ($tag, $fname) = @_; - - check_bad_attrs($tag, 1, 1); - my $count = $tag->getAttribute('size') || 0; - my $align = $tag->getAttribute('alignment') || 1; - - if ($align == 1) { - return ('char', "[$count]"); - } elsif ($align == 2) { - ($count % 2 == 0) or die "Size not aligned in padding: $count at $align\n"; - return ('short', "[".($count/2)."]"); - } elsif ($align == 4) { - ($count % 4 == 0) or die "Size not aligned in padding: $count at $align\n"; - return ('int', "[".($count/4)."]"); - } else { - die "Bad padding alignment $align in $typename in $filename\n"; - } -} - -sub get_static_array_type { - # static-array handler - my ($tag, $fname) = @_; - my ($pre, $post) = get_container_item_type($tag, 1); - my $count = $tag->getAttribute('count') - or die "Count is mandatory for static-array in $typename in $filename\n"; - return ($pre, "[$count]".$post); -} - -sub get_pointer_type($) { - # pointer handler - my ($tag) = @_; - my $item = get_container_item_type($tag, 0, 'void'); - return ($item.'*', ''); -} - -sub get_compound_type($) { - # compound (nested struct) handler - my ($tag) = @_; - check_bad_attrs($tag); - - my $tname = decode_type_name_ref($tag); - unless ($tname) { - $tname = ensure_name undef; - with_struct_block { - render_struct_field($_) for get_struct_fields($tag); - } $tag, $tname; - } - return ($tname,''); -} - -sub get_bitfield_type($) { - # nested bitfield handler - my ($tag) = @_; - check_bad_attrs($tag); - - my $tname = decode_type_name_ref($tag, -force_type => 'bitfield-type'); - unless ($tname) { - $tname = ensure_name undef; - with_anon { - render_bitfield_core($tname, $tag); - }; - } - return ($tname,''); -} - -sub get_enum_type($) { - # nested enum handler - my ($tag) = @_; - check_bad_attrs($tag); - - my $tname = decode_type_name_ref($tag, -force_type => 'enum-type', -force_strong => 1); - my $base = get_primitive_base($tag, 'int32_t'); - unless ($tname) { - $tname = ensure_name undef; - with_anon { - render_enum_core($tname,$tag); - }; - } - return ("enum_field<$tname,$base>", ''); -} - -sub get_stl_vector_type($) { - # STL vector - my ($tag) = @_; - my $item = get_container_item_type($tag,1,'void*'); - $item = 'char' if $item eq 'bool'; - return ("std::vector<$item>", ''); -} - -sub get_stl_bit_vector_type($) { - # STL bit vector - my ($tag) = @_; - check_bad_attrs($tag); - return ("std::vector", ''); -} - -sub get_df_flagarray_type($) { - # DF flag array - my ($tag) = @_; - check_bad_attrs($tag); - my $type = decode_type_name_ref($tag, -attr_name => 'index-enum', -force_type => 'enum-type', -force_strong => 1) || 'int'; - return ("BitArray<$type>", ''); -} - -# Struct dispatch table and core - -%struct_field_handlers = ( - 'comment' => undef, # skip - 'code-helper' => undef, # skip - 'cond-if' => sub { die "cond handling error"; }, - 'cond-elseif' => sub { die "cond handling error"; }, - 'static-string' => \&get_static_string_type, - 'padding' => \&get_padding_type, - 'static-array' => \&get_static_array_type, - 'pointer' => \&get_pointer_type, - 'compound' => \&get_compound_type, - 'bitfield' => \&get_bitfield_type, - 'enum' => \&get_enum_type, - 'stl-vector' => \&get_stl_vector_type, - 'stl-bit-vector' => \&get_stl_bit_vector_type, - 'df-flagarray' => \&get_df_flagarray_type, -); -$struct_field_handlers{$_} ||= \&get_primitive_field_type for @primitive_type_list; - -sub emit_find_instance { - my ($tag) = @_; - - my $instance_vector = translate_lookup $tag->getAttribute('instance-vector'); - if ($instance_vector) { - emit "static std::vector<$typename*> &get_vector();"; - emit "static $typename *find(int id);"; - - with_emit_static { - emit_block { - emit "return ", $instance_vector, ";"; - } "std::vector<$typename*>& ${typename}::get_vector() "; - - emit_block { - emit "std::vector<$typename*> &vec_ = get_vector();"; - - if (my $id = $tag->getAttribute('key-field')) { - emit "return binsearch_in_vector(vec_, &${typename}::$id, id_);"; - } else { - emit "return (id_ >= 0 && id_ < vec_.size()) ? vec_[id_] : NULL;"; - } - } "$typename *${typename}::find(int id_) "; - } - } -} - -sub render_struct_type { - my ($tag) = @_; - - my $tag_name = $tag->nodeName; - my $is_class = ($tag_name eq 'class-type'); - my $has_methods = $is_class || is_attr_true($tag, 'has-methods'); - my $inherits = $tag->getAttribute('inherits-from'); - my $original_name = $tag->getAttribute('original-name'); - my $ispec = ''; - - if ($inherits) { - register_ref $inherits, 1; - $ispec = ' : '.$inherits; - } elsif ($is_class) { - $ispec = ' : virtual_class'; - } - - with_struct_block { - render_struct_field($_) for get_struct_fields($tag); - - emit_find_instance($tag); - - if ($has_methods) { - if ($is_class) { - emit "static class_virtual_identity<$typename> _identity;"; - with_emit_static { - emit "class_virtual_identity<$typename> ${typename}::_identity(", - "\"$typename\",", - ($original_name ? "\"$original_name\"" : 'NULL'), ',', - ($inherits ? "&${inherits}::_identity" : 'NULL'), - ");"; - } - } - - outdent { - emit "protected:"; - }; - - if ($is_class) { - emit "virtual ~",$typename,"() {}"; - } else { - emit "~",$typename,"() {}"; - } - } - } $tag, "$typename$ispec", -export => 1; -} - -# MAIN BODY - -# Collect all type definitions from XML files - -sub add_type_to_hash($) { - my ($type) = @_; - - my $name = $type->getAttribute('type-name') - or die "Type without a name in $filename\n"; - - die "Duplicate definition of $name in $filename\n" if $types{$name}; - - local $typename = $name; - check_bad_attrs $type; - $types{$name} = $type; - $type_files{$name} = $filename; -} - -for my $fn (glob "$input_dir/*.xml") { - local $filename = $fn; - my $parser = XML::LibXML->new(); - my $doc = $parser->parse_file($filename); - - add_type_to_hash $_ foreach $doc->findnodes('/data-definition/enum-type'); - add_type_to_hash $_ foreach $doc->findnodes('/data-definition/bitfield-type'); - add_type_to_hash $_ foreach $doc->findnodes('/data-definition/struct-type'); - add_type_to_hash $_ foreach $doc->findnodes('/data-definition/class-type'); -} - -# Generate text representations - -my %type_handlers = ( - 'enum-type' => \&render_enum_type, - 'bitfield-type' => \&render_bitfield_type, - 'class-type' => \&render_struct_type, - 'struct-type' => \&render_struct_type, -); - -my %type_data; - -for my $name (sort { $a cmp $b } keys %types) { - local $typename = $name; - local $filename = $type_files{$typename}; - local %weak_refs; - local %strong_refs; - - eval { - my $type = $types{$typename}; - - # Emit the actual type definition - my @code = with_emit { - with_anon { - $type_handlers{$type->nodeName}->($type); - }; - } 2; - - delete $weak_refs{$name}; - delete $strong_refs{$name}; - - # Add wrapping - my @all = with_emit { - my $def = type_header_def($typename); - emit "#ifndef $def"; - emit "#define $def"; - - for my $strong (sort { $a cmp $b } keys %strong_refs) { - my $sdef = type_header_def($strong); - emit "#ifndef $sdef"; - emit "#include \"$strong.h\""; - emit "#endif"; - } - - emit_block { - for my $weak (sort { $a cmp $b } keys %weak_refs) { - next if $strong_refs{$weak}; - my $ttype = $types{$weak}; - my $tstr = 'struct'; - $tstr = 'enum' if $ttype->nodeName eq 'enum-type'; - $tstr = 'union' if $ttype->nodeName eq 'bitfield-type'; - $tstr = 'union' if ($ttype->nodeName eq 'struct-type' && is_attr_true($ttype,'is-union')); - emit $tstr, ' ', $weak, ';'; - } - - push @lines, @code; - } "namespace $main_namespace "; - - emit "#endif"; - }; - - $type_data{$typename} = \@all; - }; - if ($@) { - print 'Error: '.$@."Type $typename in $filename ignored\n"; - } -} - -# Write output files - -mkdir $output_dir; - -{ - # Delete the old files - for my $name (glob "$output_dir/*.h") { - unlink $name; - } - - # Write out the headers - local $, = "\n"; - local $\ = "\n"; - - for my $name (keys %type_data) { - open FH, ">$output_dir/$name.h"; - print FH "/* THIS FILE WAS GENERATED. DO NOT EDIT. */"; - print FH @{$type_data{$name}}; - close FH; - } - - # Write out the static file - open FH, ">$output_dir/static.inc"; - print FH "/* THIS FILE WAS GENERATED. DO NOT EDIT. */"; - for my $name (sort { $a cmp $b } keys %static_includes) { - print FH "#include \"$name.h\""; - } - print FH "namespace $main_namespace {"; - print FH @static_lines; - print FH '}'; - close FH; -} diff --git a/library/xml/df.building-raws.xml b/library/xml/df.building-raws.xml deleted file mode 100644 index bf522ae31..000000000 --- a/library/xml/df.building-raws.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.buildings.xml b/library/xml/df.buildings.xml deleted file mode 100644 index 74df09eb7..000000000 --- a/library/xml/df.buildings.xml +++ /dev/null @@ -1,403 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - not room; 1 in stockpile; 2 wall; 3 inner; 4 distance boundary. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- stockpile -- - - - - - - - - - - - - - - - - - - - - - - - - - -- zone -- - - - - - - -- actual -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- workshops -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- misc -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.creature-raws.xml b/library/xml/df.creature-raws.xml deleted file mode 100644 index 61aa7ed7c..000000000 --- a/library/xml/df.creature-raws.xml +++ /dev/null @@ -1,592 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 0 around of, 1 around by - - - - - - - - - - - - - - - - - - - $global.world.raws.creatures.all[$$].caste[$] - - - - - - - - - // temporary - - - - fingers[2], nose, ear, head, eyes, mouth, hair, knuckles, lips, cheek, nails, f eet, arms, hands, tongue, leg - - - - - - - - - - - - - - - - - - - - - - - - - - // NOT 32-bit! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $global.world.raws.creatures.all[$] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.d_init.xml b/library/xml/df.d_init.xml deleted file mode 100644 index 345fa812a..000000000 --- a/library/xml/df.d_init.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 85266c0 - - - - diff --git a/library/xml/df.history.xml b/library/xml/df.history.xml deleted file mode 100644 index 700329ea8..000000000 --- a/library/xml/df.history.xml +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - (describe-obj $.name) - (awhen (find-creature $.race) - (fmt "~:(~A ~A~)" $it.caste[$.caste].caste_id $it.creature_id)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - dtor 8532fa0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.init.xml b/library/xml/df.init.xml deleted file mode 100644 index 6680b788a..000000000 --- a/library/xml/df.init.xml +++ /dev/null @@ -1,138 +0,0 @@ - - -- init.h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- texture_handler.h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.item-raws.xml b/library/xml/df.item-raws.xml deleted file mode 100644 index 81d9c7671..000000000 --- a/library/xml/df.item-raws.xml +++ /dev/null @@ -1,303 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.items.xml b/library/xml/df.items.xml deleted file mode 100644 index c1b989b23..000000000 --- a/library/xml/df.items.xml +++ /dev/null @@ -1,577 +0,0 @@ - - -- MISC TYPES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- CORE ITEM - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- ACTUAL ITEM - - - -- Important - - - - - - -- Misc - - - - - - - - - - - - - - - - - - - - - - - - - - -- Wielders - - - - - - - - - - - - (if (> $.stack_size 1) (fmt "stack: ~A" $.stack_size)) - (if (> $.wear 0) (fmt "wear: ~A" $.wear)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- CRAFTED ITEM - - - - - - - $.quality - (describe-obj (material-by-id $.matType $.matIndex)) - - - - - - - - - - -- CONSTRUCTED ITEM - - - - - - - - -- BODY COMPONENT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- CRITTER - - - - - - - - - -- LIQUID/POWER - - - - - - - - - - - - - - - - - - -- MISC - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- CONSTRUCTED - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.job-enums.xml b/library/xml/df.job-enums.xml deleted file mode 100644 index 6a84ec8f5..000000000 --- a/library/xml/df.job-enums.xml +++ /dev/null @@ -1,1785 +0,0 @@ - - ----- PROFESSION ----- - - - - - - - -- 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 10 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 30 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 40 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 50 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 60 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 80 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 90 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 100 - - - - - - - - - - - - - - - - - - - - - - ----- LABOR ----- - - - - - -- 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 10 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 30 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 40 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 50 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 60 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 70 - - - - - - - - - - - - - ----- SKILL ----- - - - - - -- 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 10 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 30 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 40 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 50 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 60 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 80 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 90 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 100 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 110 - - - - - - - - - - - - - - - - - - - - - - ----- JOB TYPE ----- - - - -- Declare attributes: - - - - -- 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 10 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 30 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 40 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 50 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 60 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 80 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 90 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 100 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 110 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 130 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 140 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 150 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 160 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 170 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 180 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 190 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 200 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 210 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 220 - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.jobs.xml b/library/xml/df.jobs.xml deleted file mode 100644 index 8c6c6d849..000000000 --- a/library/xml/df.jobs.xml +++ /dev/null @@ -1,263 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- Guess: - - - - - - - - - - - -- Either empty, or same as above: - - - - - - - - -- These are equal to the ones above: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.language.xml b/library/xml/df.language.xml deleted file mode 100644 index 961057f2d..000000000 --- a/library/xml/df.language.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $.word - - - - - - - - - - - - - - $.name - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (when $.has_name - (let* ((nick $.nickname) - (language $global.world.raws.translations[$.language]) - (fname $.first_name) - (lwords $language.words)) - (fmt "~:(~@[~A ~]~@['~A' ~]~{~A~^ ~}~)" - (if (> (length fname) 0) fname) - (if (> (length nick) 0) nick) - (loop for i from 0 below 7 for word = $.words[i] - when (>= word 0) collect $lwords[word].value)))) - - - - - diff --git a/library/xml/df.legends.xml b/library/xml/df.legends.xml deleted file mode 100644 index a9d2e4a65..000000000 --- a/library/xml/df.legends.xml +++ /dev/null @@ -1,301 +0,0 @@ - - - - - - - - - - - - - (describe-obj $.name) - (describe-obj (find-creature $.race)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (describe-obj $.name) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (describe-obj $.figure) - - - - - - - - - - - - - - - - (describe-obj $.name) - - - - - - - - - - diff --git a/library/xml/df.machines.xml b/library/xml/df.machines.xml deleted file mode 100644 index 000e83255..000000000 --- a/library/xml/df.machines.xml +++ /dev/null @@ -1,96 +0,0 @@ - - -- MACHINE - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- MACHINE COMPONENT BUILDINGS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.map.xml b/library/xml/df.map.xml deleted file mode 100644 index eac8bbeb9..000000000 --- a/library/xml/df.map.xml +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.materials.xml b/library/xml/df.materials.xml deleted file mode 100644 index ea464879a..000000000 --- a/library/xml/df.materials.xml +++ /dev/null @@ -1,341 +0,0 @@ - - - - - - - - (describe-material $) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // color token index - - - - - - - - - - - - - (material-by-id $ $$) - (describe-material $) - - - - - - - - - - - - - - - (describe-material $) - - - - - - - - - $.id - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $.id - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.military.xml b/library/xml/df.military.xml deleted file mode 100644 index d44af3d30..000000000 --- a/library/xml/df.military.xml +++ /dev/null @@ -1,236 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- May be invalid: - - - - - - - - - - - - - - - - - - - (describe-obj $.name) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (describe-obj $.name) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.projectile.xml b/library/xml/df.projectile.xml deleted file mode 100644 index 5fc9b3e4a..000000000 --- a/library/xml/df.projectile.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.raws.xml b/library/xml/df.raws.xml deleted file mode 100644 index ed2745fb5..000000000 --- a/library/xml/df.raws.xml +++ /dev/null @@ -1,237 +0,0 @@ - - - -- Materials - - - - - - -- Inorganic - - - - - - - - - -- Plants - - - dtor 852cc20 - - - - - - - - - - - - - - - - - - - - - - - - - -- Creature RAWs - - - - dtor 89bab50 - - - dtor 8527e40 - - - - - - - - - - - - - dtor 89ba980 - - - -- Creatures - - - dtor 81448c0 - - - - - - - - - - - - - - - - -- Item RAWs - - - dtor 852e080 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- Sapient species - - - - - - -- Language RAWs - - dtor 852bc90 - - - - - - - - - - - - - - - - - - - - - - -- Words - - - - - - - - - - - - - - - - - - - - - - - - - - - -- Reaction RAWs - - - - - - -- Workshops - - - - - - - - - - - - - - - - -- Material index - - - - - - diff --git a/library/xml/df.refs.xml b/library/xml/df.refs.xml deleted file mode 100644 index 04671dc55..000000000 --- a/library/xml/df.refs.xml +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.stockpile.xml b/library/xml/df.stockpile.xml deleted file mode 100644 index cfd48e38d..000000000 --- a/library/xml/df.stockpile.xml +++ /dev/null @@ -1,254 +0,0 @@ - - - - - - - - - - - also 26 - also 31 - also 32 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 - - - - - - - - - - - - - - - - - - - - - 2 - - - - - - - - 5 - 5 - - - - - 659 - - - - - - - - 17 - - - - - - - - - - - - - - - - - - - - - - - - 11 - - - - - - - - - - - - - - - 11 - - - - - - - - - - - - - diff --git a/library/xml/df.ui.xml b/library/xml/df.ui.xml deleted file mode 100644 index 457617a00..000000000 --- a/library/xml/df.ui.xml +++ /dev/null @@ -1,603 +0,0 @@ - - - - - - - - - - - - - - - (describe-obj $.name) - - - - - - - - - - - - - - - - - - -- 2 - - - - - - - - - - - - - - - -- 14 - - - - - - -- 17 - - - - - - - - -- 22 - - - - - - -- 25 - - - - - - - - - - - -- 33 - - - - - -- 35 - - - - -- 36 - - - - - - - -- 40 - - - - - - - -- 44 - - - - - - - - - - - - - - - - - - - - - - - - - - ctor 86e33c0 x - dtor 8534190 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - dtor: 0x85272c0 - - - - diff --git a/library/xml/df.units.xml b/library/xml/df.units.xml deleted file mode 100644 index fdad8cd56..000000000 --- a/library/xml/df.units.xml +++ /dev/null @@ -1,701 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Scuttle creature: causes creature to be killed, leaving a behind - corpse and generating negative thoughts like a real kill. - - - - - - - - - - - - (describe-obj $.name) - (awhen (find-creature $.race) - (fmt "~:(~A ~A~)" $it.caste[$.caste].caste_id $it.creature_id)) - - - - - - - - - - - - - - - - E.g. for a dead miner, holds the place where he - was likely hanging around when he got the command - to mine in an aquifer. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- If shot by a ranged weapon: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // fight related - // fight related - - - // increments every tick - - - - - - - - - // 87*0 ? - - - - - // 238*0 - // 238*0 - // 238*0 - // 238*0 - // 238*0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 490 - - - - - - - - - - - - - - - - - - - - - - - - // 53c decrements every job_counter reroll, set when changing jobs - // 540 current_job unit/walk done when reach -1, decremented every tick - // if set, decrements every job_counter reroll - - - // 54c decrements every tick, unstun at 0 - - - - - // coords ? (-30.000x3) - - - // coords again - - - - - - - - - - - - - - - - - - - - - - - - // counter, decrement to 0 - // same as 58c - - // fluctuate - - - - - - - - - - - - - - - - - - - - - - - - // 0x3e8 (1000) - // 0x3e8 (1000) - - - - - - - - - - - - - - - - // item ids? - - // 6f0: dined in a legendary dinning room, etc - - - - // 710 - - - - - // 738 - - - - // coords (-30000*3) - - - - - - - - - - - // 794 - // 796 - // 798 - // 79a - - - - - - - - - - - - - - - - - - - - - - // combat log? - - - - - - - - - - - - - // item related - - - - - - // age ? incremented every tick - - - - - - - - - - // items ids? - - // same size as 8e8, soldier related? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (fmt "value=~A" $.value) - - - - - - - - - - - - - - - (describe-obj $.name) - (awhen (find-creature $.race) - (fmt "~:(~A ~A~)" $it.caste[$.caste].caste_id $it.creature_id)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.viewscreen.xml b/library/xml/df.viewscreen.xml deleted file mode 100644 index 3874c445a..000000000 --- a/library/xml/df.viewscreen.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.world-data.xml b/library/xml/df.world-data.xml deleted file mode 100644 index 2f0faa3a2..000000000 --- a/library/xml/df.world-data.xml +++ /dev/null @@ -1,374 +0,0 @@ - - - - - - - - - - - - - - - - - - - - (describe-obj $.name) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/df.world.xml b/library/xml/df.world.xml deleted file mode 100644 index 3058b0a64..000000000 --- a/library/xml/df.world.xml +++ /dev/null @@ -1,503 +0,0 @@ - - - dtor 89fff80 - - - dtor 8532540 - - - - - - - - - - - - - - - - - -- - - - - - - - - - - -- Entities - - - - - - - - - - - - -- Unknown - - - - -- Units - - - - - - - - - - - - - - - - - - -- Unknown - - - - - - - - - -- Nemesis - - - - - - - - - - - - - - -- Items - - - dtor 852f4b0 - - - - - - - - - - - - - - - - - - - -- Artifacts - - - - - - - - - - - - -- Jobs and projectiles - - - - - - -- Buildings - - - dtor 85316f0 - - - - - - - - - - - - - - - - - - - - -- Machines (connected groups of gears and so on) - - - - - - - - - - - -- Unknown - - - - - - - - - - - - - - - - - - - - - - - - -- Plants - - - - - - - - - -- Unknown - - - - -- Unknown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- Drills - - - - - - - - - - - -- Reports and announcements - - - dtor 85356e0 - - - - - - - - - - Written to by code at 0x80fd7b0 - - - - - - - - - - - - - - - - - - - - - - 52cdc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 547f8 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- RAWs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ctor 87ae880 - - - - - - - - - - - dtor 83bed90 - - - - - - - - - - - - -- hist figures - - - - - - - - - - - - - - - - Looks like a temporary buffer for pathfinding or something. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 192be0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/xml/list.pl b/library/xml/list.pl deleted file mode 100755 index 206565843..000000000 --- a/library/xml/list.pl +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; - -use XML::LibXML; - -my $input_dir = $ARGV[0] || '.'; -my $output_dir = $ARGV[1] || 'codegen'; -my $separator = $ARGV[2] || "\n"; - -print "$output_dir/static.inc"; - -for my $filename (glob "$input_dir/*.xml") { - my $parser = XML::LibXML->new(); - my $doc = $parser->parse_file($filename); - - my @nodes = ( - $doc->findnodes('/data-definition/enum-type'), - $doc->findnodes('/data-definition/bitfield-type'), - $doc->findnodes('/data-definition/struct-type'), - $doc->findnodes('/data-definition/class-type') - ); - - for my $node (@nodes) { - my $name = $node->getAttribute('type-name') - or die "Unnamed type in $filename\n"; - print "$separator$output_dir/$name.h"; - } -} - -print $separator if $separator eq "\n"; - diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index ab7e039a4..2e60e9b34 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -59,6 +59,10 @@ DFHACK_PLUGIN(filltraffic filltraffic.cpp) DFHACK_PLUGIN(seedwatch seedwatch.cpp) DFHACK_PLUGIN(initflags initflags.cpp) DFHACK_PLUGIN(stockpiles stockpiles.cpp) +DFHACK_PLUGIN(rename rename.cpp) +DFHACK_PLUGIN(fixwagons fixwagons.cpp) +DFHACK_PLUGIN(jobutils jobutils.cpp) +DFHACK_PLUGIN(regrass regrass.cpp) #DFHACK_PLUGIN(versionosd versionosd.cpp) # this is the skeleton plugin. If you want to make your own, make a copy and then change it diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index cbe84aef9..7bba2217b 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include -#include -#include "dfhack/extra/stopwatch.h" +#include "Core.h" +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "MemAccess.h" +#include "MiscUtils.h" #include #include diff --git a/plugins/Dfusion/include/hexsearch.h b/plugins/Dfusion/include/hexsearch.h index b4ffb84d8..6cbc978ce 100644 --- a/plugins/Dfusion/include/hexsearch.h +++ b/plugins/Dfusion/include/hexsearch.h @@ -1,8 +1,8 @@ #ifndef HEXSEARCH_H #define HEXSEARCH_H #include -#include "dfhack/Core.h" //for some reason process.h needs core -#include "dfhack/Process.h" +#include "Core.h" //for some reason process.h needs core +#include "MemAccess.h" //(not yet)implemented using Boyer-Moore algorithm @@ -15,20 +15,20 @@ public: ANYBYTE=0x101,DWORD_,ANYDWORD,ADDRESS }; - Hexsearch(const SearchArgType &args,uint64_t startpos,uint64_t endpos); + Hexsearch(const SearchArgType &args,char * startpos,char * endpos); ~Hexsearch(); void Reset(){pos_=startpos_;}; - void SetStart(uint64_t pos){pos_=pos;}; + void SetStart(char * pos){pos_=pos;}; - uint64_t FindNext(); - std::vector FindAll(); + void * FindNext(); + std::vector FindAll(); private: bool Compare(int a,int b); void ReparseArgs(); SearchArgType args_; - uint64_t pos_,startpos_,endpos_; + char * pos_,* startpos_,* endpos_; std::vector BadCharShifts,GoodSuffixShift; void PrepareGoodSuffixTable(); void PrepareBadCharShift(); diff --git a/plugins/Dfusion/include/lua_Console.h b/plugins/Dfusion/include/lua_Console.h index a6430dcbf..2ced33645 100644 --- a/plugins/Dfusion/include/lua_Console.h +++ b/plugins/Dfusion/include/lua_Console.h @@ -1,6 +1,6 @@ #ifndef LUA_CONSOLE_H #define LUA_CONSOLE_H -#include +#include #include "luamain.h" namespace lua diff --git a/plugins/Dfusion/include/lua_Misc.h b/plugins/Dfusion/include/lua_Misc.h index 3254ed3d0..8bada83c4 100644 --- a/plugins/Dfusion/include/lua_Misc.h +++ b/plugins/Dfusion/include/lua_Misc.h @@ -3,8 +3,8 @@ #include -#include -#include +#include "Core.h" +#include #include "luamain.h" #include "OutFile.h" #include "bit.h" diff --git a/plugins/Dfusion/include/lua_Process.h b/plugins/Dfusion/include/lua_Process.h index 515aa55af..e6639cfc8 100644 --- a/plugins/Dfusion/include/lua_Process.h +++ b/plugins/Dfusion/include/lua_Process.h @@ -1,8 +1,8 @@ #ifndef LUA_PROCESS_H #define LUA_PROCESS_H -#include -#include +#include "Core.h" +#include #include "luamain.h" diff --git a/plugins/Dfusion/include/lua_VersionInfo.h b/plugins/Dfusion/include/lua_VersionInfo.h index e221eff04..99010f590 100644 --- a/plugins/Dfusion/include/lua_VersionInfo.h +++ b/plugins/Dfusion/include/lua_VersionInfo.h @@ -1,7 +1,7 @@ #ifndef LUA_VERSIONINFO_H #define LUA_VERSIONINFO_H -#include -#include +#include "Core.h" +#include #include "luamain.h" namespace lua { diff --git a/plugins/Dfusion/src/hexsearch.cpp b/plugins/Dfusion/src/hexsearch.cpp index 1958086ce..30dcf26f8 100644 --- a/plugins/Dfusion/src/hexsearch.cpp +++ b/plugins/Dfusion/src/hexsearch.cpp @@ -1,7 +1,7 @@ #include "hexsearch.h" -Hexsearch::Hexsearch(const SearchArgType &args,uint64_t startpos,uint64_t endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos) +Hexsearch::Hexsearch(const SearchArgType &args,char * startpos,char * endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos) { ReparseArgs(); } @@ -52,7 +52,7 @@ void Hexsearch::ReparseArgs() } } } -uint64_t Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm +void * Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm { DFHack::Core &inst=DFHack::Core::getInstance(); DFHack::Process *p=inst.p; @@ -81,16 +81,16 @@ uint64_t Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm return pos_-args_.size(); } } - pos_++; + pos_ = pos_ + 1; } delete [] buf; return 0; } -std::vector Hexsearch::FindAll() +std::vector Hexsearch::FindAll() { - std::vector ret; - uint64_t cpos=pos_; + std::vector ret; + void * cpos=pos_; while(cpos!=0) { cpos=FindNext(); diff --git a/plugins/Dfusion/src/lua_Hexsearch.cpp b/plugins/Dfusion/src/lua_Hexsearch.cpp index 49a8edc02..8ee7eb9c2 100644 --- a/plugins/Dfusion/src/lua_Hexsearch.cpp +++ b/plugins/Dfusion/src/lua_Hexsearch.cpp @@ -2,14 +2,14 @@ int lua::Hexsearch::find(lua_State *L) { lua::state st(L); - uint64_t pos=p->FindNext(); + void * pos=p->FindNext(); st.push(pos); return 1; } int lua::Hexsearch::findall(lua_State *L) { lua::state st(L); - std::vector pos=p->FindAll(); + std::vector pos=p->FindAll(); st.newtable(); for(unsigned i=0;i(1); - end=st.as(2); + start= (char *)st.as(1); + end=(char *)st.as(2); for(int i=3;i<=st.gettop();i++) { args.push_back(st.as(i)); diff --git a/plugins/Dfusion/src/lua_Misc.cpp b/plugins/Dfusion/src/lua_Misc.cpp index 1c7de39d1..5eb957861 100644 --- a/plugins/Dfusion/src/lua_Misc.cpp +++ b/plugins/Dfusion/src/lua_Misc.cpp @@ -32,7 +32,7 @@ static int LoadMod(lua_State *L) buf=new char[size]; f.GetText(buf); //std::cout<<"poking @:"<write(pos,size,(uint8_t*)buf); + DFHack::Core::getInstance().p->write((void *) pos,size,(uint8_t*)buf); delete [] buf; st.push(pos); st.push(size); diff --git a/plugins/Dfusion/src/lua_Process.cpp b/plugins/Dfusion/src/lua_Process.cpp index ea96f8ac8..8ea73e973 100644 --- a/plugins/Dfusion/src/lua_Process.cpp +++ b/plugins/Dfusion/src/lua_Process.cpp @@ -14,7 +14,7 @@ static int lua_Process_readDWord(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - uint32_t ret=c->readDWord(st.as(1)); + uint32_t ret=c->readDWord( (void *) st.as(1)); st.push(ret); return 1; } @@ -22,14 +22,14 @@ static int lua_Process_writeDWord(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - c->writeDWord(st.as(1),st.as(2)); + c->writeDWord((void *) st.as(1),st.as(2)); return 0; } static int lua_Process_readFloat(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - float ret=c->readFloat(st.as(1)); + float ret=c->readFloat((void *) st.as(1)); st.push(ret); return 1; } @@ -38,7 +38,7 @@ static int lua_Process_readWord(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - uint16_t ret=c->readWord(st.as(1)); + uint16_t ret=c->readWord((void *) st.as(1)); st.push(ret); return 1; } @@ -47,14 +47,14 @@ static int lua_Process_writeWord(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - c->writeWord(st.as(1),st.as(2)); + c->writeWord((void *) st.as(1),st.as(2)); return 0; } static int lua_Process_readByte(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - uint8_t ret=c->readByte(st.as(1)); + uint8_t ret=c->readByte((void *) st.as(1)); st.push(ret); return 1; } @@ -63,7 +63,7 @@ static int lua_Process_writeByte(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - c->writeByte(st.as(1),st.as(2)); + c->writeByte((void *) st.as(1),st.as(2)); return 0; } static int lua_Process_read(lua_State *S) @@ -77,7 +77,7 @@ static int lua_Process_read(lua_State *S) buf=(uint8_t*)lua_touserdata(st,3); else buf=new uint8_t[len]; - c->read(st.as(1),len,buf); + c->read((void *) st.as(1),len,buf); st.pushlightuserdata(buf); return 1; } @@ -85,14 +85,14 @@ static int lua_Process_write(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - c-> write(st.as(1),st.as(2),static_cast(lua_touserdata(st,3))); + c-> write((void *) st.as(1),st.as(2),static_cast(lua_touserdata(st,3))); return 0; } static int lua_Process_readSTLString (lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - std::string r=c->readSTLString(st.as(1)); + std::string r=c->readSTLString((void *) st.as(1)); st.push(r); return 1; } @@ -101,14 +101,14 @@ static int lua_Process_writeSTLString(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - c->writeSTLString(st.as(1),st.as(2)); + c->writeSTLString((void *) st.as(1),st.as(2)); return 0; } static int lua_Process_copySTLString(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - c->copySTLString(st.as(1),st.as(2)); + c->copySTLString((void *) st.as(1),st.as(2)); return 0; } static int lua_Process_doReadClassName(lua_State *S) @@ -131,7 +131,7 @@ static int lua_Process_readCString (lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - std::string r=c->readCString(st.as(1)); + std::string r=c->readCString((void *) st.as(1)); st.push(r); return 1; } @@ -226,10 +226,10 @@ static int lua_Process_setPermisions(lua_State *S) DFHack::t_memrange range,trange; st.getfield("start",1); - range.start=st.as(); + range.start= (void *)st.as(); st.pop(); st.getfield("end",1); - range.end=st.as(); + range.end= (void *)st.as(); st.pop(); st.getfield("read",2); diff --git a/plugins/Dfusion/src/lua_VersionInfo.cpp b/plugins/Dfusion/src/lua_VersionInfo.cpp index d6f90be15..8dd6b5f23 100644 --- a/plugins/Dfusion/src/lua_VersionInfo.cpp +++ b/plugins/Dfusion/src/lua_VersionInfo.cpp @@ -16,7 +16,7 @@ int OffsetGroup::getOffset(lua_State *L) int OffsetGroup::getAddress(lua_State *L) { lua::state st(L); - uint32_t ret=p->getAddress(st.as(1)); + uint32_t ret= (uint32_t)p->getAddress(st.as(1)); st.push(ret); return 1; } @@ -57,7 +57,7 @@ int OffsetGroup::getSafeOffset(lua_State *L) int OffsetGroup::getSafeAddress(lua_State *L) { lua::state st(L); - uint32_t out; + void * out; bool ret=p->getSafeAddress(st.as(1),out); st.push(ret); st.push(out); @@ -286,7 +286,7 @@ static int __lua_resolveObjectToClassID(lua_State *S) { lua::state st(S); int32_t ret; - bool output=DFHack::Core::getInstance().vinfo->resolveObjectToClassID(st.as(1),ret); + bool output=DFHack::Core::getInstance().vinfo->resolveObjectToClassID((char *)st.as(1),ret); st.push(output); st.push(ret); return 2; @@ -329,7 +329,7 @@ static int __lua_getOffset(lua_State *S) static int __lua_getAddress(lua_State *S) { lua::state st(S); - uint32_t ret=DFHack::Core::getInstance().vinfo->getAddress(st.as(1)); + void * ret=DFHack::Core::getInstance().vinfo->getAddress(st.as(1)); st.push(ret); return 1; } @@ -392,7 +392,7 @@ static int __lua_getSafeOffset(lua_State *S) static int __lua_getSafeAddress(lua_State *S) { lua::state st(S); - uint32_t out; + void * out; bool ret=DFHack::Core::getInstance().vinfo->getSafeAddress(st.as(1),out); st.push(ret); st.push(out); diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index 26fe70cc2..3963bf2af 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -8,19 +8,19 @@ #include using namespace std; -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include #include #include #include -#include +#include -#include -#include -#include -#include +#include +#include +#include +#include using namespace DFHack; using MapExtras::Block; diff --git a/plugins/cleaners.cpp b/plugins/cleaners.cpp index b93b18f37..8992b2078 100644 --- a/plugins/cleaners.cpp +++ b/plugins/cleaners.cpp @@ -1,11 +1,11 @@ -#include -#include -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include +#include +#include using namespace DFHack; @@ -27,7 +27,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector { commands.clear(); commands.push_back(PluginCommand("clean","Removes contaminants from map tiles, items and creatures.",clean)); - commands.push_back(PluginCommand("spotclean","Cleans map tile under cursor.",spotclean)); + commands.push_back(PluginCommand("spotclean","Cleans map tile under cursor.",spotclean,cursor_hotkey)); return CR_OK; } @@ -165,7 +165,7 @@ command_result cleanunits (Core * c) DFhackCExport command_result spotclean (Core * c, vector & parameters) { - c->Suspend(); + // HOTKEY COMMAND: CORE ALREADY SUSPENDED vector splatter; DFHack::Maps *Mapz = c->getMaps(); DFHack::Gui *Gui = c->getGui(); @@ -173,7 +173,6 @@ DFhackCExport command_result spotclean (Core * c, vector & parameters) if(!Mapz->Start()) { c->con.printerr("Can't init map.\n"); - c->Resume(); return CR_FAILURE; } int32_t cursorX, cursorY, cursorZ; @@ -181,7 +180,6 @@ DFhackCExport command_result spotclean (Core * c, vector & parameters) if(cursorX == -30000) { c->con.printerr("The cursor is not active.\n"); - c->Resume(); return CR_FAILURE; } int32_t blockX = cursorX / 16, blockY = cursorY / 16; @@ -193,7 +191,6 @@ DFhackCExport command_result spotclean (Core * c, vector & parameters) { spatters[i]->intensity[tileX][tileY] = 0; } - c->Resume(); return CR_OK; } diff --git a/plugins/cleanowned.cpp b/plugins/cleanowned.cpp index 4b1b61e63..c7d931676 100644 --- a/plugins/cleanowned.cpp +++ b/plugins/cleanowned.cpp @@ -8,17 +8,17 @@ #include using namespace std; -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include using namespace DFHack; DFhackCExport command_result df_cleanowned (Core * c, vector & parameters); diff --git a/plugins/colonies.cpp b/plugins/colonies.cpp index ce8beccb8..6b2d8a1d2 100644 --- a/plugins/colonies.cpp +++ b/plugins/colonies.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include #include #include -#include +#include using std::vector; using std::string; diff --git a/plugins/deramp.cpp b/plugins/deramp.cpp index 0aab27d20..c5b1c8558 100644 --- a/plugins/deramp.cpp +++ b/plugins/deramp.cpp @@ -7,12 +7,12 @@ #include #include using namespace std; -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include using namespace DFHack; DFhackCExport command_result df_deramp (Core * c, vector & parameters); diff --git a/plugins/devel/buildprobe.cpp b/plugins/devel/buildprobe.cpp index 0c7fbb7fd..9893705de 100644 --- a/plugins/devel/buildprobe.cpp +++ b/plugins/devel/buildprobe.cpp @@ -1,13 +1,13 @@ //Quick building occupancy flag test. //Individual bits had no apparent meaning. Assume it's an enum, set by number. -#include -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/plugins/devel/itemhacks.cpp b/plugins/devel/itemhacks.cpp index d9f045a13..0dbc94d58 100644 --- a/plugins/devel/itemhacks.cpp +++ b/plugins/devel/itemhacks.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include #include #include #include diff --git a/plugins/devel/kittens.cpp b/plugins/devel/kittens.cpp index 7c502143c..c202331f3 100644 --- a/plugins/devel/kittens.cpp +++ b/plugins/devel/kittens.cpp @@ -1,13 +1,13 @@ -#include -#include -#include -#include +#include "Core.h" +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "MiscUtils.h" #include #include -#include "dfhack/extra/stopwatch.h" -#include "dfhack/modules/Maps.h" -#include "dfhack/modules/Items.h" -#include +#include "modules/Maps.h" +#include "modules/Items.h" +#include #include using std::vector; @@ -329,8 +329,8 @@ DFhackCExport command_result kittens (Core * c, vector & parameters) } } -#include "dfhack/modules/Units.h" -#include "dfhack/VersionInfo.h" +#include "modules/Units.h" +#include "VersionInfo.h" #include command_result test_creature_offsets(Core* c, vector< string >& parameters) diff --git a/plugins/devel/memview.cpp b/plugins/devel/memview.cpp index 02727a485..030eb4cdc 100644 --- a/plugins/devel/memview.cpp +++ b/plugins/devel/memview.cpp @@ -1,194 +1,194 @@ -#include -#include -#include -#include -#include -#include <../depends/tthread/tinythread.h> //not sure if correct -#include -#include -#include - -using std::vector; -using std::string; -using namespace DFHack; - -uint64_t timeLast=0; -static tthread::mutex* mymutex=0; - -struct memory_data -{ - size_t addr; - size_t len; - size_t refresh; - int state; - uint8_t *buf,*lbuf; - vector ranges; -}memdata; -enum HEXVIEW_STATES -{ - STATE_OFF,STATE_ON -}; -DFhackCExport command_result memview (Core * c, vector & parameters); - -DFhackCExport const char * plugin_name ( void ) -{ - return "memview"; -} - -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) -{ - commands.clear(); - commands.push_back(PluginCommand("memview","Shows memory in real time. Params: adrr length refresh_rate. If addr==0 then stop viewing",memview)); - memdata.state=STATE_OFF; - mymutex=new tthread::mutex; - return CR_OK; -} -size_t convert(const std::string& p,bool ishex=false) -{ - size_t ret; - std::stringstream conv; - if(ishex) - conv<>ret; - return ret; -} -bool isAddr(uint32_t *trg,vector & ranges) -{ - if(trg[0]%4==0) - for(size_t i=0;i & ranges) -{ +#include "Core.h" +#include "Console.h" +#include "PluginManager.h" +#include "MemAccess.h" +#include "MiscUtils.h" +#include <../depends/tthread/tinythread.h> //not sure if correct +#include +#include +#include + +using std::vector; +using std::string; +using namespace DFHack; + +uint64_t timeLast=0; +static tthread::mutex* mymutex=0; + +struct memory_data +{ + void * addr; + size_t len; + size_t refresh; + int state; + uint8_t *buf,*lbuf; + vector ranges; +}memdata; +enum HEXVIEW_STATES +{ + STATE_OFF,STATE_ON +}; +DFhackCExport command_result memview (Core * c, vector & parameters); + +DFhackCExport const char * plugin_name ( void ) +{ + return "memview"; +} + +DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +{ + commands.clear(); + commands.push_back(PluginCommand("memview","Shows memory in real time. Params: adrr length refresh_rate. If addr==0 then stop viewing",memview)); + memdata.state=STATE_OFF; + mymutex=new tthread::mutex; + return CR_OK; +} +size_t convert(const std::string& p,bool ishex=false) +{ + size_t ret; + std::stringstream conv; + if(ishex) + conv<>ret; + return ret; +} +bool isAddr(uint32_t *trg,vector & ranges) +{ + if(trg[0]%4==0) + for(size_t i=0;i & ranges) +{ Console &con=c->con; - const size_t page_size=16; - con.clear(); - - for(size_t i=0;i31)&&(buf[j+i]<128)) //only printable ascii - con.print("%c",buf[j+i]); - else - con.print("."); - //con.print("\n"); + //TODO make something better? + } + if(lbuf[j+i]!=buf[j+i]) + con.print("*%02X",buf[j+i]); //if modfied show a star + else + con.print(" %02X",buf[j+i]); + } + con.reset_color(); + con.print(" | "); + for(size_t j=0;(j31)&&(buf[j+i]<128)) //only printable ascii + con.print("%c",buf[j+i]); + else + con.print("."); + //con.print("\n"); } - con.print("\n"); - con.flush(); - -} -void Deinit() -{ - if(memdata.state==STATE_ON) - { - memdata.state=STATE_OFF; - delete [] memdata.buf; - delete [] memdata.lbuf; - } -} -DFhackCExport command_result plugin_onupdate ( Core * c ) -{ - - mymutex->lock(); - if(memdata.state==STATE_OFF) - { - mymutex->unlock(); - return CR_OK; - } - //Console &con=c->con; - uint64_t time2 = GetTimeMs64(); - uint64_t delta = time2-timeLast; - - if(memdata.refresh!=0) - if(deltaunlock(); - return CR_OK; - } - timeLast = time2; - - c->p->read(memdata.addr,memdata.len,memdata.buf); - outputHex(memdata.buf,memdata.lbuf,memdata.len,memdata.addr,c,memdata.ranges); - memcpy(memdata.lbuf, memdata.buf, memdata.len); - if(memdata.refresh==0) - Deinit(); - mymutex->unlock(); - return CR_OK; - -} -DFhackCExport command_result memview (Core * c, vector & parameters) -{ - mymutex->lock(); - c->p->getMemRanges(memdata.ranges); - memdata.addr=convert(parameters[0],true); - if(memdata.addr==0) - { - Deinit(); - memdata.state=STATE_OFF; - mymutex->unlock(); - return CR_OK; - } - else - { - Deinit(); - bool isValid=false; - for(size_t i=0;icon.printerr("Invalid address:%x\n",memdata.addr); - mymutex->unlock(); - return CR_OK; - } - memdata.state=STATE_ON; - } - if(parameters.size()>1) - memdata.len=convert(parameters[1]); - else - memdata.len=20*16; - - if(parameters.size()>2) - memdata.refresh=convert(parameters[2]); - else - memdata.refresh=0; - - - uint8_t *buf,*lbuf; - memdata.buf=new uint8_t[memdata.len]; - memdata.lbuf=new uint8_t[memdata.len]; - c->p->getMemRanges(memdata.ranges); - mymutex->unlock(); - return CR_OK; -} -DFhackCExport command_result plugin_shutdown ( Core * c ) -{ - mymutex->lock(); - Deinit(); - delete mymutex; - mymutex->unlock(); - return CR_OK; -} + con.print("\n"); + con.flush(); + +} +void Deinit() +{ + if(memdata.state==STATE_ON) + { + memdata.state=STATE_OFF; + delete [] memdata.buf; + delete [] memdata.lbuf; + } +} +DFhackCExport command_result plugin_onupdate ( Core * c ) +{ + + mymutex->lock(); + if(memdata.state==STATE_OFF) + { + mymutex->unlock(); + return CR_OK; + } + //Console &con=c->con; + uint64_t time2 = GetTimeMs64(); + uint64_t delta = time2-timeLast; + + if(memdata.refresh!=0) + if(deltaunlock(); + return CR_OK; + } + timeLast = time2; + + c->p->read(memdata.addr,memdata.len,memdata.buf); + outputHex(memdata.buf,memdata.lbuf,memdata.len,(size_t)memdata.addr,c,memdata.ranges); + memcpy(memdata.lbuf, memdata.buf, memdata.len); + if(memdata.refresh==0) + Deinit(); + mymutex->unlock(); + return CR_OK; + +} +DFhackCExport command_result memview (Core * c, vector & parameters) +{ + mymutex->lock(); + c->p->getMemRanges(memdata.ranges); + memdata.addr=(void *)convert(parameters[0],true); + if(memdata.addr==0) + { + Deinit(); + memdata.state=STATE_OFF; + mymutex->unlock(); + return CR_OK; + } + else + { + Deinit(); + bool isValid=false; + for(size_t i=0;icon.printerr("Invalid address:%x\n",memdata.addr); + mymutex->unlock(); + return CR_OK; + } + memdata.state=STATE_ON; + } + if(parameters.size()>1) + memdata.len=convert(parameters[1]); + else + memdata.len=20*16; + + if(parameters.size()>2) + memdata.refresh=convert(parameters[2]); + else + memdata.refresh=0; + + + uint8_t *buf,*lbuf; + memdata.buf=new uint8_t[memdata.len]; + memdata.lbuf=new uint8_t[memdata.len]; + c->p->getMemRanges(memdata.ranges); + mymutex->unlock(); + return CR_OK; +} +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + mymutex->lock(); + Deinit(); + delete mymutex; + mymutex->unlock(); + return CR_OK; +} diff --git a/plugins/devel/notes.cpp b/plugins/devel/notes.cpp index 32b436121..412f64476 100644 --- a/plugins/devel/notes.cpp +++ b/plugins/devel/notes.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include #include #include -#include +#include using std::vector; using std::string; diff --git a/plugins/devel/rawdump.cpp b/plugins/devel/rawdump.cpp index 0e6cac5bd..2ad840b78 100644 --- a/plugins/devel/rawdump.cpp +++ b/plugins/devel/rawdump.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include #include #include -#include +#include #include using std::vector; diff --git a/plugins/devel/tiles.cpp b/plugins/devel/tiles.cpp index fc83f1891..d6ca4cbd1 100644 --- a/plugins/devel/tiles.cpp +++ b/plugins/devel/tiles.cpp @@ -7,15 +7,15 @@ using std::vector; using std::string; -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace MapExtras; using namespace DFHack; diff --git a/plugins/devel/vectors.cpp b/plugins/devel/vectors.cpp index 320f55c00..777d661e7 100644 --- a/plugins/devel/vectors.cpp +++ b/plugins/devel/vectors.cpp @@ -3,11 +3,11 @@ // // Linux only, enabled with BUILD_VECTORS cmake option. -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include #include #include @@ -19,9 +19,9 @@ using namespace DFHack; struct t_vecTriplet { - uint32_t start; - uint32_t end; - uint32_t alloc_end; + void * start; + void * end; + void * alloc_end; }; DFhackCExport command_result df_vectors (Core * c, @@ -74,7 +74,7 @@ static bool mightBeVec(vector &heap_ranges, // Vector length might not be a multiple of 4 if, for example, // it's a vector of uint8_t or uint16_t. However, the actual memory // allocated to the vector should be 4 byte aligned. - if ((vec->start % 4 != 0) || (vec->alloc_end % 4 != 0)) + if (((int)vec->start % 4 != 0) || ((int)vec->alloc_end % 4 != 0)) return false; for (size_t i = 0; i < heap_ranges.size(); i++) @@ -88,7 +88,7 @@ static bool mightBeVec(vector &heap_ranges, return false; } -static bool inAnyRange(vector &ranges, uint32_t ptr) +static bool inAnyRange(vector &ranges, void * ptr) { for (size_t i = 0; i < ranges.size(); i++) { @@ -141,7 +141,7 @@ static void vectorsUsage(Console &con) static void printVec(Console &con, const char* msg, t_vecTriplet *vec, uint32_t start, uint32_t pos) { - uint32_t length = vec->end - vec->start; + uint32_t length = (int)vec->end - (int)vec->start; uint32_t offset = pos - start; con.print("%8s offset %06p, addr %010p, start %010p, length %u\n", @@ -193,15 +193,15 @@ DFhackCExport command_result df_vectors (Core * c, vector & parameters) { t_memrange &range = heap_ranges[i]; - if (!range.isInRange(start)) + if (!range.isInRange((void *)start)) continue; // Found the range containing the start - if (!range.isInRange(end)) + if (!range.isInRange((void *)end)) { con.print("Scanning %u bytes would read past end of memory " "range.\n", bytes); - uint32_t diff = end - range.end; + uint32_t diff = end - (int)range.end; con.print("Cutting bytes down by %u.\n", diff); end = (uint32_t) range.end; @@ -242,7 +242,7 @@ DFhackCExport command_result df_vectors (Core * c, vector & parameters) { uint32_t ptr = * ( (uint32_t*) pos); - if (inAnyRange(heap_ranges, ptr)) + if (inAnyRange(heap_ranges, (void *) ptr)) { t_vecTriplet* vec = (t_vecTriplet*) ptr; @@ -320,7 +320,7 @@ DFhackCExport command_result df_clearvec (Core * c, vector & parameters continue; } - if (!inAnyRange(heap_ranges, addr)) + if (!inAnyRange(heap_ranges, (void *) addr)) { con << addr_str << " not in any valid address range." << std::endl; continue; @@ -338,7 +338,7 @@ DFhackCExport command_result df_clearvec (Core * c, vector & parameters addr = * ( (uint32_t*) addr); vec = (t_vecTriplet*) addr; - if (inAnyRange(heap_ranges, addr) && mightBeVec(heap_ranges, vec)) + if (inAnyRange(heap_ranges, (void *) addr) && mightBeVec(heap_ranges, vec)) { valid = true; ptr = true; diff --git a/plugins/df2mc b/plugins/df2mc index 8ffad5163..3277c6b29 160000 --- a/plugins/df2mc +++ b/plugins/df2mc @@ -1 +1 @@ -Subproject commit 8ffad51635ceeae55870106a75f3dd84b044ea5a +Subproject commit 3277c6b29ddbb5d800ccb65eba27fed200236f3d diff --git a/plugins/drybuckets.cpp b/plugins/drybuckets.cpp index 245661736..0ea079c0c 100644 --- a/plugins/drybuckets.cpp +++ b/plugins/drybuckets.cpp @@ -7,14 +7,14 @@ #include using namespace std; -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include #include #include #include -#include +#include using namespace DFHack; diff --git a/plugins/fastdwarf.cpp b/plugins/fastdwarf.cpp index 534e34614..38b7f312d 100644 --- a/plugins/fastdwarf.cpp +++ b/plugins/fastdwarf.cpp @@ -8,12 +8,12 @@ #include #include using namespace std; -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include using namespace DFHack; // dfhack interface diff --git a/plugins/filltraffic.cpp b/plugins/filltraffic.cpp index c27029a85..a5c2188fe 100644 --- a/plugins/filltraffic.cpp +++ b/plugins/filltraffic.cpp @@ -1,22 +1,37 @@ // Wide-area traffic designation utility. // Flood-fill from cursor or fill entire map. -#include //For toupper(). +#include //For toupper(). +#include //for min(). #include #include -#include -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include +#include using std::stack; using MapExtras::MapCache; using namespace DFHack; +//Function pointer type for whole-map tile checks. +typedef void (*checkTile)(DFHack::DFCoord, MapExtras::MapCache *); + +//Forward Declarations for Commands DFhackCExport command_result filltraffic(DFHack::Core * c, std::vector & params); -DFhackCExport command_result tiletraffic(DFHack::Core * c, std::vector & params); +DFhackCExport command_result alltraffic(DFHack::Core * c, std::vector & params); + +//Forward Declarations for Utility Functions +DFhackCExport command_result setAllMatching(DFHack::Core * c, checkTile checkProc, + DFHack::DFCoord minCoord = DFHack::DFCoord(0, 0, 0), + DFHack::DFCoord maxCoord = DFHack::DFCoord(0xFFFF, 0xFFFF, 0xFFFF)); + +void allHigh(DFHack::DFCoord coord, MapExtras::MapCache * map); +void allNormal(DFHack::DFCoord coord, MapExtras::MapCache * map); +void allLow(DFHack::DFCoord coord, MapExtras::MapCache * map); +void allRestricted(DFHack::DFCoord coord, MapExtras::MapCache * map); DFhackCExport const char * plugin_name ( void ) { @@ -27,7 +42,8 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector { commands.clear(); commands.push_back(PluginCommand("filltraffic","Flood-fill with selected traffic designation from cursor",filltraffic)); - commands.push_back(PluginCommand("tiletraffic","Set traffic for all tiles based on given criteria",tiletraffic)); + commands.push_back(PluginCommand("alltraffic","Set traffic for the entire map",alltraffic)); + return CR_OK; } @@ -60,7 +76,7 @@ DFhackCExport command_result filltraffic(DFHack::Core * c, std::vector & params) +DFhackCExport command_result alltraffic(DFHack::Core * c, std::vector & params) { - //Target traffic types. - e_traffic target = traffic_normal; - //!!! Options Later !!! - + void (*proc)(DFHack::DFCoord, MapExtras::MapCache *) = allNormal; + //Loop through parameters for(int i = 0; i < params.size();i++) { @@ -248,19 +262,30 @@ DFhackCExport command_result tiletraffic(DFHack::Core * c, std::vectorSuspend(); @@ -280,27 +305,76 @@ DFhackCExport command_result tiletraffic(DFHack::Core * c, std::vector maxCoord.x) + { + c->con.printerr("Minimum x coordinate is greater than maximum x coordinate.\n"); + c->Resume(); + return CR_FAILURE; + } + if (minCoord.y > maxCoord.y) + { + c->con.printerr("Minimum y coordinate is greater than maximum y coordinate.\n"); + c->Resume(); + return CR_FAILURE; + } + if (minCoord.z > maxCoord.y) + { + c->con.printerr("Minimum z coordinate is greater than maximum z coordinate.\n"); + c->Resume(); + return CR_FAILURE; + } + MapExtras::MapCache * MCache = new MapExtras::MapCache(Maps); - c->con.print("Entire map ... FILLING!\n"); + c->con.print("Setting traffic...\n"); //Loop through every single tile - for(uint32_t x = 0; x <= tx_max; x++) + for(uint32_t x = minCoord.x; x <= maxCoord.x; x++) { - for(uint32_t y = 0; y <= ty_max; y++) + for(uint32_t y = minCoord.y; y <= maxCoord.y; y++) { - for(uint32_t z = 0; z <= z_max; z++) + for(uint32_t z = minCoord.z; z <= maxCoord.z; z++) { DFHack::DFCoord tile = DFHack::DFCoord(x, y, z); - DFHack::t_designation des = MCache->designationAt(tile); - - des.bits.traffic = target; - MCache->setDesignationAt(tile, des); + checkProc(tile, MCache); } } } MCache->WriteAll(); + c->con.print("Complete!\n"); c->Resume(); return CR_OK; +} + +//Unconditionally set map to target traffic type +void allHigh(DFHack::DFCoord coord, MapExtras::MapCache * map) +{ + DFHack::t_designation des = map->designationAt(coord); + des.bits.traffic = traffic_high; + map->setDesignationAt(coord, des); +} +void allNormal(DFHack::DFCoord coord, MapExtras::MapCache * map) +{ + DFHack::t_designation des = map->designationAt(coord); + des.bits.traffic = traffic_normal; + map->setDesignationAt(coord, des); +} +void allLow(DFHack::DFCoord coord, MapExtras::MapCache * map) +{ + DFHack::t_designation des = map->designationAt(coord); + des.bits.traffic = traffic_low; + map->setDesignationAt(coord, des); +} +void allRestricted(DFHack::DFCoord coord, MapExtras::MapCache * map) +{ + DFHack::t_designation des = map->designationAt(coord); + des.bits.traffic = traffic_restricted; + map->setDesignationAt(coord, des); } \ No newline at end of file diff --git a/plugins/fixwagons.cpp b/plugins/fixwagons.cpp new file mode 100644 index 000000000..29253880e --- /dev/null +++ b/plugins/fixwagons.cpp @@ -0,0 +1,110 @@ +// I'll fix his little red wagon... + +#include "Core.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using std::string; +using std::vector; +using namespace DFHack; + +using df::global::world; +using df::historical_entity; +using df::entity_raw_flags; +using df::creature_raw; +using df::creature_raw_flags; + +command_result df_fixwagons (Core *c, vector ¶meters) +{ + if (!parameters.empty()) + return CR_WRONG_USAGE; + + CoreSuspender suspend(c); + int32_t wagon_creature = -1, wagon_puller_creature = -1; + creature_raw *wagon, *wagon_puller; + for (int i = 0; i < world->raws.creatures.all.size(); i++) + { + creature_raw *cr = world->raws.creatures.all[i]; + if (cr->flags.is_set(creature_raw_flags::EQUIPMENT_WAGON) && (wagon_creature == -1)) + { + wagon = cr; + wagon_creature = i; + } + if ((cr->creature_id == "HORSE") && (wagon_puller_creature == -1)) + { + wagon_puller = cr; + wagon_puller_creature = i; + } + } + if (wagon_creature == -1) + { + c->con.printerr("Couldn't find a valid wagon creature!\n"); + return CR_FAILURE; + } + if (wagon_puller_creature == -1) + { + c->con.printerr("Couldn't find 'HORSE' creature for default wagon puller!\n"); + return CR_FAILURE; + } + int count = 0; + for (int i = 0; i < world->entities.all.size(); i++) + { + bool updated = false; + historical_entity *ent = world->entities.all[i]; + if (!ent->entity_raw->flags.is_set(entity_raw_flags::COMMON_DOMESTIC_PULL)) + continue; + if (ent->resources.animals.wagon_races.size() == 0) + { + updated = true; + for (int j = 0; j < wagon->caste.size(); j++) + { + ent->resources.animals.wagon_races.push_back(wagon_creature); + ent->resources.animals.wagon_castes.push_back(j); + } + } + if (ent->resources.animals.wagon_puller_races.size() == 0) + { + updated = true; + for (int j = 0; j < wagon_puller->caste.size(); j++) + { + ent->resources.animals.wagon_puller_races.push_back(wagon_puller_creature); + ent->resources.animals.wagon_puller_castes.push_back(j); + } + } + if (updated) + count++; + } + if(count) + c->con.print("Fixed %d civilizations to bring wagons once again.\n", count); + return CR_OK; +} + +DFhackCExport const char * plugin_name ( void ) +{ + return "fixwagons"; +} + +DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +{ + commands.clear(); + commands.push_back(PluginCommand( + "fixwagons", "Fix all civilizations to be able to bring wagons.", + df_fixwagons, false, + " Since DF v0.31.1 merchants no longer bring wagons due to a bug.\n" + " This command re-enables them for all appropriate civilizations.\n" + )); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} diff --git a/plugins/flows.cpp b/plugins/flows.cpp index b82d01adb..c5b588903 100644 --- a/plugins/flows.cpp +++ b/plugins/flows.cpp @@ -6,11 +6,11 @@ #include #include using namespace std; -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include using namespace DFHack; DFhackCExport command_result df_flows (Core * c, vector & parameters); diff --git a/plugins/getplants.cpp b/plugins/getplants.cpp index dbec990f0..14fb8b90c 100644 --- a/plugins/getplants.cpp +++ b/plugins/getplants.cpp @@ -8,14 +8,14 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include +#include +#include using namespace std; using namespace DFHack; diff --git a/plugins/initflags.cpp b/plugins/initflags.cpp index f27a318ae..c7a634b78 100644 --- a/plugins/initflags.cpp +++ b/plugins/initflags.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include -#include -#include +#include +#include using std::vector; using std::string; @@ -26,8 +26,10 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & { commands.clear(); if (d_init) { - commands.push_back(PluginCommand("twaterlvl", "Toggle display of water/magma depth.", twaterlvl)); - commands.push_back(PluginCommand("tidlers", "Toggle display of idlers.", tidlers)); + commands.push_back(PluginCommand("twaterlvl", "Toggle display of water/magma depth.", + twaterlvl, dwarfmode_hotkey)); + commands.push_back(PluginCommand("tidlers", "Toggle display of idlers.", + tidlers, dwarfmode_hotkey)); } std::cerr << "d_init: " << sizeof(df::d_init) << endl; return CR_OK; @@ -40,21 +42,16 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result twaterlvl(Core * c, vector & parameters) { - c->Suspend(); + // HOTKEY COMMAND: CORE ALREADY SUSPENDED df::global::d_init->flags1.toggle(d_init_flags1::SHOW_FLOW_AMOUNTS); c->con << "Toggled the display of water/magma depth." << endl; - c->Resume(); return CR_OK; } DFhackCExport command_result tidlers(Core * c, vector & parameters) { - c->Suspend(); - df::d_init_idlers iv = df::d_init_idlers(int(d_init->idlers) + 1); - if (!d_init_idlers::is_valid(iv)) - iv = ENUM_FIRST_ITEM(d_init_idlers); - d_init->idlers = iv; - c->con << "Toggled the display of idlers to " << ENUM_KEY_STR(d_init_idlers, iv) << endl; - c->Resume(); + // HOTKEY COMMAND: CORE ALREADY SUSPENDED + d_init->idlers = ENUM_NEXT_ITEM(d_init_idlers, d_init->idlers); + c->con << "Toggled the display of idlers to " << ENUM_KEY_STR(d_init_idlers, d_init->idlers) << endl; return CR_OK; } diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp new file mode 100644 index 000000000..66ed00024 --- /dev/null +++ b/plugins/jobutils.cpp @@ -0,0 +1,534 @@ +#include "Core.h" +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; +using std::string; +using std::endl; +using namespace DFHack; +using namespace df::enums; + +using df::global::world; +using df::global::ui; +using df::global::ui_build_selector; +using df::global::ui_workshop_job_cursor; +using df::global::job_next_id; + +/* Plugin registration */ + +static bool workshop_job_hotkey(Core *c, df::viewscreen *top); +static bool build_selector_hotkey(Core *c, df::viewscreen *top); +static bool job_material_hotkey(Core *c, df::viewscreen *top); + +static command_result job_material(Core *c, vector & parameters); +static command_result job_duplicate(Core *c, vector & parameters); +static command_result job_cmd(Core *c, vector & parameters); + +DFhackCExport const char * plugin_name ( void ) +{ + return "jobutils"; +} + +DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +{ + commands.clear(); + if (!world || !ui) + return CR_FAILURE; + + commands.push_back( + PluginCommand( + "job", "General job query and manipulation.", + job_cmd, false, + " job query\n" + " Print details of the current job.\n" + " job list\n" + " Print details of all jobs in the workshop.\n" + " job item-material [submaterial]\n" + " Replace the exact material id in the job item.\n" + ) + ); + + if (ui_workshop_job_cursor || ui_build_selector) { + commands.push_back( + PluginCommand( + "job-material", "Alter the material of the selected job.", + job_material, job_material_hotkey, + " job-material \n" + "Intended to be used as a keybinding:\n" + " - In 'q' mode, when a job is highlighted within a workshop\n" + " or furnace, changes the material of the job.\n" + " - In 'b' mode, during selection of building components\n" + " positions the cursor over the first available choice\n" + " with the matching material.\n" + ) + ); + } + + if (ui_workshop_job_cursor && job_next_id) { + commands.push_back( + PluginCommand( + "job-duplicate", "Duplicate the selected job in a workshop.", + job_duplicate, workshop_job_hotkey, + " - In 'q' mode, when a job is highlighted within a workshop\n" + " or furnace building, instantly duplicates the job.\n" + ) + ); + } + + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} + +/* UI state guards */ + +static bool workshop_job_hotkey(Core *c, df::viewscreen *top) +{ + using namespace ui_sidebar_mode; + + if (!dwarfmode_hotkey(c,top)) + return false; + + switch (ui->main.mode) { + case QueryBuilding: + { + if (!ui_workshop_job_cursor) // allow missing + return false; + + df::building *selected = world->selected_building; + if (!virtual_cast(selected) && + !virtual_cast(selected)) + return false; + + // No jobs? + if (selected->jobs.empty() || + selected->jobs[0]->job_type == job_type::DestroyBuilding) + return false; + + // Add job gui activated? + if (df::global::ui_workshop_in_add && // allow missing + *df::global::ui_workshop_in_add) + return false; + + return true; + }; + default: + return false; + } +} + +static bool build_selector_hotkey(Core *c, df::viewscreen *top) +{ + using namespace ui_sidebar_mode; + + if (!dwarfmode_hotkey(c,top)) + return false; + + switch (ui->main.mode) { + case Build: + { + if (!ui_build_selector) // allow missing + return false; + + // Not selecting, or no choices? + if (ui_build_selector->building_type < 0 || + ui_build_selector->stage != 2 || + ui_build_selector->choices.empty()) + return false; + + return true; + }; + default: + return false; + } +} + +static bool job_material_hotkey(Core *c, df::viewscreen *top) +{ + return workshop_job_hotkey(c, top) || + build_selector_hotkey(c, top); +} + +/* job-material implementation */ + +static df::job *getWorkshopJob(Core *c) +{ + df::building *selected = world->selected_building; + int idx = *ui_workshop_job_cursor; + + if (idx < 0 || idx >= selected->jobs.size()) + { + c->con.printerr("Invalid job cursor index: %d\n", idx); + return NULL; + } + + return selected->jobs[idx]; +} + +static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) +{ + df::job *job = getWorkshopJob(c); + if (!job) + return CR_FAILURE; + + MaterialInfo cur_mat(job); + + if (!cur_mat.isValid() || cur_mat.type != 0) + { + c->con.printerr("Current job material isn't inorganic: %s\n", + cur_mat.toString().c_str()); + return CR_FAILURE; + } + + df::craft_material_class old_class = cur_mat.getCraftClass(); + if (old_class == craft_material_class::None) + { + c->con.printerr("Unexpected current material type: %s\n", + cur_mat.toString().c_str()); + return CR_FAILURE; + } + if (new_mat.getCraftClass() != old_class) + { + c->con.printerr("New material %s does not satisfy requirement: %s\n", + new_mat.toString().c_str(), ENUM_KEY_STR(craft_material_class, old_class)); + return CR_FAILURE; + } + + for (unsigned i = 0; i < job->job_items.size(); i++) + { + df::job_item *item = job->job_items[i]; + MaterialInfo item_mat(item); + + if (item_mat != cur_mat) + { + c->con.printerr("Job item %d has different material: %s\n", + i, item_mat.toString().c_str()); + return CR_FAILURE; + } + } + + // Apply the substitution + job->mat_type = new_mat.type; + job->mat_index = new_mat.index; + + for (unsigned i = 0; i < job->job_items.size(); i++) + { + df::job_item *item = job->job_items[i]; + item->mat_type = new_mat.type; + item->mat_index = new_mat.index; + } + + c->con << "Applied material '" << new_mat.toString() + << "' to job " << ENUM_KEY_STR(job_type,job->job_type) << endl; + return CR_OK; +} + +static bool build_choice_matches(df::ui_build_item_req *req, df::build_req_choicest *choice, + MaterialInfo &new_mat) +{ + if (VIRTUAL_CAST_VAR(gen, df::build_req_choice_genst, choice)) + { + if (gen->mat_type == new_mat.type && + gen->mat_index == new_mat.index && + gen->used_count < gen->candidates.size()) + { + return true; + } + } + else if (VIRTUAL_CAST_VAR(spec, df::build_req_choice_specst, choice)) + { + if (spec->candidate && + spec->candidate->getActualMaterial() == new_mat.type && + spec->candidate->getActualMaterialIndex() == new_mat.index && + !req->candidate_selected[spec->candidate_id]) + { + return true; + } + } + + return false; +} + +static command_result job_material_in_build(Core *c, MaterialInfo &new_mat) +{ + df::ui_build_item_req *req = ui_build_selector->requirements[ui_build_selector->req_index]; + + for (unsigned i = 0; i < ui_build_selector->choices.size(); i++) + { + if (build_choice_matches(req, ui_build_selector->choices[i], new_mat)) + { + ui_build_selector->sel_index = i; + return CR_OK; + } + } + + c->con.printerr("Could not find material in list: %s\n", new_mat.toString().c_str()); + return CR_FAILURE; +} + +static command_result job_material(Core * c, vector & parameters) +{ + // HOTKEY COMMAND: CORE ALREADY SUSPENDED + + MaterialInfo new_mat; + if (parameters.size() == 1) + { + if (!new_mat.findInorganic(parameters[0])) { + c->con.printerr("Could not find inorganic material: %s\n", parameters[0].c_str()); + return CR_WRONG_USAGE; + } + } + else + return CR_WRONG_USAGE; + + if (ui->main.mode == ui_sidebar_mode::QueryBuilding) + return job_material_in_job(c, new_mat); + if (ui->main.mode == ui_sidebar_mode::Build) + return job_material_in_build(c, new_mat); + + return CR_WRONG_USAGE; +} + +/* job-duplicate implementation */ + +static df::job *clone_job(df::job *job) +{ + df::job *pnew = new df::job(*job); + + pnew->id = (*job_next_id)++; + + // Clean out transient fields + pnew->flags.whole = 0; + pnew->flags.bits.repeat = job->flags.bits.repeat; + + pnew->completion_timer = -1; + pnew->items.clear(); + pnew->misc_links.clear(); + + // Link the job into the global list + pnew->list_link = new df::job_list_link(); + pnew->list_link->item = pnew; + + linked_list_append(&world->job_list, pnew->list_link); + + // Clone refs + for (int i = pnew->references.size()-1; i >= 0; i--) + { + df::general_ref *ref = pnew->references[i]; + + if (virtual_cast(ref)) + pnew->references.erase(pnew->references.begin()+i); + else + pnew->references[i] = ref->clone(); + } + + // Clone items + for (int i = pnew->job_items.size()-1; i >= 0; i--) + pnew->job_items[i] = new df::job_item(*pnew->job_items[i]); + + return pnew; +} + +static command_result job_duplicate(Core * c, vector & parameters) +{ + if (!parameters.empty()) + return CR_WRONG_USAGE; + + df::job *job = getWorkshopJob(c); + if (!job) + return CR_FAILURE; + + if (!job->misc_links.empty() || job->job_items.empty()) + { + c->con.printerr("Cannot duplicate job %s\n", ENUM_KEY_STR(job_type,job->job_type)); + return CR_FAILURE; + } + + df::building *building = world->selected_building; + if (building->jobs.size() >= 10) + { + c->con.printerr("Job list is already full.\n"); + return CR_FAILURE; + } + + // Actually clone + df::job *pnew = clone_job(job); + + int pos = ++*ui_workshop_job_cursor; + building->jobs.insert(building->jobs.begin()+pos, pnew); + + return CR_OK; +} + +/* Main job command implementation */ + +static void print_job_item_details(Core *c, df::job *job, unsigned idx, df::job_item *item) +{ + c->con << " Input Item " << (idx+1) << ": " << ENUM_KEY_STR(item_type,item->item_type); + if (item->item_subtype != -1) + c->con << " [" << item->item_subtype << "]"; + if (item->quantity != 1) + c->con << "; quantity=" << item->quantity; + if (item->min_dimension >= 0) + c->con << "; min_dimension=" << item->min_dimension; + c->con << endl; + + MaterialInfo mat(item); + if (mat.isValid() || item->metal_ore >= 0) { + c->con << " material: " << mat.toString(); + if (item->metal_ore >= 0) + c->con << "; ore of " << MaterialInfo(0,item->metal_ore).toString(); + c->con << endl; + } + + if (item->flags1.whole) + c->con << " flags1: " << bitfieldToString(item->flags1) << endl; + if (item->flags2.whole) + c->con << " flags2: " << bitfieldToString(item->flags2) << endl; + if (item->flags3.whole) + c->con << " flags3: " << bitfieldToString(item->flags3) << endl; + + if (!item->reaction_class.empty()) + c->con << " reaction class: " << item->reaction_class << endl; + if (!item->has_material_reaction_product.empty()) + c->con << " reaction product: " << item->has_material_reaction_product << endl; + if (item->has_tool_use >= 0) + c->con << " tool use: " << ENUM_KEY_STR(tool_uses, item->has_tool_use) << endl; +} + +static void print_job_details(Core *c, df::job *job) +{ + c->con << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type); + if (job->flags.whole) + c->con << " (" << bitfieldToString(job->flags) << ")"; + c->con << endl; + + MaterialInfo mat(job); + if (mat.isValid() || job->material_category.whole) + { + c->con << " material: " << mat.toString(); + if (job->material_category.whole) + c->con << " (" << bitfieldToString(job->material_category) << ")"; + c->con << endl; + } + + if (job->item_subtype >= 0 || job->item_category.whole) + c->con << " item: " << job->item_subtype + << " (" << bitfieldToString(job->item_category) << ")" << endl; + + if (job->hist_figure_id >= 0) + c->con << " figure: " << job->hist_figure_id << endl; + + if (!job->reaction_name.empty()) + c->con << " reaction: " << job->reaction_name << endl; + + for (unsigned i = 0; i < job->job_items.size(); i++) + print_job_item_details(c, job, i, job->job_items[i]); +} + +static df::job *getWorkshopJobSafe(Core *c) +{ + if (!workshop_job_hotkey(c, c->getTopViewscreen())) { + c->con.printerr("No job is highlighted.\n"); + return NULL; + } + + return getWorkshopJob(c); +} + +static command_result job_cmd(Core * c, vector & parameters) +{ + CoreSuspender suspend(c); + + if (parameters.empty()) + return CR_WRONG_USAGE; + + std::string cmd = parameters[0]; + if (cmd == "query" || cmd == "list") + { + df::job *job = getWorkshopJobSafe(c); + if (!job) + return CR_WRONG_USAGE; + + if (cmd == "query") { + print_job_details(c, job); + } else { + df::building *selected = world->selected_building; + for (unsigned i = 0; i < selected->jobs.size(); i++) + print_job_details(c, selected->jobs[i]); + } + } + else if (cmd == "item-material") + { + if (parameters.size() < 1+1+1) + return CR_WRONG_USAGE; + + df::job *job = getWorkshopJobSafe(c); + if (!job) + return CR_WRONG_USAGE; + + int v = atoi(parameters[1].c_str()); + if (v < 1 || v > job->job_items.size()) { + c->con.printerr("Invalid item index.\n"); + return CR_WRONG_USAGE; + } + + df::job_item *item = job->job_items[v-1]; + + std::string subtoken = (parameters.size()>3 ? parameters[3] : ""); + MaterialInfo info; + if (!info.find(parameters[2], subtoken)) { + c->con.printerr("Could not find the specified material.\n"); + return CR_FAILURE; + } + + if (!info.matches(*item)) { + c->con.printerr("Material does not match the requirements.\n"); + print_job_details(c, job); + return CR_FAILURE; + } + + if (job->mat_type != -1 && + job->mat_type == item->mat_type && + job->mat_index == item->mat_index) + { + job->mat_type = info.type; + job->mat_index = info.index; + } + + item->mat_type = info.type; + item->mat_index = info.index; + + c->con << "Job item " << v << " updated." << endl; + print_job_details(c, job); + return CR_OK; + } + else + return CR_WRONG_USAGE; + + return CR_OK; +} diff --git a/plugins/liquids.cpp b/plugins/liquids.cpp index 92067ba7e..17f4e6309 100644 --- a/plugins/liquids.cpp +++ b/plugins/liquids.cpp @@ -9,15 +9,15 @@ using std::string; using std::endl; using std::set; -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace MapExtras; using namespace DFHack; diff --git a/plugins/mode.cpp b/plugins/mode.cpp index 4a64fd2b8..2ca741ae2 100644 --- a/plugins/mode.cpp +++ b/plugins/mode.cpp @@ -1,13 +1,13 @@ #include using namespace std; -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include #include #include -#include +#include #include using namespace DFHack; diff --git a/plugins/plants.cpp b/plugins/plants.cpp index 7afa0d897..4d8960cee 100644 --- a/plugins/plants.cpp +++ b/plugins/plants.cpp @@ -5,15 +5,15 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include +#include +#include +#include using std::vector; using std::string; diff --git a/plugins/probe.cpp b/plugins/probe.cpp index 59588185f..a000d9e31 100644 --- a/plugins/probe.cpp +++ b/plugins/probe.cpp @@ -9,18 +9,18 @@ #include using namespace std; -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include using std::vector; using std::string; diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp index 5e642ed5a..6287734c1 100644 --- a/plugins/prospector.cpp +++ b/plugins/prospector.cpp @@ -14,11 +14,10 @@ using namespace std; #include -#include -#include -#include -#include -#include +#include +#include "Core.h" +#include +#include using namespace DFHack; diff --git a/plugins/qtplug/qtplug.cpp b/plugins/qtplug/qtplug.cpp index 2c6dbf3ad..a33c28ad5 100644 --- a/plugins/qtplug/qtplug.cpp +++ b/plugins/qtplug/qtplug.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/plugins/regrass.cpp b/plugins/regrass.cpp new file mode 100644 index 000000000..bd227638e --- /dev/null +++ b/plugins/regrass.cpp @@ -0,0 +1,83 @@ +// All above-ground soil not covered by buildings will be covered with grass. +// Necessary for worlds generated prior to version 0.31.19 - otherwise, outdoor shrubs and trees no longer grow. + +#include "Core.h" +#include +#include +#include + +#include +#include +#include +#include + +using std::string; +using std::vector; +using namespace DFHack; + +using df::global::world; +using df::map_block; + +DFhackCExport command_result df_regrass (Core * c, vector & parameters) +{ + if (!parameters.empty()) + return CR_WRONG_USAGE; + + CoreSuspender suspend(c); + + int count = 0; + for (int i = 0; i < world->map.map_blocks.size(); i++) + { + map_block *cur = world->map.map_blocks[i]; + for (int x = 0; x < 16; x++) + { + for (int y = 0; y < 16; y++) + { + if (DFHack::tileShape(cur->tiletype[x][y]) != DFHack::FLOOR) + continue; + if (DFHack::tileMaterial(cur->tiletype[x][y]) != DFHack::SOIL) + continue; + if (cur->designation[x][y].bits.subterranean) + continue; + if (cur->occupancy[x][y].bits.building) + continue; + + switch (rand() % 8) + { + // light grass + case 0: cur->tiletype[x][y] = 0x015C; break; + case 1: cur->tiletype[x][y] = 0x015D; break; + case 2: cur->tiletype[x][y] = 0x015E; break; + case 3: cur->tiletype[x][y] = 0x015F; break; + // dark grass + case 4: cur->tiletype[x][y] = 0x018E; break; + case 5: cur->tiletype[x][y] = 0x018F; break; + case 6: cur->tiletype[x][y] = 0x0190; break; + case 7: cur->tiletype[x][y] = 0x0191; break; + } + count++; + } + } + } + + if (count) + c->con.print("Regrew %d tiles of grass.\n", count); + return CR_OK; +} + +DFhackCExport const char *plugin_name ( void ) +{ + return "regrass"; +} + +DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +{ + commands.clear(); + commands.push_back(PluginCommand("regrass", "Regrows all surface grass, restoring outdoor plant growth for pre-0.31.19 worlds.", df_regrass)); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} diff --git a/plugins/rename.cpp b/plugins/rename.cpp new file mode 100644 index 000000000..17841c5fa --- /dev/null +++ b/plugins/rename.cpp @@ -0,0 +1,90 @@ +#include "Core.h" +#include +#include +#include + +#include +#include +#include +#include + +#include + +using std::vector; +using std::string; +using std::endl; +using namespace DFHack; +using namespace df::enums; + +using df::global::ui; +using df::global::world; + +static command_result rename(Core * c, vector & parameters); + +DFhackCExport const char * plugin_name ( void ) +{ + return "rename"; +} + +DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +{ + commands.clear(); + if (world && ui) { + commands.push_back(PluginCommand("rename", "Rename various things.", rename)); + } + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} + +static command_result usage(Core *c) +{ + c->con << "Usage:" << endl + << " rename squad \"name\"" << endl + << " rename hotkey \"name\"" << endl; + return CR_OK; +} + +static command_result rename(Core * c, vector ¶meters) +{ + CoreSuspender suspend(c); + + string cmd; + if (!parameters.empty()) + cmd = parameters[0]; + + if (cmd == "squad") { + if (parameters.size() != 3) + return usage(c); + + std::vector &squads = world->squads.all; + + int id = atoi(parameters[1].c_str()); + if (id < 1 || id > squads.size()) { + c->con.printerr("Invalid squad index\n"); + return usage(c); + } + + squads[id-1]->alias = parameters[2]; + } else if (cmd == "hotkey") { + if (parameters.size() != 3) + return usage(c); + + int id = atoi(parameters[1].c_str()); + if (id < 1 || id > 16) { + c->con.printerr("Invalid hotkey index\n"); + return usage(c); + } + + ui->main.hotkeys[id-1].name = parameters[2]; + } else { + if (!parameters.empty() && cmd != "?") + c->con.printerr("Invalid command: %s\n", cmd.c_str()); + return usage(c); + } + + return CR_OK; +} diff --git a/plugins/reveal.cpp b/plugins/reveal.cpp index 5d7c1df29..ce37f3f1e 100644 --- a/plugins/reveal.cpp +++ b/plugins/reveal.cpp @@ -2,14 +2,14 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include +#include +#include using MapExtras::MapCache; using namespace DFHack; diff --git a/plugins/seedwatch.cpp b/plugins/seedwatch.cpp index 418398e3d..3b83338e2 100755 --- a/plugins/seedwatch.cpp +++ b/plugins/seedwatch.cpp @@ -1,19 +1,18 @@ -// This does not work with Linux Dwarf Fortress +// This does not work with Linux Dwarf Fortress // With thanks to peterix for DFHack and Quietust for information http://www.bay12forums.com/smf/index.php?topic=91166.msg2605147#msg2605147 #include #include #include -#include "dfhack/Console.h" -#include "dfhack/Core.h" -#include "dfhack/Export.h" -#include "dfhack/PluginManager.h" -#include "dfhack/Process.h" -#include "dfhack/modules/Materials.h" -#include "dfhack/modules/Items.h" -#include "dfhack/modules/World.h" -#include "dfhack/modules/kitchen.h" -#include +#include "Console.h" +#include "Core.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Materials.h" +#include "modules/Items.h" +#include "modules/World.h" +#include "modules/kitchen.h" +#include using DFHack::t_materialType; using DFHack::t_materialIndex; @@ -288,10 +287,32 @@ DFhackCExport DFHack::command_result plugin_init(DFHack::Core* pCore, std::vecto return DFHack::CR_OK; } +DFhackCExport DFHack::command_result plugin_onstatechange(DFHack::Core* pCore, DFHack::state_change_event event) +{ + switch (event) { + case DFHack::SC_GAME_LOADED: + case DFHack::SC_GAME_UNLOADED: + if (running) + pCore->con.printerr("seedwatch deactivated due to game load/unload\n"); + running = false; + break; + default: + break; + } + + return DFHack::CR_OK; +} + DFhackCExport DFHack::command_result plugin_onupdate(DFHack::Core* pCore) { - if(running) + if (running) { + // reduce processing rate + static int counter = 0; + if (++counter < 500) + return DFHack::CR_OK; + counter = 0; + DFHack::Core& core = *pCore; DFHack::World *w = core.getWorld(); DFHack::t_gamemodes gm; diff --git a/plugins/server/main.cpp b/plugins/server/main.cpp index b47128c50..91dabc6f0 100644 --- a/plugins/server/main.cpp +++ b/plugins/server/main.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include #include #ifndef LINUX_BUILD #include diff --git a/plugins/skeleton/skeleton.cpp b/plugins/skeleton/skeleton.cpp index d69a2dd95..1b3ad398d 100644 --- a/plugins/skeleton/skeleton.cpp +++ b/plugins/skeleton/skeleton.cpp @@ -1,10 +1,10 @@ // This is a generic plugin that does nothing useful apart from acting as an example... of a plugin that does nothing :D // some headers required for a plugin. Nothing special, just the basics. -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include using namespace DFHack; // our own, empty header. diff --git a/plugins/stockpiles.cpp b/plugins/stockpiles.cpp index 5cd153335..e104ec908 100644 --- a/plugins/stockpiles.cpp +++ b/plugins/stockpiles.cpp @@ -1,12 +1,14 @@ -#include -#include -#include -#include - -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include using std::vector; using std::string; @@ -16,10 +18,12 @@ using namespace df::enums; using df::global::world; using df::global::ui; +using df::global::selection_rect; using df::building_stockpilest; -DFhackCExport command_result copystock(Core * c, vector & parameters); +static command_result copystock(Core *c, vector & parameters); +static bool copystock_guard(Core *c, df::viewscreen *top); DFhackCExport const char * plugin_name ( void ) { @@ -30,7 +34,16 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & { commands.clear(); if (world && ui) { - commands.push_back(PluginCommand("copystock", "Copy stockpile under cursor.", copystock)); + commands.push_back( + PluginCommand( + "copystock", "Copy stockpile under cursor.", + copystock, copystock_guard, + " - In 'q' or 't' mode: select a stockpile and invoke in order\n" + " to switch to the 'p' stockpile creation mode, and initialize\n" + " the custom settings from the selected stockpile.\n" + " - In 'p': invoke in order to switch back to 'q'.\n" + ) + ); } std::cerr << "world: " << sizeof(df::world) << " ui: " << sizeof(df::ui) << " b_stock: " << sizeof(building_stockpilest) << endl; @@ -42,40 +55,43 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) return CR_OK; } -bool inSelectMode() { +static bool copystock_guard(Core *c, df::viewscreen *top) +{ using namespace ui_sidebar_mode; + if (!dwarfmode_hotkey(c,top)) + return false; + switch (ui->main.mode) { + case Stockpiles: + return true; case BuildingItems: case QueryBuilding: - return true; + return !!virtual_cast(world->selected_building); default: return false; } } -DFhackCExport command_result copystock(Core * c, vector & parameters) +static command_result copystock(Core * c, vector & parameters) { - CoreSuspender suspend(c); + // HOTKEY COMMAND: CORE ALREADY SUSPENDED // For convenience: when used in the stockpiles mode, switch to 'q' if (ui->main.mode == ui_sidebar_mode::Stockpiles) { world->selected_building = NULL; // just in case it contains some kind of garbage ui->main.mode = ui_sidebar_mode::QueryBuilding; + selection_rect->start_x = -30000; c->con << "Switched back to query building." << endl; return CR_OK; } - if (!inSelectMode()) { - c->con << "Cannot copy stockpile in mode " << ENUM_KEY_STR(ui_sidebar_mode, ui->main.mode) << endl; - return CR_OK; - } - building_stockpilest *sp = virtual_cast(world->selected_building); - if (!sp) { - c->con << "Selected building isn't a stockpile." << endl; - return CR_OK; + if (!sp) + { + c->con.printerr("Selected building isn't a stockpile.\n"); + return CR_WRONG_USAGE; } ui->stockpile.custom_settings = sp->settings; diff --git a/plugins/stonesense b/plugins/stonesense index dbfeaf935..545b2730e 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit dbfeaf935df92644b72746842166baf700450e15 +Subproject commit 545b2730ed137935643778f1b8ba115ae11c50a2 diff --git a/plugins/tiletypes.cpp b/plugins/tiletypes.cpp index e15d787f7..57184f013 100644 --- a/plugins/tiletypes.cpp +++ b/plugins/tiletypes.cpp @@ -10,15 +10,15 @@ using std::string; using std::endl; using std::set; -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace MapExtras; using namespace DFHack; @@ -63,6 +63,7 @@ struct TileType DFHack::TileMaterial material; DFHack::TileSpecial special; DFHack::TileVariant variant; + int dig; int hidden; int light; int subterranean; @@ -74,6 +75,7 @@ struct TileType material = DFHack::tilematerial_invalid; special = DFHack::tilespecial_invalid; variant = DFHack::tilevariant_invalid; + dig = -1; hidden = -1; light = -1; subterranean = -1; @@ -83,7 +85,8 @@ struct TileType bool empty() { return shape == -1 && material == -1 && special == -1 && variant == -1 - && hidden == -1 && light == -1 && subterranean == -1 && skyview == -1; + && hidden == -1 && light == -1 && subterranean == -1 && skyview == -1 + && dig == -1; } }; @@ -138,6 +141,19 @@ std::ostream &operator<<(std::ostream &stream, const TileType &paint) needSpace = true; } + if (paint.dig >= 0) + { + if (needSpace) + { + stream << " "; + needSpace = false; + } + + stream << (paint.dig ? "DESIGNATED" : "UNDESIGATNED"); + used = true; + needSpace = true; + } + if (paint.hidden >= 0) { if (needSpace) @@ -300,6 +316,18 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri std::cout << "Unknown tile variant: " << value << std::endl; } } + else if (option == "designated" || option == "d") + { + if (valInt >= -1 && valInt < 2) + { + paint.dig = valInt; + found = true; + } + else + { + std::cout << "Unknown designation flag: " << value << std::endl; + } + } else if (option == "hidden" || option == "h") { if (valInt >= -1 && valInt < 2) @@ -374,6 +402,7 @@ void help( std::ostream & out, const std::string &option) << " Material / mat / m: set tile material information" << std::endl << " Special / sp: set special tile information" << std::endl << " Variant / var / v: set variant tile information" << std::endl + << " Designated / d: set designated flag" << std::endl << " Hidden / h: set hidden flag" << std::endl << " Light / l: set light flag" << std::endl << " Subterranean / st: set subterranean flag" << std::endl @@ -412,6 +441,11 @@ void help( std::ostream & out, const std::string &option) out << "Available variants:" << std::endl << " ANY, 0 - " << DFHack::VAR_4 << std::endl; } + else if (option == "designated" || option == "d") + { + out << "Available designated flags:" << std::endl + << " ANY, 0, 1" << std::endl; + } else if (option == "hidden" || option == "h") { out << "Available hidden flags:" << std::endl @@ -746,11 +780,13 @@ DFhackCExport command_result df_tiletypes (Core * c, vector & parameter for (coord_vec::iterator iter = all_tiles.begin(); iter != all_tiles.end(); ++iter) { const DFHack::TileRow *source = DFHack::getTileRow(map.tiletypeAt(*iter)); + DFHack::t_designation des = map.designationAt(*iter); if ((filter.shape > -1 && filter.shape != source->shape) || (filter.material > -1 && filter.material != source->material) || (filter.special > -1 && filter.special != source->special) || (filter.variant > -1 && filter.variant != source->variant) + || (filter.dig > -1 && (filter.dig != 0) != (des.bits.dig != DFHack::designation_no)) ) { continue; @@ -812,8 +848,6 @@ DFhackCExport command_result df_tiletypes (Core * c, vector & parameter if(type != -1) map.setTiletypeAt(*iter, type); - DFHack::t_designation des = map.designationAt(*iter); - if (paint.hidden > -1) { des.bits.hidden = paint.hidden; diff --git a/plugins/tubefill.cpp b/plugins/tubefill.cpp index 1249c20fb..23e6e992a 100644 --- a/plugins/tubefill.cpp +++ b/plugins/tubefill.cpp @@ -4,14 +4,14 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include +#include +#include using MapExtras::MapCache; using namespace DFHack; diff --git a/plugins/vdig.cpp b/plugins/vdig.cpp index e9cc0db3a..fbbd36e46 100644 --- a/plugins/vdig.cpp +++ b/plugins/vdig.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include +#include #include #include #include @@ -30,8 +30,17 @@ DFhackCExport const char * plugin_name ( void ) DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) { commands.clear(); - commands.push_back(PluginCommand("vdig","Dig a whole vein.",vdig)); - commands.push_back(PluginCommand("vdigx","Dig a whole vein, follow vein through z-levels with stairs.",vdigx)); + commands.push_back(PluginCommand( + "vdig","Dig a whole vein.",vdig,cursor_hotkey, + " Designates a whole vein under the cursor for digging.\n" + "Options:\n" + " x - follow veins through z-levels with stairs.\n" + )); + commands.push_back(PluginCommand( + "vdigx","Dig a whole vein, following through z-levels.",vdigx,cursor_hotkey, + " Designates a whole vein under the cursor for digging.\n" + " Also follows the vein between z-levels with stairs, like 'vdig x' would.\n" + )); commands.push_back(PluginCommand("expdig","Select or designate an exploratory pattern. Use 'expdig ?' for help.",expdig)); commands.push_back(PluginCommand("digcircle","Dig desingate a circle (filled or hollow) with given radius.",digcircle)); //commands.push_back(PluginCommand("autodig","Mark a tile for continuous digging.",autodig)); @@ -450,6 +459,100 @@ static digmask diag5[5] = }, }; +static digmask diag5r[5] = +{ + { + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + }, + { + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + }, + { + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + }, + { + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + }, + { + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + }, +}; + static digmask ladder[3] = { { @@ -508,6 +611,64 @@ static digmask ladder[3] = }, }; +static digmask ladderr[3] = +{ + { + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + }, + { + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + }, + { + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + }, +}; + static digmask all_tiles = { {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, @@ -551,7 +712,9 @@ enum explo_how { EXPLO_NOTHING, EXPLO_DIAG5, + EXPLO_DIAG5R, EXPLO_LADDER, + EXPLO_LADDERR, EXPLO_CLEAR, EXPLO_CROSS, }; @@ -644,6 +807,10 @@ DFhackCExport command_result expdig (Core * c, vector & parameters) { how = EXPLO_DIAG5; } + else if(parameters[i] == "diag5r") + { + how = EXPLO_DIAG5R; + } else if(parameters[i] == "clear") { how = EXPLO_CLEAR; @@ -652,6 +819,10 @@ DFhackCExport command_result expdig (Core * c, vector & parameters) { how = EXPLO_LADDER; } + else if(parameters[i] == "ladderr") + { + how = EXPLO_LADDERR; + } else if(parameters[i] == "cross") { how = EXPLO_CROSS; @@ -665,7 +836,9 @@ DFhackCExport command_result expdig (Core * c, vector & parameters) "There are two variables that can be set: pattern and filter.\n" "Patterns:\n" " diag5 = diagonals separated by 5 tiles\n" - " ladder = A 'ladder' pattern\n" + " diag5r = diag5 rotated 90 degrees\n" + " ladder = A 'ladder' pattern\n" + "ladderr = ladder rotated 90 degrees\n" " clear = Just remove all dig designations\n" " cross = A cross, exactly in the middle of the map.\n" "Filters:\n" @@ -710,6 +883,19 @@ DFhackCExport command_result expdig (Core * c, vector & parameters) } } } + else if(how == EXPLO_DIAG5R) + { + int which; + for(uint32_t x = 0; x < x_max; x++) + { + for(int32_t y = 0 ; y < y_max; y++) + { + which = (4*x + 1000-y) % 5; + stamp_pattern(maps, x,y_max - 1 - y, z_level, diag5r[which], + how, what, x_max, y_max); + } + } + } else if(how == EXPLO_LADDER) { int which; @@ -723,6 +909,19 @@ DFhackCExport command_result expdig (Core * c, vector & parameters) } } } + else if(how == EXPLO_LADDERR) + { + int which; + for(int32_t y = 0 ; y < y_max; y++) + { + which = y % 3; + for(uint32_t x = 0; x < x_max; x++) + { + stamp_pattern(maps, x, y, z_level, ladderr[which], + how, what, x_max, y_max); + } + } + } else if(how == EXPLO_CROSS) { // middle + recentering for the image @@ -760,18 +959,10 @@ DFhackCExport command_result expdig (Core * c, vector & parameters) c->Resume(); return CR_OK; } + DFhackCExport command_result vdigx (Core * c, vector & parameters) { - for(int i = 0; i < parameters.size();i++) - { - if(parameters[i] == "help" || parameters[i] == "?") - { - c->con.print("Designates a whole vein under the cursor for digging.\n" - "Also follows the vein between z-levels with stairs, like 'vdig x' would.\n" - ); - return CR_OK; - } - } + // HOTKEY COMMAND: CORE ALREADY SUSPENDED vector lol; lol.push_back("x"); return vdig(c,lol); @@ -779,32 +970,25 @@ DFhackCExport command_result vdigx (Core * c, vector & parameters) DFhackCExport command_result vdig (Core * c, vector & parameters) { + // HOTKEY COMMAND: CORE ALREADY SUSPENDED uint32_t x_max,y_max,z_max; bool updown = false; for(int i = 0; i < parameters.size();i++) { if(parameters.size() && parameters[0]=="x") updown = true; - else if(parameters[i] == "help" || parameters[i] == "?") - { - c->con.print("Designates a whole vein under the cursor for digging.\n" - "Options:\n" - "x - follow veins through z-levels with stairs.\n" - ); - return CR_OK; - } + else + return CR_WRONG_USAGE; } Console & con = c->con; - c->Suspend(); DFHack::Maps * Maps = c->getMaps(); DFHack::Gui * Gui = c->getGui(); // init the map if(!Maps->Start()) { con.printerr("Can't init map. Make sure you have a map loaded in DF.\n"); - c->Resume(); return CR_FAILURE; } @@ -816,14 +1000,12 @@ DFhackCExport command_result vdig (Core * c, vector & parameters) while(cx == -30000) { con.printerr("Cursor is not active. Point the cursor at a vein.\n"); - c->Resume(); return CR_FAILURE; } DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz); if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1) { con.printerr("I won't dig the borders. That would be cheating!\n"); - c->Resume(); return CR_FAILURE; } MapExtras::MapCache * MCache = new MapExtras::MapCache(Maps); @@ -834,7 +1016,6 @@ DFhackCExport command_result vdig (Core * c, vector & parameters) { con.printerr("This tile is not a vein.\n"); delete MCache; - c->Resume(); return CR_FAILURE; } con.print("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole); @@ -944,11 +1125,10 @@ DFhackCExport command_result vdig (Core * c, vector & parameters) } } MCache->WriteAll(); - c->Resume(); return CR_OK; } DFhackCExport command_result autodig (Core * c, vector & parameters) { return CR_NOT_IMPLEMENTED; -} \ No newline at end of file +} diff --git a/plugins/versionosd.cpp b/plugins/versionosd.cpp index 466c4a45b..5f4ff11a8 100644 --- a/plugins/versionosd.cpp +++ b/plugins/versionosd.cpp @@ -7,12 +7,12 @@ #include #include using namespace std; -#include -#include -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include +#include +#include using namespace DFHack; DFhackCExport command_result df_versionosd (Core * c, vector & parameters); diff --git a/plugins/weather.cpp b/plugins/weather.cpp index d01bfcb7b..0f2325d48 100644 --- a/plugins/weather.cpp +++ b/plugins/weather.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include +#include "Core.h" +#include +#include +#include #include #include -#include +#include using std::vector; using std::string; diff --git a/tools/examples/dfitemdump.cpp b/tools/examples/dfitemdump.cpp index a19c19734..655caf409 100644 --- a/tools/examples/dfitemdump.cpp +++ b/tools/examples/dfitemdump.cpp @@ -12,7 +12,7 @@ using namespace std; #define DFHACK_WANT_MISCUTILS #include -#include +#include int main (int argc, char *argv[]) { diff --git a/tools/examples/processenum.cpp b/tools/examples/processenum.cpp index 425b247e4..ff15c8645 100644 --- a/tools/examples/processenum.cpp +++ b/tools/examples/processenum.cpp @@ -9,7 +9,7 @@ using namespace std; #include -#include +#include using namespace DFHack; #ifndef LINUX_BUILD #endif diff --git a/tools/playground/blockflags.cpp b/tools/playground/blockflags.cpp index f46f66407..f78a8894e 100644 --- a/tools/playground/blockflags.cpp +++ b/tools/playground/blockflags.cpp @@ -6,8 +6,8 @@ using namespace std; #include -#include -#include +#include +#include int main(int argc, char *argv[]) diff --git a/tools/playground/copypaste.cpp b/tools/playground/copypaste.cpp index cc32c872f..4f584241e 100644 --- a/tools/playground/copypaste.cpp +++ b/tools/playground/copypaste.cpp @@ -13,7 +13,7 @@ #define DFHACK_WANT_MISCUTILS #define DFHACK_WANT_TILETYPES #include -#include "dfhack/modules/WindowIO.h" +#include "modules/WindowIO.h" using namespace DFHack; //bool waitTillCursorState(DFHack::Context *DF, bool On); diff --git a/tools/playground/creaturemanager.cpp b/tools/playground/creaturemanager.cpp index 59e94e9fc..0d65e9f6e 100644 --- a/tools/playground/creaturemanager.cpp +++ b/tools/playground/creaturemanager.cpp @@ -70,7 +70,7 @@ using namespace std; #define DFHACK_WANT_MISCUTILS #include -#include +#include /* Note about magic numbers: * If you have an idea how to better solve this, tell me. Currently I'd be diff --git a/tools/playground/digger.cpp b/tools/playground/digger.cpp index 16a90b682..86a9b84b2 100644 --- a/tools/playground/digger.cpp +++ b/tools/playground/digger.cpp @@ -13,7 +13,7 @@ using namespace std; #include -#include +#include #include // counts the occurances of a certain element in a vector diff --git a/tools/playground/digger2.cpp b/tools/playground/digger2.cpp index 80f202aa5..ea34b8c2c 100644 --- a/tools/playground/digger2.cpp +++ b/tools/playground/digger2.cpp @@ -22,7 +22,7 @@ using namespace std; #include -#include +#include #define BLOCK_SIZE 16 diff --git a/tools/playground/digpattern.cpp b/tools/playground/digpattern.cpp index f49df96c6..90d960ba1 100644 --- a/tools/playground/digpattern.cpp +++ b/tools/playground/digpattern.cpp @@ -9,7 +9,7 @@ using namespace std; #include -#include +#include using namespace MapExtras; //#include diff --git a/tools/playground/drawtile.cpp b/tools/playground/drawtile.cpp index 8610d7f0c..72f2beb0f 100644 --- a/tools/playground/drawtile.cpp +++ b/tools/playground/drawtile.cpp @@ -11,7 +11,7 @@ using namespace std; #include -#include +#include //Avoid including Windows.h because it causes name clashes extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long milliseconds); diff --git a/tools/playground/hellhole.cpp b/tools/playground/hellhole.cpp index ac7781a7c..a38d14cbf 100644 --- a/tools/playground/hellhole.cpp +++ b/tools/playground/hellhole.cpp @@ -16,8 +16,8 @@ using namespace std; #include -#include -#include +#include +#include using namespace DFHack; diff --git a/tools/playground/itemdesignator.cpp b/tools/playground/itemdesignator.cpp index a1211c013..63b41eb72 100644 --- a/tools/playground/itemdesignator.cpp +++ b/tools/playground/itemdesignator.cpp @@ -8,7 +8,7 @@ using namespace std; #include -#include +#include using namespace DFHack; int main () diff --git a/tools/playground/printtiletypes.cpp b/tools/playground/printtiletypes.cpp index 48fb35a44..6d37e0a1b 100644 --- a/tools/playground/printtiletypes.cpp +++ b/tools/playground/printtiletypes.cpp @@ -11,7 +11,7 @@ using namespace std; #include -#include +#include using namespace DFHack; diff --git a/tools/playground/renamer.cpp b/tools/playground/renamer.cpp index 8b3be7eb8..e82fd691e 100644 --- a/tools/playground/renamer.cpp +++ b/tools/playground/renamer.cpp @@ -8,9 +8,9 @@ using namespace std; #define DFHACK_WANT_MISCUTILS #include -#include -#include -#include +#include +#include +#include vector< vector > englishWords; vector< vector > foreignWords; diff --git a/tools/playground/veinswap.cpp b/tools/playground/veinswap.cpp index 47b83bb82..668386100 100644 --- a/tools/playground/veinswap.cpp +++ b/tools/playground/veinswap.cpp @@ -9,8 +9,8 @@ using namespace std; #include #include -#include -#include +#include +#include //Globals diff --git a/tools/supported/dfstatus.cpp b/tools/supported/dfstatus.cpp index 0ae2b3447..91c6f6589 100644 --- a/tools/supported/dfstatus.cpp +++ b/tools/supported/dfstatus.cpp @@ -24,8 +24,8 @@ #include using namespace std; #include -#include -#include +#include +#include WINDOW *create_newwin(int height, int width, int starty, int startx); diff --git a/tools/supported/lair.cpp b/tools/supported/lair.cpp index a0427f7c2..7bf3ddc28 100644 --- a/tools/supported/lair.cpp +++ b/tools/supported/lair.cpp @@ -5,7 +5,7 @@ #include using namespace std; #include -#include +#include int main (void) { diff --git a/tools/supported/position.cpp b/tools/supported/position.cpp index ca90b2532..1bf6cf098 100644 --- a/tools/supported/position.cpp +++ b/tools/supported/position.cpp @@ -7,7 +7,7 @@ using namespace std; #include -#include +#include std::ostream &operator<<(std::ostream &stream, DFHack::t_gamemodes funzies) { const char * gm[]=