mmi 0.2.1 → 0.2.3

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: 54e9d7ed91e3ac72f8c78ba1d9bb550de696e87b134e4bd1f5db393e99e7d7d2
4
- data.tar.gz: 55df81f836288de4d0166c03488b7a3362992e6fc76304ccba2dc085758b1bb8
3
+ metadata.gz: 84c944c267d13afff856179fd1a089d1ff6213a865e256f6c2678ed7f24e09ee
4
+ data.tar.gz: 3da84073781c7e7a185e3e9f03fba104649c1b695b25bc4aa74e90b6cdc8e6da
5
5
  SHA512:
6
- metadata.gz: 2c9e1954062c87ea12251b23103fee16b141a9c1f78ca88199c70441649090c16f5bb09481e5d6b158903f6553c201a754608346b12dbc208400fa973eebab73
7
- data.tar.gz: '0481cffce09c9bf0439c1b739cb53cfeba1779a994c4b0ee203f45c3c17becd0164cc8c4b6c7400da01e26605e4e2065c4eeb141f0c6054fef06722f7bd7def2'
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,17 +153,29 @@ 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
160
164
  end
161
165
  when Mmi::Source::Modrinth
162
166
  mod_version = CLI::UI::Prompt.ask('Choose a version.') do |handler|
163
- asset.cached_mod_versions.select do |version|
167
+ version_filter_parameters =
168
+ case processor.modloader
169
+ when Mmi::Modloader::Fabric
170
+ {
171
+ loader: 'fabric',
172
+ game_version: processor.modloader.minecraft_version,
173
+ }
174
+ else
175
+ {}
176
+ end
177
+
178
+ source.cached_mod_versions(**version_filter_parameters).select do |version|
164
179
  version['files'].any?
165
180
  end.each do |version|
166
181
  handler.option("#{version['name']} (for game versions #{version['game_versions'].join('/')})") do
@@ -189,14 +204,18 @@ module Mmi
189
204
  when :quit
190
205
  false
191
206
  else
192
- asset.version = mod_version['name']
193
- asset.version_file = version_file['filename']
207
+ source.update_properties!({
208
+ version: mod_version['name'],
209
+ version_file: version_file['filename'],
210
+ })
194
211
 
195
212
  true
196
213
  end
197
214
  end
198
215
  when Mmi::Source::Url
199
- 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})
200
219
  else
201
220
  CLI::UI.puts('This asset cannot be updated.', color: CLI::UI::Color::RED)
202
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