modsvaskr 0.2.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29dad9a5413e803a1980b6d0d9aa4f71e66c8c233c0398b30eacb03c3a35d563
4
- data.tar.gz: 0b9fb7f2efd87394746327fd79783717cb0871eb83f5447a395b411e8c8adfd9
3
+ metadata.gz: 3b3bda4db035df3b3289829342c1a70a47be0191de49f35e72c2e25f6e8aaada
4
+ data.tar.gz: bed82e160e1310241b870e8545a08913b81caf210f5388121afd1fc465ad01c1
5
5
  SHA512:
6
- metadata.gz: 55cc0a939035ec8dbebb92f4d2e96f168faeb81b486370122951c795933088214ec90585fb6fe2a62d2cb6be55a86a1ab4d7062c43a5a7056abe4292ecbb82d5
7
- data.tar.gz: aeb1f38ccfa4cf5f1e0362b350ad8f219e6ac92b2a3c5bf1027e4a03a3f45242d5a00fc02fc3425d420e8e72669e3c3135f415ad4b926692ef45581bb494af24
6
+ metadata.gz: 35e165ef5571a0a54c47393aea22ec848e42be1d6d27940f8a23e24fba00b35da00677049b474d1370ba7b4fadf4de9088089ec8cb582ceb8c2c1de489490cf5
7
+ data.tar.gz: '08ade008d6263b3bef50df32efeda147e409e2f9c7644177ccaa03c112a9aafdb4f54e3102eb98b56814e6fbe42210d72df176d7e4feb0cb2341f3117faf72aa'
data/bin/modsvaskr CHANGED
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
- # require 'mod_organizer'
2
+ require 'English'
3
3
  require 'modsvaskr/config'
4
4
  require 'modsvaskr/ui'
5
5
 
6
6
  begin
7
7
  Modsvaskr::Ui.new(config: Modsvaskr::Config.new('./modsvaskr.yaml')).run
8
8
  rescue
9
+ puts "An exception has occurred: #{$ERROR_INFO}\n#{$ERROR_INFO.backtrace.join("\n")}"
9
10
  puts 'Press Enter to exit.'
10
11
  $stdin.gets
11
12
  end
@@ -1,3 +1,4 @@
1
+ require 'mod_organizer'
1
2
  require 'yaml'
2
3
  require 'modsvaskr/game'
3
4
  require 'modsvaskr/xedit'
@@ -73,6 +74,19 @@ module Modsvaskr
73
74
  @config['no_prompt'] || false
74
75
  end
75
76
 
77
+ # Return the ModOrganizer instance, if configured.
78
+ #
79
+ # Result::
80
+ # * ModOrganizer or nil: The ModOrganizer instance, or nil if none
81
+ def mod_organizer
82
+ return nil unless @config['mod_organizer']
83
+
84
+ ModOrganizer.new(
85
+ @config['mod_organizer']['installation_dir'],
86
+ instance_name: @config['mod_organizer']['instance_name']
87
+ )
88
+ end
89
+
76
90
  end
77
91
 
78
92
  end
@@ -203,6 +203,29 @@ module Modsvaskr
203
203
  [load_order[form_id / 16_777_216], form_id % 16_777_216]
204
204
  end
205
205
 
206
+ # Clean a list plugins.
207
+ # Make sure they are cleaned in the right order, according to the load order.
208
+ # Put the cleaned plugins in a cleaned_plugins subfolder.
209
+ # Make sure that subsequent plugins to be cleaned are cleaned with the previously cleaned plugins in the list.
210
+ #
211
+ # Parameters::
212
+ # * *plugins* (Array<String>): List of plugins to be cleaned
213
+ def clean_plugins(plugins)
214
+ return if plugins.empty?
215
+
216
+ esp = (load_order & plugins).first
217
+ log "Clean #{esp}"
218
+ FileUtils.cp "#{path}/Data/#{esp}", "#{path}/Data/#{esp}.backup"
219
+ begin
220
+ xedit.quick_auto_clean(esp)
221
+ clean_plugins(plugins - [esp])
222
+ FileUtils.mkdir_p "#{path}/Data/cleaned_plugins"
223
+ FileUtils.mv "#{path}/Data/#{esp}", "#{path}/Data/cleaned_plugins/#{esp}"
224
+ ensure
225
+ FileUtils.mv "#{path}/Data/#{esp}.backup", "#{path}/Data/#{esp}"
226
+ end
227
+ end
228
+
206
229
  end
207
230
 
208
231
  end
data/lib/modsvaskr/ui.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'English'
2
2
  require 'curses_menu'
3
+ require 'launchy'
3
4
  require 'modsvaskr/logger'
4
5
  require 'modsvaskr/tests_runner'
5
6
  require 'modsvaskr/run_cmd'
@@ -20,8 +21,12 @@ module Modsvaskr
20
21
  def initialize(config:)
21
22
  log "Launch Modsvaskr UI v#{Modsvaskr::VERSION} - Logs in #{Logger.log_file}"
22
23
  @config = config
24
+ @mod_organizer = @config.mod_organizer
23
25
  end
24
26
 
27
+ # Time that should be before any file time of mods (used for sorting)
28
+ TIME_BEGIN = Time.parse('2000-01-01')
29
+
25
30
  # Run the UI
26
31
  def run
27
32
  last_modsvaskr_version = nil
@@ -44,7 +49,13 @@ module Modsvaskr
44
49
  end
45
50
  end
46
51
  CursesMenu.new(
47
- "Modsvaskr v#{Modsvaskr::VERSION} - Stronghold of Mods#{!last_modsvaskr_version.nil? && last_modsvaskr_version != Modsvaskr::VERSION ? " - !!! New version available: #{last_modsvaskr_version}" : ''}",
52
+ "Modsvaskr v#{Modsvaskr::VERSION} - Stronghold of Mods#{
53
+ if !last_modsvaskr_version.nil? && last_modsvaskr_version != Modsvaskr::VERSION
54
+ " - !!! New version available: #{last_modsvaskr_version}"
55
+ else
56
+ ''
57
+ end
58
+ }",
48
59
  key_presses:
49
60
  ) do |main_menu|
50
61
  @config.games.each do |game|
@@ -53,6 +64,27 @@ module Modsvaskr
53
64
  "Modsvaskr v#{Modsvaskr::VERSION} - Stronghold of Mods > #{game.name}",
54
65
  key_presses:
55
66
  ) do |game_menu|
67
+ game_menu.item 'Plugins' do
68
+ selected_esps = {}
69
+ CursesMenu.new(
70
+ "Modsvaskr v#{Modsvaskr::VERSION} - Stronghold of Mods > #{game.name} > Plugins",
71
+ key_presses:
72
+ ) do |plugins_menu|
73
+ game.load_order.each.with_index do |esp, idx|
74
+ plugins_menu.item "[#{selected_esps.key?(esp) ? '*' : ' '}] #{idx} - #{esp}" do
75
+ if selected_esps.key?(esp)
76
+ selected_esps.delete(esp)
77
+ else
78
+ selected_esps[esp] = nil
79
+ end
80
+ :menu_refresh
81
+ end
82
+ end
83
+ plugins_menu.item "Clean #{selected_esps.size} selected plugins" do
84
+ game.clean_plugins(selected_esps.keys)
85
+ end
86
+ end
87
+ end
56
88
  game_menu.item 'Testing' do
57
89
  # Read tests info
58
90
  tests_runner = TestsRunner.new(@config, game)
@@ -176,6 +208,102 @@ module Modsvaskr
176
208
  end
177
209
  end
178
210
  end
211
+ unless @mod_organizer.nil?
212
+ main_menu.item 'Mods Organizer' do
213
+ CursesMenu.new(
214
+ 'Modsvaskr - Stronghold of Mods > Mods Organizer',
215
+ key_presses:
216
+ ) do |mo_menu|
217
+ # Show status
218
+ mo_menu.item 'Run Mod Organizer' do
219
+ @mod_organizer.run
220
+ end
221
+ mo_menu.item "#{@mod_organizer.mod_names.size} mods (#{@mod_organizer.mod_names.select { |mod_name| @mod_organizer.mod(name: mod_name).enabled? }.size} enabled)" do
222
+ CursesMenu.new(
223
+ 'Modsvaskr - Stronghold of Mods > Mods Organizer > Mods',
224
+ key_presses:
225
+ ) do |mods_menu|
226
+ mod_names = @mod_organizer.mods_list
227
+ idx_size = (mod_names.size - 1).to_s.size
228
+ mod_names.each.with_index do |mod_name, idx|
229
+ mod = @mod_organizer.mod(name: mod_name)
230
+ # need_update = false
231
+ mods_menu.item(
232
+ proc do
233
+ sections = {
234
+ enabled_cell: {
235
+ text: mod.enabled? ? 'X' : ' ',
236
+ begin_with: '[',
237
+ end_with: ']',
238
+ fixed_size: 3
239
+ },
240
+ idx_cell: {
241
+ text: idx.to_s,
242
+ fixed_size: idx_size
243
+ },
244
+ name_cell: {
245
+ text: mod_name,
246
+ color_pair: CursesMenu::COLORS_GREEN,
247
+ fixed_size: 64
248
+ },
249
+ categories_cell: {
250
+ text: mod.categories.map { |category| "[#{category}]" }.join(' '),
251
+ fixed_size: 16
252
+ },
253
+ esps_cell: {
254
+ text: "#{mod.plugins.size} plugins",
255
+ fixed_size: 10
256
+ }
257
+ }
258
+ mod.sources.sort_by { |source| source.download.nil? ? TIME_BEGIN : source.download.downloaded_date }.each.with_index do |source, src_idx|
259
+ source_name = src_idx.zero? ? '' : '+ '
260
+ source_name <<
261
+ case source.type
262
+ when :nexus_mods
263
+ "Nexus Mod #{source.nexus_mod_id}/" +
264
+ if source.download&.nexus_file_name
265
+ source.download&.nexus_file_name
266
+ elsif source.file_name
267
+ source.file_name
268
+ else
269
+ '<Unknown file>'
270
+ end
271
+ when :unknown
272
+ source.file_name || '<Unknown source>'
273
+ else
274
+ raise "Unknown source type: #{source.type} for #{mod.name}"
275
+ end
276
+ sections["source_#{src_idx}".to_sym] = {
277
+ text: source_name,
278
+ color_pair: CursesMenu::COLORS_WHITE
279
+ }
280
+ end
281
+ CursesMenu::CursesRow.new(sections)
282
+ end,
283
+ actions: proc do
284
+ actions = {}
285
+ # TODO: Use downloads' URL instead of mod's URL as it is very often more accurate
286
+ if mod.url
287
+ actions['v'] = {
288
+ name: 'Visit',
289
+ execute: proc { Launchy.open(mod.url) }
290
+ }
291
+ end
292
+ actions
293
+ end
294
+ )
295
+ end
296
+ mods_menu.item 'Back' do
297
+ :menu_exit
298
+ end
299
+ end
300
+ end
301
+ mo_menu.item 'Back' do
302
+ :menu_exit
303
+ end
304
+ end
305
+ end
306
+ end
179
307
  main_menu.item 'See logs' do
180
308
  CursesMenu.new(
181
309
  'Modsvaskr - Stronghold of Mods > Logs',
@@ -1,5 +1,5 @@
1
1
  module Modsvaskr
2
2
 
3
- VERSION = '0.2.1'
3
+ VERSION = '1.1.0'
4
4
 
5
5
  end
@@ -1,5 +1,6 @@
1
1
  require 'csv'
2
2
  require 'modsvaskr/encoding'
3
+ require 'modsvaskr/logger'
3
4
  require 'modsvaskr/run_cmd'
4
5
 
5
6
  module Modsvaskr
@@ -7,6 +8,7 @@ module Modsvaskr
7
8
  # Helper to use an instance of xEdit
8
9
  class Xedit
9
10
 
11
+ include Logger
10
12
  include RunCmd
11
13
 
12
14
  # String: Installation path
@@ -49,6 +51,24 @@ module Modsvaskr
49
51
  @runs[script] = nil
50
52
  end
51
53
 
54
+ # Run a QuickAutoClean of a given plugin
55
+ #
56
+ # Parameters::
57
+ # * *esp* (String): Plugin to autoclean
58
+ def quick_auto_clean(esp)
59
+ # TODO: Find a way to select the right esp automatically
60
+ out "Please double-click on the following plugin: #{esp}"
61
+ run_cmd(
62
+ {
63
+ dir: @install_path,
64
+ exe: 'SSEEdit.exe'
65
+ },
66
+ args: %w[
67
+ -quickautoclean
68
+ ]
69
+ )
70
+ end
71
+
52
72
  # Parse a CSV that has been dumped by a previous run of xEdit
53
73
  #
54
74
  # Parameters::
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: modsvaskr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Muriel Salvan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-31 00:00:00.000000000 Z
11
+ date: 2023-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses_menu
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.0'
19
+ version: '0.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.0'
26
+ version: '0.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: elder_scrolls_plugin
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,20 +38,48 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: launchy
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.5'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mod_organizer
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: nokogiri
43
71
  requirement: !ruby/object:Gem::Requirement
44
72
  requirements:
45
73
  - - "~>"
46
74
  - !ruby/object:Gem::Version
47
- version: '1.13'
75
+ version: '1.14'
48
76
  type: :runtime
49
77
  prerelease: false
50
78
  version_requirements: !ruby/object:Gem::Requirement
51
79
  requirements:
52
80
  - - "~>"
53
81
  - !ruby/object:Gem::Version
54
- version: '1.13'
82
+ version: '1.14'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: rspec
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -100,28 +128,28 @@ dependencies:
100
128
  requirements:
101
129
  - - "~>"
102
130
  - !ruby/object:Gem::Version
103
- version: '1.41'
131
+ version: '1.47'
104
132
  type: :development
105
133
  prerelease: false
106
134
  version_requirements: !ruby/object:Gem::Requirement
107
135
  requirements:
108
136
  - - "~>"
109
137
  - !ruby/object:Gem::Version
110
- version: '1.41'
138
+ version: '1.47'
111
139
  - !ruby/object:Gem::Dependency
112
140
  name: rubocop-rspec
113
141
  requirement: !ruby/object:Gem::Requirement
114
142
  requirements:
115
143
  - - "~>"
116
144
  - !ruby/object:Gem::Version
117
- version: '2.16'
145
+ version: '2.18'
118
146
  type: :development
119
147
  prerelease: false
120
148
  version_requirements: !ruby/object:Gem::Requirement
121
149
  requirements:
122
150
  - - "~>"
123
151
  - !ruby/object:Gem::Version
124
- version: '2.16'
152
+ version: '2.18'
125
153
  description: Command-line UI handling a full Mods' ecosystem for Bethesda's games.
126
154
  email:
127
155
  - muriel@x-aeon.com