diff --git a/changelog.txt b/changelog.txt index a1bdf3bc6e..38c1e26c9c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -30,6 +30,7 @@ that repo. - `digfort`: documented that removing ramps, cutting trees, and gathering plants are indeed supported - `exportlegends`: changed some flags to be represented by self-closing tags instead of true/false strings (e.g. ````) - note that this may require changes to other XML-parsing utilities - `exportlegends`: changed some enum values from numbers to their string representations +- `exportlegends`: added ability to save all files to a subfolder, named after the region folder and date by default - `gui/advfort`: added support for specifying the entity used to determine available resources - `gui/gm-editor`: added support for automatically following ref-targets when pressing the ``i`` key - `modtools/moddable-gods`: added support for ``neuter`` gender diff --git a/exportlegends.lua b/exportlegends.lua index 8403d6e03f..4ab088537b 100644 --- a/exportlegends.lua +++ b/exportlegends.lua @@ -10,7 +10,11 @@ The 'info' option exports more data than is possible in vanilla, to a :file:`region-date-legends_plus.xml` file developed to extend :forums:`World Viewer <128932>` and other legends utilities. -Options: +Usage:: + + exportlegends OPTION [FOLDER_NAME] + +Valid values for ``OPTION`` are: :info: Exports the world/gen info, the legends XML, and a custom XML with more information :custom: Exports a custom XML with more information @@ -18,15 +22,41 @@ Options: :maps: Exports all seventeen detailed maps :all: Equivalent to calling all of the above, in that order +``FOLDER_NAME``, if specified, is the name of the folder where all the files +will be saved. This defaults to the ``regionX-YYYYY-MM-DD`` format. A path is +also allowed, although everything but the last folder has to exist. To export +to the top-level DF folder, pass ``.`` for this argument. + +Examples: + +* Export all information to the ``regionX-YYYYY-MM-DD`` folder:: + + exportlegends all + +* Export all information to the ``region6`` folder:: + + exportlegends all region6 + +* Export just the files included in ``info`` (above) to the ``regionX-YYYYY-MM-DD`` folder:: + + exportlegends info + +* Export just the custom XML file to the DF folder (no subfolder):: + + exportlegends custom . + ]====] --luacheck-flags: strictsubtype +-- General note: If you are looking for main function look at the buttom of this script file. + local gui = require 'gui' local script = require 'gui.script' local args = {...} local vs = dfhack.gui.getCurViewscreen() +-- List of all the detailed maps local MAPS = { "Standard biome+site map", "Elevations including lake and ocean floors", @@ -47,6 +77,31 @@ local MAPS = { "Diplomacy", } +-- Get that date of the world as a string +-- Format: "YYYYY-MM-DD" +function get_world_date_str() + local month = dfhack.world.ReadCurrentMonth() + 1 --days and months are 1-indexed + local day = dfhack.world.ReadCurrentDay() + local year_str = string.format('%0'..math.max(5, string.len(''..df.global.cur_year))..'d', df.global.cur_year) + local date_str = year_str..string.format('-%02d-%02d', month, day) + return date_str +end + +-- Go back to root folder so dfhack does not break, returns true if successfully +function move_back_to_main_folder() + return dfhack.filesystem.chdir(dfhack.getDFPath()) +end + +-- Set default folder name +local folder_name = df.global.world.cur_savegame.save_dir.."-"..get_world_date_str() +-- Go to save folder, returns true if successfully +function move_to_save_folder() + if move_back_to_main_folder() then + return dfhack.filesystem.chdir(folder_name) + end + return false +end + function getItemSubTypeName(itemType, subType) if (dfhack.items.getSubtypeCount(itemType)) <= 0 then return tostring(-1) @@ -122,17 +177,20 @@ function printifvalue (file, indentation, tag, value) end end ---create an extra legends xml with extra data, by Mason11987 for World Viewer +-- Export additional legends data, legends_plus.xml function export_more_legends_xml() - local month = dfhack.world.ReadCurrentMonth() + 1 --days and months are 1-indexed - local day = dfhack.world.ReadCurrentDay() - local year_str = string.format('%0'..math.max(5, string.len(''..df.global.cur_year))..'d', df.global.cur_year) - local date_str = year_str..string.format('-%02d-%02d', month, day) local problem_elements = {} - local filename = df.global.world.cur_savegame.save_dir.."-"..date_str.."-legends_plus.xml" + -- Move into the save folder + if not move_to_save_folder() then + qerror('Could not move into the save folder.') + end + local filename = df.global.world.cur_savegame.save_dir.."-"..get_world_date_str().."-legends_plus.xml" local file = io.open(filename, 'w') - if not file then qerror("could not open file: " .. filename) end + move_back_to_main_folder() + if not file then + qerror("could not open file: " .. filename) + end file:write("\n") file:write("\n") @@ -1003,45 +1061,87 @@ function export_more_legends_xml() end end --- export information and XML ('p, x') +-- Export world information and legends.xml (keys: 'p and x') function export_legends_info() + -- Move into the save folder + if not move_to_save_folder() then + qerror('Could not move into the save folder.') + end print(' Exporting: World map/gen info') gui.simulateInput(vs, 'LEGENDS_EXPORT_MAP') print(' Exporting: Legends xml') gui.simulateInput(vs, 'LEGENDS_EXPORT_XML') + move_back_to_main_folder() -- Move back out of the save folder print(" Exporting: Extra legends_plus xml") export_more_legends_xml() end +-- Export all the detailed maps like biome and elevation maps. (key: 'd') function export_detailed_maps() - script.start(function() - for i = 1, #MAPS do - local vs = dfhack.gui.getViewscreenByType(df.viewscreen_export_graphical_mapst, 0) - if not vs then - local legends_vs = dfhack.gui.getViewscreenByType(df.viewscreen_legendsst, 0) - or qerror("Could not find legends screen") - gui.simulateInput(legends_vs, 'LEGENDS_EXPORT_DETAILED_MAP') - end + script.start( + function() + -- When script is finished run `move_back_to_main_folder()` + dfhack.with_finalize( + -- Function when script is finished + function() + -- This makes sure it will always go back to the main folder. + -- Even if an error occurs + move_back_to_main_folder() + -- Make sure this is always printed even when error occurs. + print(" Done exporting.") + end, + -- Run script + function() + -- Loop over all the detailed maps and export them. + for i = 1, #MAPS do + -- Select the detailed map section + local vs = dfhack.gui.getViewscreenByType(df.viewscreen_export_graphical_mapst, 0) + if not vs then + local legends_vs = dfhack.gui.getViewscreenByType(df.viewscreen_legendsst, 0) + if not legends_vs then + qerror("Could not find legends screen") + end + + gui.simulateInput(legends_vs, 'LEGENDS_EXPORT_DETAILED_MAP') + end - vs = dfhack.gui.getViewscreenByType(df.viewscreen_export_graphical_mapst, 0) - or qerror("Could not find map export screen") - vs.sel_type = i - 1 - print(' Exporting map: ' .. MAPS[i]) - gui.simulateInput(vs, 'SELECT') - while dfhack.gui.getCurViewscreen() == vs do - script.sleep(10, 'frames') + vs = dfhack.gui.getViewscreenByType(df.viewscreen_export_graphical_mapst, 0) + if not vs then + qerror("Could not find map export screen") + end + + vs.sel_type = i - 1 + -- Move into the save folder + if not move_to_save_folder() then + qerror('Could not move into the save folder.') + end + print(' Exporting map ' ..i.. '/' ..#MAPS..': '.. MAPS[i]) + -- Select the map and start exporting + gui.simulateInput(vs, 'SELECT') + -- Wait for the map to finish exporting + while dfhack.gui.getCurViewscreen() == vs do + script.sleep(10, 'frames') + end + -- Move back out of the save folder + move_back_to_main_folder() + end end + ) end - end) + ) end --- export site maps +-- Export the maps of all the sites (cities, towns,...) (key: 'sites', 'p') function export_site_maps() local vs = dfhack.gui.getCurViewscreen() if ((dfhack.gui.getCurFocus() ~= "legends" ) and (not table_contains(vs, "main_cursor"))) then -- Using open-legends vs = vs.parent --luacheck: retype end if df.viewscreen_legendsst:is_instance(vs) then + -- Move into the save folder + if not move_to_save_folder() then + qerror('Could not move into the save folder.') + end print(' Exporting: All possible site maps') vs.main_cursor = 1 gui.simulateInput(vs, 'SELECT') @@ -1050,12 +1150,40 @@ function export_site_maps() gui.simulateInput(vs, 'STANDARDSCROLL_DOWN') end gui.simulateInput(vs, 'LEAVESCREEN') + move_back_to_main_folder() -- Move back out of the save folder else qerror('this command can only be used in Legends mode') end end --- main() +-- Check if a folder with this name could be created or already exists +function create_folder(folder_name) + if folder_name == "-00000-01-01" then + qerror('"'..folder_name..'" is the default foldername, this folder will not be created as you are probably not in the legends screen.') + end + -- check if it is a file, not a folder + if dfhack.filesystem.isfile(folder_name) then + qerror(folder_name..' is a file, not a folder') + end + if dfhack.filesystem.exists(folder_name) then + return true + else + return dfhack.filesystem.mkdir(folder_name) + end +end + +-- If folder_name is given as a argument use that +if #args >= 2 then + folder_name = args[2] +end +-- Create folder to export all files into, if possible. +if not create_folder(folder_name) then + -- no valid folder name or could not create folder + qerror('The foldername '..folder_name..' could not be created') +end +print("Writing all files in: "..folder_name) + +-- Main: Check if on legends screen and trigger the correct export. if dfhack.gui.getCurFocus() == "legends" or dfhack.gui.getCurFocus() == "dfhack/lua/legends" then -- either native legends mode, or using the open-legends.lua script if args[1] == "all" then @@ -1078,3 +1206,5 @@ elseif args[1] == "maps" and dfhack.gui.getCurFocus() == "export_graphical_map" else qerror('exportlegends must be run from the main legends view') end + +print("Exported files can be found in the \""..folder_name.."\" folder.")