@@ -8,9 +8,10 @@ local dialogs = require('gui.dialogs')
88local json = require (' json' )
99local utils = require (' utils' )
1010
11+ local scriptmanager = require (' script-manager' )
12+
1113local presets_file = json .open (" dfhack-config/mod-manager.json" )
1214local GLOBAL_KEY = ' mod-manager'
13- local INSTALLED_MODS_PATH = ' data/installed_mods/'
1415
1516-- get_newregion_viewscreen and get_modlist_fields are declared as global functions
1617-- so external tools can call them to get the DF mod list
@@ -404,99 +405,86 @@ end
404405
405406ModlistMenu = defclass (ModlistMenu , widgets .Window )
406407ModlistMenu .ATTRS {
407- view_id = " modlist_menu" ,
408408 frame_title = " Active Modlist" ,
409- frame_style = gui .WINDOW_FRAME ,
410409
411410 resize_min = { w = 30 , h = 15 },
412- frame = { w = 40 , t = 10 , b = 15 },
411+ frame = { w = 40 , h = 20 },
413412
414413 resizable = true ,
415- autoarrange_subviews = false ,
416414}
417415
418- local function get_mod_id_and_version (path )
419- local idfile = path .. ' /info.txt'
420- local ok , lines = pcall (io.lines , idfile )
421- if not ok then return end
422- local id , version
423- for line in lines do
424- if not id then
425- _ ,_ ,id = line :find (' ^%[ID:([^%]]+)%]' )
426- end
427- if not version then
428- -- note this doesn't include the closing brace since some people put
429- -- non-number characters in here, and DF only reads the leading digits
430- -- as the numeric version
431- _ ,_ ,version = line :find (' ^%[NUMERIC_VERSION:(%d+)' )
432- end
433- -- note that we do *not* want to break out of this loop early since
434- -- lines has to hit EOF to close the file
435- end
436- return id , version
437- end
438-
439- local function add_mod_paths (mod_paths , id , base_path , subdir )
440- local sep = base_path :endswith (' /' ) and ' ' or ' /'
441- local path = (' %s%s%s' ):format (base_path , sep , subdir )
442- if dfhack .filesystem .isdir (path ) then
443- table.insert (mod_paths , {id = id , path = path })
444- end
445- end
446-
447- local function getWorldModlist ()
416+ local function getWorldModlist (detailed , include_vanilla )
448417 -- ordered map of mod id -> {handled=bool, versions=map of version -> path}
449418 local mods = utils .OrderedTable ()
450419 local mod_paths = {}
451420
452421 -- if a world is loaded, process active mods first, and lock to active version
453422 if dfhack .isWorldLoaded () then
454- for _ ,path in ipairs (df .global .world .object_loader .object_load_order_src_dir ) do
455- path = tostring (path .value )
456- -- skip vanilla "mods"
457- if not path :startswith (INSTALLED_MODS_PATH ) then goto continue end
458- local id = get_mod_id_and_version (path )
459- if not id then goto continue end
460- mods [id ] = {handled = true }
461- add_mod_paths (mod_paths , id , path , ' .' )
462- :: continue::
463- end
423+ scriptmanager .getAllModsInfo (include_vanilla , mods , mod_paths )
464424 local modlist = {}
465425 for _ ,mod in ipairs (mod_paths ) do
466- table.insert (modlist ,mod .id )
426+ if detailed then
427+ local url
428+ if mods [mod .id ].steam_id then
429+ url = ' : https://steamcommunity.com/sharedfiles/filedetails/?id=' .. mods [mod .id ].steam_id
430+ end
431+ table.insert (modlist ,(' %s %s (%s)%s' ):format (mods [mod .id ].name or mod .id , mods [mod .id ].version or ' ' , mod .id , url or ' ' ))
432+ else
433+ table.insert (modlist ,mods [mod .id ].name or mod .id )
434+ end
467435 end
468436 return modlist
469437 end
470438 qerror (' No world is loaded' )
471439end
472440
473441function ModlistMenu :init ()
474- local modlist = widgets .List {
475- view_id = ' modlist' ,
476- frame = {t = 3 },
477- choices = getWorldModlist ()
478- }
442+ self .include_vanilla = self .include_vanilla or false
479443 self :addviews {
480444 widgets .Label {
481445 frame = { l = 0 , t = 0 },
482446 text = {' Active mods:' },
483447 },
484448 widgets .HotkeyLabel {
485- view_id = ' copy ' ,
449+ view_id = ' copy_names ' ,
486450 frame = {t = 1 , r = 1 },
487- label = ' Copy modlist to clipboard' ,
451+ label = ' Copy mod names to clipboard' ,
488452 text_pen = COLOR_YELLOW ,
489453 auto_width = true ,
490454 on_activate = function ()
491- local mods = ' '
492- for _ ,mod in ipairs (getWorldModlist ()) do
493- mods = (mods == ' ' and mod ) or (mods .. ' , ' .. mod )
494- end
455+ local mods = table.concat (getWorldModlist (false , self .include_vanilla ), ' , ' )
495456 dfhack .internal .setClipboardTextCp437 (mods )
496457 end ,
497- enabled = function () return # modlist :getChoices () > 0 end ,
458+ enabled = function () return # self . subviews . modlist :getChoices () > 0 end ,
498459 },
499- modlist
460+ widgets .HotkeyLabel {
461+ view_id = ' copy_list' ,
462+ frame = {t = 2 , r = 1 },
463+ label = ' Copy list to clipboard' ,
464+ text_pen = COLOR_YELLOW ,
465+ auto_width = true ,
466+ on_activate = function ()
467+ local mods = table.concat (getWorldModlist (true , self .include_vanilla ), NEWLINE )
468+ dfhack .internal .setClipboardTextCp437Multiline (mods )
469+ end ,
470+ enabled = function () return # self .subviews .modlist :getChoices () > 0 end ,
471+ },
472+ widgets .List {
473+ view_id = ' modlist' ,
474+ frame = {t = 4 ,b = 2 },
475+ choices = getWorldModlist (true ,self .include_vanilla )
476+ },
477+ widgets .HotkeyLabel {
478+ view_id = ' include_vanilla' ,
479+ frame = {b = 0 },
480+ key = ' CUSTOM_V' ,
481+ label = ' Include Vanilla Mods: ' .. ((self .include_vanilla and ' Yes' ) or ' No' ),
482+ on_activate = function ()
483+ self .include_vanilla = not self .include_vanilla
484+ self .subviews .include_vanilla :setLabel (' Include Vanilla Mods: ' .. ((self .include_vanilla and ' Yes' ) or ' No' ))
485+ self .subviews .modlist :setChoices (getWorldModlist (true ,self .include_vanilla ))
486+ end
487+ }
500488 }
501489end
502490
0 commit comments