mmi 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac664a5f071c4eeb437b6e1f501130373baa722e3e97277bd627de91db6340b0
4
- data.tar.gz: ec0937a098b99dd02302ee3c0256ad1d6e3e3e6f14e7ef72e76dfb7924e52beb
3
+ metadata.gz: 84c944c267d13afff856179fd1a089d1ff6213a865e256f6c2678ed7f24e09ee
4
+ data.tar.gz: 3da84073781c7e7a185e3e9f03fba104649c1b695b25bc4aa74e90b6cdc8e6da
5
5
  SHA512:
6
- metadata.gz: 7eac5b99470ab80d174bdac020fd0f2872907d2bc2fc117ac102806d5dc6a2a58e410b6f96811376a0d8c32d8970c155b119ecf1d6620436211769b011676b4b
7
- data.tar.gz: 600c32a227d7458a3f034e00c40347fd35bf11a4699f76ebd35521d9ee5a366e55740b70cfe8122ab96b468c9b985131cfc7218468231ed0c5c9edb8a04ce7ad
6
+ metadata.gz: 1bf673321a3ccdef9c310af18e841b0a74278154ee83f5cc37c777a56ba1a370edf77b9f2d589f62b153ed0f12884f527e0ce6ba7045711be17fcaf77e1874ea
7
+ data.tar.gz: 3fdd21c1b7f0e002e12d4851f7369697fb2d5b61685ef26b44a54643ef48ffb87b2a7297c639def93c5e30972da147ecca10918235d2d63bb625768dc04ef23e
data/README.adoc CHANGED
@@ -115,15 +115,11 @@ There, within the same minor version, backwards compatibility can be expected, b
115
115
 
116
116
  == Contributing
117
117
 
118
- Contributions are very welcome, as well as feature/bug requests.
119
-
120
- In case you want to implement a feature, it would be best to create an issue beforehand so that we can discuss it.
121
- This reduces the chance of a pull request being rejected.
118
+ Contributions are very welcome, including feature/bug requests.
119
+ Before implementing a (larger) feature, consider opening a ticket to discuss the implementation or feature.
122
120
 
123
121
  If you intend to create a pull request, please choose a branch name describing its changes (i.e. not some generic term like `master` or `fix`, but e.g. `fix_typo` or `add_interactive_update_command`).
124
122
 
125
- Please be aware that I have a very specific code style and am interested in keeping it in this repository.
126
- Some basic rules are specified in the `.editorconfig` file, which your editor should support.
127
- Additionally, Rubocop has been configured using the existing code and every commit should pass Rubocop’s inspection.
128
- There most likely are a lot of Rubocop rules that are currently not triggered and therefore not configured.
129
- In such a case, either try to derive a style from existing code or feel free to ask.
123
+ Please try to follow the existing coding style as close as possible.
124
+ Some basic rules are specified in the `.editorconfig` file, and Rubocop is also available to help.
125
+ Every commit should pass Rubocop’s inspection.
data/exe/mmi CHANGED
@@ -12,7 +12,7 @@ def processor(file)
12
12
  content = Psych.load_file(file)
13
13
 
14
14
  begin
15
- Mmi::ModFileProcessor.new(content)
15
+ Mmi::ModFileProcessor.parse(content)
16
16
  rescue Mmi::ValidationError => e
17
17
  puts e
18
18
  Kernel.exit 1
data/lib/mmi/asset.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'mmi/property_attributes'
2
+ require 'mmi/source/github'
3
+ require 'mmi/source/modrinth'
4
+ require 'mmi/source/url'
5
+
6
+ module Mmi
7
+ class Asset
8
+ prepend Mmi::PropertyAttributes
9
+
10
+ property :source, type: {field: 'type', types: {'github' => Source::Github, 'modrinth' => Source::Modrinth, 'url' => Source::Url}}
11
+
12
+ def install(install_record)
13
+ source.install(install_record)
14
+ end
15
+ end
16
+ end
@@ -1,53 +1,22 @@
1
- require 'mmi/option_attributes'
2
- require 'mmi/source/github'
3
- require 'mmi/source/modrinth'
4
- require 'mmi/source/url'
1
+ require 'mmi/constants'
2
+ require 'mmi/property_attributes'
3
+ require 'mmi/asset'
4
+ require 'mmi/install_record'
5
5
 
6
6
  module Mmi
7
7
  class AssetsProcessor
8
- include OptionAttributes
8
+ prepend PropertyAttributes
9
9
 
10
- opt_accessor(:profile_dir) { Mmi.minecraft_dir }
11
- opt_accessor(:items ) { [] }
12
-
13
- attr_reader :parsed_items
14
-
15
- def initialize(options)
16
- @options = options
17
-
18
- parse!
19
- end
20
-
21
- def parse!
22
- if self.items.is_a?(Array)
23
- @parsed_items = self.items.map.with_index do |asset, index|
24
- source = asset['source']
25
-
26
- if source
27
- type = source['type']
28
-
29
- case type
30
- when 'github'
31
- Source::Github.new(source)
32
- when 'modrinth'
33
- Source::Modrinth.new(source)
34
- when 'url'
35
- Source::Url.new(source)
36
- else
37
- raise Mmi::InvalidAttributeError, %Q(Invalid "source.type" in asset #{index.inspect}: #{type.inspect})
38
- end
39
- else
40
- raise Mmi::MissingAttributeError, %Q(Missing "source" in asset #{index.inspect}.)
41
- end
42
- end
43
- else
44
- raise Mmi::InvalidAttributeError, %Q(Invalid "assets": expected Array or nothing, got #{self.items.inspect}.)
45
- end
46
- end
10
+ property :profile_dir, default: Mmi::Constants.minecraft_dir
11
+ property :items, type: Asset, default: []
47
12
 
48
13
  def install
49
- self.parsed_items.each do |asset|
50
- asset.install(self.profile_dir)
14
+ InstallRecord.new.tap do |install_record|
15
+ self.items.each do |asset|
16
+ asset.install(install_record)
17
+ end
18
+
19
+ install_record.install(self.profile_dir)
51
20
  end
52
21
  end
53
22
  end
@@ -0,0 +1,14 @@
1
+ module Mmi
2
+ module Constants
3
+ MMI_CACHE_DIR = File.join(Dir.home, '.cache', 'mmi')
4
+ MINECRAFT_DIR = File.join(Dir.home, '.minecraft')
5
+
6
+ def self.cache_dir
7
+ MMI_CACHE_DIR
8
+ end
9
+
10
+ def self.minecraft_dir
11
+ MINECRAFT_DIR
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ module Mmi
2
+ module ContentHash
3
+ class Base
4
+ def match_file?(file_path)
5
+ raise NotImplementedError
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ require 'digest'
2
+
3
+ require 'mmi/content_hash/base'
4
+
5
+ module Mmi
6
+ module ContentHash
7
+ class Sha512 < Base
8
+ attr_accessor :hex_digest
9
+
10
+ def initialize(hex_digest)
11
+ super()
12
+
13
+ self.hex_digest = hex_digest
14
+ end
15
+
16
+ def match_file?(file_path)
17
+ Digest::SHA512.hexdigest(File.read(file_path)) == self.hex_digest
18
+ end
19
+
20
+ def ==(other)
21
+ self.class == other.class && self.hex_digest == other.hex_digest
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,72 @@
1
+ require 'psych'
2
+
3
+ require 'mmi/content_hash/base'
4
+
5
+ module Mmi
6
+ class InstallRecord
7
+ RecordEntry = Struct.new(:url, :content_hash)
8
+
9
+ RECORD_FILE = '.mmi_install_record'.freeze
10
+
11
+ def initialize
12
+ @record = {}
13
+ end
14
+
15
+ def add(url, relative_path, content_hash:)
16
+ raise 'content_hash must be nil or an instance of Mmi::ContentHash::Base' unless content_hash.nil? || content_hash.is_a?(Mmi::ContentHash::Base)
17
+
18
+ @record[relative_path] = RecordEntry.new(url, content_hash)
19
+ end
20
+
21
+ def install(dir)
22
+ old_record = self.class.parse_record_file(dir) || {}
23
+
24
+ @record.each do |relative_path, entry|
25
+ target_file = File.expand_path(relative_path, dir)
26
+
27
+ if old_record[relative_path] != entry || (File.exist?(target_file) && !entry.content_hash&.match_file?(target_file))
28
+ Mmi.info "Downloading #{entry.url.inspect} into #{target_file.inspect}."
29
+
30
+ begin
31
+ Mmi::InstallUtils.download_to_file(entry.url, target_file, entry.content_hash)
32
+ rescue OpenURI::HTTPError => e
33
+ Mmi.fail! "Error when requesting asset.\n#{e.inspect}"
34
+ end
35
+ else
36
+ Mmi.info "Skipping #{entry.url.inspect} because it is already present at #{target_file.inspect}."
37
+ end
38
+
39
+ old_record.delete(relative_path)
40
+ end
41
+
42
+ old_record.each do |relative_path, _|
43
+ target_file = File.expand_path(relative_path, dir)
44
+
45
+ File.delete(target_file) if File.exist?(target_file)
46
+ end
47
+
48
+ File.write(File.expand_path(RECORD_FILE, dir), to_yaml)
49
+ end
50
+
51
+ def to_yaml
52
+ Psych.dump(@record)
53
+ end
54
+
55
+ def self.parse_record_file(dir)
56
+ record_file = File.expand_path(RECORD_FILE, dir)
57
+
58
+ if File.exist?(record_file)
59
+ parsed_record = Psych.unsafe_load_file(record_file)
60
+
61
+ unless !parsed_record.is_a?(Hash) || parsed_record.keys.any?{|k| !k.is_a?(String)} && parsed_record.values.any?{|v| !v.is_a?(Record)}
62
+ parsed_record
63
+ else
64
+ Mmi.warn("Found invalid install record at #{record_file}. The file will be ignored.")
65
+ nil
66
+ end
67
+ else
68
+ nil
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,24 @@
1
+ require 'digest'
2
+ require 'fileutils'
3
+ require 'open-uri'
4
+
5
+ require 'mmi/constants'
6
+ require 'mmi/content_hash/base'
7
+
8
+ module Mmi
9
+ module InstallUtils
10
+ class << self
11
+ def download_to_file(url, target_file, content_hash=nil)
12
+ raise 'content_hash must be nil or an instance of Mmi::ContentHash::Base' unless content_hash.nil? || content_hash.is_a?(Mmi::ContentHash::Base)
13
+
14
+ FileUtils.mkdir_p(File.dirname(target_file))
15
+
16
+ stream = URI.parse(url).open
17
+
18
+ IO.copy_stream(stream, target_file)
19
+
20
+ raise "Failed to match #{target_file} with #{content_hash.inspect}!" if content_hash && !content_hash.match_file?(target_file)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -8,12 +8,12 @@ module Mmi
8
8
  module Assets
9
9
  def update_assets
10
10
  loop do
11
- assets = processor.parsed_assets.parsed_items
11
+ assets = processor.assets.items
12
12
 
13
13
  choice = CLI::UI::Prompt.ask('Which asset do you want to change?') do |handler|
14
14
  assets.each do |asset|
15
- handler.option(asset.display_name) do
16
- asset
15
+ handler.option(asset.source.display_name) do
16
+ asset.source
17
17
  end
18
18
  end
19
19
 
@@ -27,12 +27,27 @@ module Mmi
27
27
  when :add
28
28
  add_asset
29
29
  else
30
- update_asset_version(choice)
30
+ update_asset_source_version(choice)
31
31
  end
32
32
  end
33
33
  end
34
34
 
35
35
  def add_asset
36
+ if (source = create_source)
37
+ asset = Mmi::Asset.parse({
38
+ 'source' => source.to_h,
39
+ })
40
+
41
+ self.processor.assets['items'].push(asset.to_h)
42
+ self.processor.assets.parse!
43
+ else
44
+ CLI::UI.puts('Aborting asset addition. No change will be made.')
45
+
46
+ false
47
+ end
48
+ end
49
+
50
+ def create_source
36
51
  source_type = CLI::UI::Prompt.ask('Choose a source type.') do |handler|
37
52
  %w[
38
53
  github
@@ -45,80 +60,68 @@ module Mmi
45
60
  handler.option('quit', &:to_sym)
46
61
  end
47
62
 
48
- opts, source =
63
+ source =
49
64
  case source_type
50
65
  when :quit
51
66
  return false
52
67
  when :github
53
68
  options = {
54
- 'source' => {
55
- 'type' => 'github',
56
- 'asset_id' => 0,
57
- },
69
+ 'type' => 'github',
70
+ 'asset_id' => 0,
58
71
  }
59
72
 
60
- options['source']['owner' ] = CLI::UI::Prompt.ask('Who is the owner of the source repository?').strip
61
- options['source']['repo' ] = CLI::UI::Prompt.ask('What is the name of the source repository?').strip
62
- options['source']['install_dir'] = CLI::UI::Prompt.ask('In which directory should the asset be placed?', default: 'mods').strip
63
- options['source']['filename' ] = CLI::UI::Prompt.ask('Under which filename should the asset be saved? (leave empty for release asset name)', allow_empty: true).strip.then do |filename|
73
+ options['owner' ] = CLI::UI::Prompt.ask('Who is the owner of the source repository?').strip
74
+ options['repo' ] = CLI::UI::Prompt.ask('What is the name of the source repository?').strip
75
+ options['install_dir'] = CLI::UI::Prompt.ask('In which directory should the asset be placed?', default: 'mods').strip
76
+ options['filename' ] = CLI::UI::Prompt.ask('Under which filename should the asset be saved? (leave empty for release asset name)', allow_empty: true).strip.then do |filename|
64
77
  filename == '' ? nil : filename
65
78
  end
66
79
 
67
- options['source'].compact!
80
+ options.compact!
68
81
 
69
- [options, Mmi::Source::Github.new(options['source'])]
82
+ Mmi::Source::Github.parse(options)
70
83
  when :modrinth
71
84
  options = {
72
- 'source' => {
73
- 'type' => 'modrinth',
74
- 'version' => '0',
75
- 'version_file' => '0',
76
- },
85
+ 'type' => 'modrinth',
86
+ 'version' => '0',
87
+ 'version_file' => '0',
77
88
  }
78
89
 
79
- options['source']['name' ] = CLI::UI::Prompt.ask('What is the name of the mod in the Modrinth URL?').strip
80
- options['source']['install_dir'] = CLI::UI::Prompt.ask('In which directory should the asset be placed?', default: 'mods').strip
81
- options['source']['filename' ] = CLI::UI::Prompt.ask('Under which filename should the asset be saved? (leave empty for release asset name)', allow_empty: true).strip.then do |filename|
90
+ options['name' ] = CLI::UI::Prompt.ask('What is the name of the mod in the Modrinth URL?').strip
91
+ options['install_dir'] = CLI::UI::Prompt.ask('In which directory should the asset be placed?', default: 'mods').strip
92
+ options['filename' ] = CLI::UI::Prompt.ask('Under which filename should the asset be saved? (leave empty for release asset name)', allow_empty: true).strip.then do |filename|
82
93
  filename == '' ? nil : filename
83
94
  end
84
95
 
85
- options['source'].compact!
96
+ options.compact!
86
97
 
87
- [options, Mmi::Source::Modrinth.new(options['source'])]
98
+ Mmi::Source::Modrinth.parse(options)
88
99
  when :url
89
100
  options = {
90
- 'source' => {
91
- 'type' => 'url',
92
- 'url' => '',
93
- },
101
+ 'type' => 'url',
94
102
  }
95
103
 
96
- options['source']['install_dir'] = CLI::UI::Prompt.ask('In which directory should the asset be placed?', default: 'mods').strip
97
- options['source']['filename' ] = CLI::UI::Prompt.ask('Under which filename should the asset be saved? (leave empty for release asset name)', allow_empty: true).strip.then do |filename|
104
+ options['install_dir'] = CLI::UI::Prompt.ask('In which directory should the asset be placed?', default: 'mods').strip
105
+ options['filename' ] = CLI::UI::Prompt.ask('Under which filename should the asset be saved? (leave empty for release asset name)', allow_empty: true).strip.then do |filename|
98
106
  filename == '' ? nil : filename
99
107
  end
100
108
 
101
- options['source'].compact!
109
+ options.compact!
102
110
 
103
- [options, Mmi::Source::Url.new(options['source'])]
111
+ Mmi::Source::Url.parse(options)
104
112
  end
105
113
 
106
- if update_asset_version(source)
107
- self.processor.parsed_assets.items.push(opts)
108
- self.processor.parsed_assets.parsed_items.push(source)
109
-
110
- true
114
+ if update_asset_source_version(source)
115
+ source
111
116
  else
112
- CLI::UI.puts('Aborting asset addition. No change will be made.', color: CLI::UI::Color::RED)
113
-
114
- false
117
+ nil
115
118
  end
116
119
  end
117
120
 
118
- def update_asset_version(asset)
119
- case asset
121
+ def update_asset_source_version(source)
122
+ case source
120
123
  when Mmi::Source::Github
121
- github_releases = Mmi::GithubApi.client.releases("#{asset.owner}/#{asset.repo}")
124
+ github_releases = Mmi::GithubApi.client.releases("#{source.owner}/#{source.repo}")
122
125
 
123
126
  github_release = CLI::UI::Prompt.ask('Choose a release.') do |handler|
124
127
  github_releases.select do |release|
@@ -150,10 +153,11 @@ module Mmi
150
153
  when :quit
151
154
  false
152
155
  else
153
- asset.release = nil
154
- asset.file = nil
155
-
156
- asset.asset_id = release_asset.id
156
+ source.update_properties!({
157
+ release: nil,
158
+ file: nil,
159
+ asset_id: release_asset.id,
160
+ })
157
161
 
158
162
  true
159
163
  end
@@ -161,17 +165,17 @@ module Mmi
161
165
  when Mmi::Source::Modrinth
162
166
  mod_version = CLI::UI::Prompt.ask('Choose a version.') do |handler|
163
167
  version_filter_parameters =
164
- case processor.parsed_modloader
168
+ case processor.modloader
165
169
  when Mmi::Modloader::Fabric
166
170
  {
167
171
  loader: 'fabric',
168
- game_version: processor.parsed_modloader.mcversion,
172
+ game_version: processor.modloader.minecraft_version,
169
173
  }
170
174
  else
171
175
  {}
172
176
  end
173
177
 
174
- asset.cached_mod_versions(**version_filter_parameters).select do |version|
178
+ source.cached_mod_versions(**version_filter_parameters).select do |version|
175
179
  version['files'].any?
176
180
  end.each do |version|
177
181
  handler.option("#{version['name']} (for game versions #{version['game_versions'].join('/')})") do
@@ -200,14 +204,18 @@ module Mmi
200
204
  when :quit
201
205
  false
202
206
  else
203
- asset.version = mod_version['name']
204
- asset.version_file = version_file['filename']
207
+ source.update_properties!({
208
+ version: mod_version['name'],
209
+ version_file: version_file['filename'],
210
+ })
205
211
 
206
212
  true
207
213
  end
208
214
  end
209
215
  when Mmi::Source::Url
210
- asset.url = CLI::UI::Prompt.ask('What is the URL of the file that should be downloaded?', default: asset.url).strip
216
+ url = CLI::UI::Prompt.ask('What is the URL of the file that should be downloaded?', default: source.url).strip
217
+
218
+ source.update_properties!({url: url})
211
219
  else
212
220
  CLI::UI.puts('This asset cannot be updated.', color: CLI::UI::Color::RED)
213
221
 
@@ -9,7 +9,7 @@ module Mmi
9
9
  def update_modloader
10
10
  choice = CLI::UI::Prompt.ask('What do you want to do?') do |handler|
11
11
  [
12
- (["Update current modloader #{self.processor.modloader['name']}", :update_current] unless self.processor.parsed_modloader.is_a?(Mmi::Modloader::None)),
12
+ (["Update current modloader #{self.processor.modloader['name']}", :update_current] unless self.processor.modloader.is_a?(Mmi::Modloader::None)),
13
13
  ['quit', :quit ],
14
14
  ].each do |name, result|
15
15
  handler.option(name) do
@@ -29,7 +29,7 @@ module Mmi
29
29
  end
30
30
 
31
31
  def update_modloader_current
32
- ml = self.processor.parsed_modloader
32
+ ml = self.processor.modloader
33
33
 
34
34
  case ml
35
35
  when Mmi::Modloader::None
@@ -38,12 +38,12 @@ module Mmi
38
38
  loop do
39
39
  choice = CLI::UI::Prompt.ask('What do you want to update?') do |handler|
40
40
  [
41
- ['Installer version', :version ],
42
- ['Minecraft version', :mc_version ],
43
- ['Download Minecraft?', :download_mc ],
44
- ['Install directory', :install_dir ],
45
- ['Install type', :install_type],
46
- ['quit', :quit ],
41
+ ['Installer version', :version ],
42
+ ['Minecraft version', :minecraft_version ],
43
+ ['Download Minecraft?', :download_minecraft],
44
+ ['Install directory', :install_dir ],
45
+ ['Install type', :install_type ],
46
+ ['quit', :quit ],
47
47
  ].each do |name, result|
48
48
  handler.option(name) do
49
49
  result
@@ -65,9 +65,9 @@ module Mmi
65
65
  when :quit
66
66
  # Pass.
67
67
  else
68
- ml.version = choice2
68
+ ml.update_properties!({version: choice2})
69
69
  end
70
- when :mc_version
70
+ when :minecraft_version
71
71
  choice2 =
72
72
  begin
73
73
  CLI::UI::Prompt.ask('Which Minecraft version do you need?')
@@ -79,12 +79,12 @@ module Mmi
79
79
  when :quit
80
80
  # Pass.
81
81
  else
82
- ml.mcversion = choice2
82
+ ml.update_properties!({minecraft_version: choice2})
83
83
  end
84
- when :download_mc
84
+ when :download_minecraft
85
85
  choice2 =
86
86
  begin
87
- CLI::UI::Prompt.confirm('Download minecraft when installing the modloader? (Ctrl+C for no change)', default: ml.download_mc)
87
+ CLI::UI::Prompt.confirm('Download minecraft when installing the modloader? (Ctrl+C for no change)', default: ml.download_minecraft)
88
88
  rescue Interrupt
89
89
  :quit
90
90
  end
@@ -93,7 +93,7 @@ module Mmi
93
93
  when :quit
94
94
  # Pass.
95
95
  else
96
- ml.download_mc = choice2
96
+ ml.update_properties!({download_minecraft: choice2})
97
97
  end
98
98
  when :install_dir
99
99
  choice2 =
@@ -107,7 +107,7 @@ module Mmi
107
107
  when :quit
108
108
  # Pass.
109
109
  else
110
- ml.install_dir = choice2.strip.empty? ? nil : choice2
110
+ ml.update_properties!({install_dir: choice2.strip.empty? ? nil : choice2})
111
111
  end
112
112
  when :install_type
113
113
  choice2 = CLI::UI::Prompt.ask('What type of installation do you want?') do |handler|
@@ -122,7 +122,7 @@ module Mmi
122
122
  when :quit
123
123
  # Pass.
124
124
  else
125
- ml.install_type = choice2
125
+ ml.update_properties!({install_type: choice2})
126
126
  end
127
127
  when :quit
128
128
  break
@@ -39,7 +39,7 @@ module Mmi
39
39
  update_assets
40
40
  when :quit_save
41
41
  file_path = CLI::UI::Prompt.ask('Filename', default: self.file_path, is_file: true)
42
- yaml = self.processor.options.to_yaml
42
+ yaml = self.processor.to_h.to_yaml
43
43
 
44
44
  File.write(File.expand_path(file_path, Dir.pwd), yaml)
45
45
  break
@@ -1,72 +1,20 @@
1
1
  require 'mmi/assets_processor'
2
2
  require 'mmi/modloader/none'
3
3
  require 'mmi/modloader/fabric'
4
- require 'mmi/option_attributes'
4
+ require 'mmi/property_attributes'
5
5
  require 'mmi/semver'
6
6
 
7
7
  module Mmi
8
8
  class ModFileProcessor
9
- include OptionAttributes
9
+ prepend PropertyAttributes
10
10
 
11
- opt_accessor :version
12
- opt_accessor :modloader
13
- opt_accessor :assets
14
-
15
- attr_reader :parsed_modloader
16
- attr_reader :parsed_assets
17
-
18
- def initialize(options)
19
- @options = options
20
-
21
- parse!
22
- end
23
-
24
- def parse!
25
- version = Semver.parse(self.version)
26
- lib_version = Semver.parse(Mmi::VERSION)
27
-
28
- if self.version
29
- if version.major <= lib_version.major
30
- if version.minor > lib_version.minor
31
- Mmi.warn %Q(Config file specified "version" #{version}, but MMI is at #{lib_version}. Some features might not be supported.)
32
- end
33
-
34
- ml = self.modloader
35
- @parsed_modloader =
36
- if ml
37
- case ml['name']
38
- when 'none'
39
- Modloader::None.new(ml)
40
- when 'fabric'
41
- Modloader::Fabric.new(ml)
42
- else
43
- raise Mmi::InvalidAttributeError, "Unkown modloader #{ml['name'].inspect}."
44
- end
45
- else
46
- Modloader::None.new
47
- end
48
-
49
-
50
- if self.assets
51
- if self.assets.is_a?(Hash)
52
- @parsed_assets = AssetsProcessor.new(self.assets)
53
- else
54
- raise Mmi::InvalidAttributeError, %Q(Invalid "assets": expected Hash but received #{self.assets.inspect})
55
- end
56
- else
57
- raise Mmi::MissingAttributeError, 'Missing "assets".'
58
- end
59
- else
60
- raise Mmi::InvalidAttributeError, %Q(Config file specified "version" #{version}, but MMI is at #{lib_version}.)
61
- end
62
- else
63
- raise Mmi::MissingAttributeError, 'Missing "version".'
64
- end
65
- end
11
+ property :version, type: Semver
12
+ property :modloader, type: {field: 'name', types: {'none' => Modloader::None, 'fabric' => Modloader::Fabric}}
13
+ property :assets, type: AssetsProcessor
66
14
 
67
15
  def install
68
- self.parsed_modloader.install
69
- self.parsed_assets.install
16
+ self.modloader.install
17
+ self.assets.install
70
18
  end
71
19
  end
72
20
  end