lapis-minecraft-versioning 0.5.0
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 +7 -0
- data/.codeclimate.yml +18 -0
- data/.gitignore +151 -0
- data/.rspec +3 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.md +16 -0
- data/README.md +83 -0
- data/Rakefile +28 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lapis-minecraft-versioning.gemspec +35 -0
- data/lib/lapis/minecraft/version.rb +89 -0
- data/lib/lapis/minecraft/versioning.rb +26 -0
- data/lib/lapis/minecraft/versioning/asset.rb +44 -0
- data/lib/lapis/minecraft/versioning/asset_index.rb +61 -0
- data/lib/lapis/minecraft/versioning/basic.rb +56 -0
- data/lib/lapis/minecraft/versioning/detailed.rb +69 -0
- data/lib/lapis/minecraft/versioning/launcher_properties.rb +48 -0
- data/lib/lapis/minecraft/versioning/library.rb +51 -0
- data/lib/lapis/minecraft/versioning/manifest.rb +49 -0
- data/lib/lapis/minecraft/versioning/marshalling.rb +15 -0
- data/lib/lapis/minecraft/versioning/marshalling/asset_index_parser.rb +41 -0
- data/lib/lapis/minecraft/versioning/marshalling/manifest_parser.rb +66 -0
- data/lib/lapis/minecraft/versioning/marshalling/version_parser.rb +204 -0
- data/lib/lapis/minecraft/versioning/meta_server.rb +52 -0
- data/lib/lapis/minecraft/versioning/os_rule.rb +45 -0
- data/lib/lapis/minecraft/versioning/resource.rb +44 -0
- data/lib/lapis/minecraft/versioning/resource_set.rb +61 -0
- data/lib/lapis/minecraft/versioning/rule.rb +32 -0
- data/lib/lapis/minecraft/versioning/version.rb +7 -0
- data/lib/lapis/minecraft/versioning/version_list.rb +64 -0
- data/spec/factories/asset_factory.rb +11 -0
- data/spec/factories/asset_index_document_factory.rb +25 -0
- data/spec/factories/asset_index_factory.rb +15 -0
- data/spec/factories/basic_factory.rb +28 -0
- data/spec/factories/detailed_factory.rb +16 -0
- data/spec/factories/launcher_properties_factory.rb +11 -0
- data/spec/factories/library_factory.rb +21 -0
- data/spec/factories/manifest_document_factory.rb +48 -0
- data/spec/factories/manifest_factory.rb +12 -0
- data/spec/factories/meta_server_mock_factory.rb +33 -0
- data/spec/factories/os_rule_factory.rb +30 -0
- data/spec/factories/resource_factory.rb +32 -0
- data/spec/factories/resource_set_factory.rb +16 -0
- data/spec/factories/rule_factory.rb +17 -0
- data/spec/factories/version_document_factory.rb +176 -0
- data/spec/factories/version_factory.rb +18 -0
- data/spec/lapis/minecraft/version_spec.rb +181 -0
- data/spec/lapis/minecraft/versioning/asset_index_spec.rb +89 -0
- data/spec/lapis/minecraft/versioning/asset_spec.rb +65 -0
- data/spec/lapis/minecraft/versioning/basic_spec.rb +75 -0
- data/spec/lapis/minecraft/versioning/detailed_spec.rb +175 -0
- data/spec/lapis/minecraft/versioning/launcher_properties_spec.rb +73 -0
- data/spec/lapis/minecraft/versioning/library_spec.rb +91 -0
- data/spec/lapis/minecraft/versioning/manifest_spec.rb +71 -0
- data/spec/lapis/minecraft/versioning/marshalling/asset_index_parser_spec.rb +27 -0
- data/spec/lapis/minecraft/versioning/marshalling/manifest_parser_spec.rb +74 -0
- data/spec/lapis/minecraft/versioning/marshalling/version_parser_spec.rb +101 -0
- data/spec/lapis/minecraft/versioning/meta_server_spec.rb +59 -0
- data/spec/lapis/minecraft/versioning/os_rule_spec.rb +73 -0
- data/spec/lapis/minecraft/versioning/resource_set_spec.rb +87 -0
- data/spec/lapis/minecraft/versioning/resource_spec.rb +55 -0
- data/spec/lapis/minecraft/versioning/rule_spec.rb +36 -0
- data/spec/lapis/minecraft/versioning/version_list_spec.rb +66 -0
- data/spec/spec_helper.rb +90 -0
- data/spec/time_helper.rb +39 -0
- metadata +289 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'marshalling'
|
2
|
+
|
3
|
+
module Lapis
|
4
|
+
module Minecraft
|
5
|
+
module Versioning
|
6
|
+
|
7
|
+
# Provides functionality for translating version information from a meta-data server.
|
8
|
+
# A meta-data server is a server that responds to requests about Minecraft versions.
|
9
|
+
# @todo Add more checks to response data.
|
10
|
+
class MetaServer
|
11
|
+
|
12
|
+
# Creates a reference to a Minecraft meta-data server.
|
13
|
+
# @param client [HTTPClient] Client used to connect to the meta-data server.
|
14
|
+
def initialize(client)
|
15
|
+
@client = client
|
16
|
+
@manifest_parser = Marshalling::ManifestParser.new
|
17
|
+
@version_parser = Marshalling::VersionParser.new
|
18
|
+
@asset_index_parser = Marshalling::AssetIndexParser.new
|
19
|
+
end
|
20
|
+
|
21
|
+
# Retrieves the manifest from the meta-data server.
|
22
|
+
# @param url [String] URL of the version manifest.
|
23
|
+
# @return [Manifest] Information about all Minecraft versions.
|
24
|
+
def get_manifest(url)
|
25
|
+
response = @client.get(url)
|
26
|
+
fail "Failed to retrieve manifest - #{response.status} (#{response.reason})" if response.status != 200
|
27
|
+
@manifest_parser.parse(response.content)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Retrieves additional information about a Minecraft version.
|
31
|
+
# @param url [String] URL of the version document.
|
32
|
+
# @return [Detailed] Minecraft version information.
|
33
|
+
def get_details(url)
|
34
|
+
response = @client.get(url)
|
35
|
+
fail "Failed to retrieve version - #{response.status} (#{response.reason})" if response.status != 200
|
36
|
+
@version_parser.parse(response.content, url)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Retrieves a listing of assets for a Minecraft version.
|
40
|
+
# @param url [String] URL of the asset index document.
|
41
|
+
# @return [Array<Asset>] List of assets in the index.
|
42
|
+
def get_assets(url)
|
43
|
+
response = @client.get(url)
|
44
|
+
fail "Failed to retrieve assets - #{response.status} (#{response.reason})" if response.status != 200
|
45
|
+
@asset_index_parser.parse(response.content)
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative 'rule'
|
2
|
+
|
3
|
+
module Lapis
|
4
|
+
module Minecraft
|
5
|
+
module Versioning
|
6
|
+
|
7
|
+
# Description of how resources can be chosen for operating systems.
|
8
|
+
class OSRule < Rule
|
9
|
+
|
10
|
+
# Type of operating system this rule applies to.
|
11
|
+
# @return [Symbol] Can be one of: +:windows+, +:linux+, or +:osx+.
|
12
|
+
attr_reader :os_type
|
13
|
+
|
14
|
+
# Operating system version regex.
|
15
|
+
# This rule should apply if the OS version matches this regex.
|
16
|
+
# @return [Regexp]
|
17
|
+
attr_reader :os_version
|
18
|
+
|
19
|
+
# Creates an OS rule.
|
20
|
+
# @param is_allowed [Boolean] Indicates whether the resource should be included.
|
21
|
+
# @param os_type [Symbol] Type of OS this rule applies to.
|
22
|
+
# Can be one of: +:windows+, +:linux+, or +:osx+.
|
23
|
+
# @param os_version [String, nil] OS version regex.
|
24
|
+
# Can be +nil+ to apply to all versions of the OS.
|
25
|
+
def initialize(is_allowed, os_type, os_version = nil)
|
26
|
+
super(is_allowed)
|
27
|
+
@os_type = os_type
|
28
|
+
@os_version = os_version ? Regexp.new(os_version) : // # Use empty regex if no version specified.
|
29
|
+
end
|
30
|
+
|
31
|
+
# Compares one rule to another.
|
32
|
+
# @param other [OSRule] Rule to compare against.
|
33
|
+
# @return [true] The rules are the same.
|
34
|
+
# @return [false] The rules are different.
|
35
|
+
def ==(other)
|
36
|
+
super(other) &&
|
37
|
+
other.os_type == @os_type &&
|
38
|
+
other.os_version == @os_version
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require_relative 'asset'
|
2
|
+
|
3
|
+
module Lapis
|
4
|
+
module Minecraft
|
5
|
+
module Versioning
|
6
|
+
|
7
|
+
# Information about a resource (file) to download as part of the client or server.
|
8
|
+
class Resource < Asset
|
9
|
+
|
10
|
+
# URL where the resource can be found and downloaded from.
|
11
|
+
# @return [String] Download URL.
|
12
|
+
attr_reader :url
|
13
|
+
|
14
|
+
# Logical category the resource falls under.
|
15
|
+
# @return [String, nil] Name of the category or +nil+ if the resource doesn't have one.
|
16
|
+
attr_reader :classifier
|
17
|
+
|
18
|
+
# Creates information about a resource.
|
19
|
+
# @param url [String] URL where the resource can be found and downloaded from.
|
20
|
+
# @param size [Fixnum] Size of the resource in bytes.
|
21
|
+
# @param sha1 [String] SHA1 hash of the resource's contents in hexadecimal.
|
22
|
+
# @param path [String, nil] Path, relative to the installation directory, to store the resource.
|
23
|
+
# @param classifier [String, nil] Logical category the resource falls under.
|
24
|
+
def initialize(url, size, sha1, path = nil, classifier = nil)
|
25
|
+
super(size, sha1, path)
|
26
|
+
@url = url.dup.freeze
|
27
|
+
@classifier = classifier.dup.freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
# Compares one resource to another.
|
31
|
+
# @param other [Resource] Resource to compare against.
|
32
|
+
# @return [true] The resources are the same.
|
33
|
+
# @return [false] The resources are different.
|
34
|
+
def ==(other)
|
35
|
+
super(other) &&
|
36
|
+
other.url == @url &&
|
37
|
+
other.classifier == @classifier
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Lapis
|
2
|
+
module Minecraft
|
3
|
+
module Versioning
|
4
|
+
|
5
|
+
# Information about the archives and natives needed for a library.
|
6
|
+
# @see Resource
|
7
|
+
class ResourceSet
|
8
|
+
|
9
|
+
# Classifier for the Windows native.
|
10
|
+
# @return [String] Classifier for Windows.
|
11
|
+
# @return [nil] No Windows native for this library.
|
12
|
+
# @note This value can contain variables.
|
13
|
+
attr_reader :windows_classifier
|
14
|
+
|
15
|
+
# Classifier for the Linux native.
|
16
|
+
# @return [String] Classifier for Linux.
|
17
|
+
# @return [nil] No Linux native for this library.
|
18
|
+
# @note This value can contain variables.
|
19
|
+
attr_reader :linux_classifier
|
20
|
+
|
21
|
+
# Classifier for the OSX native.
|
22
|
+
# @return [String] Classifier for OSX.
|
23
|
+
# @return [nil] No OSX native for this library.
|
24
|
+
# @note This value can contain variables.
|
25
|
+
attr_reader :osx_classifier
|
26
|
+
|
27
|
+
# List of all resources (including natives) the library uses.
|
28
|
+
# @return [Array<Resource>]
|
29
|
+
attr_reader :resources
|
30
|
+
|
31
|
+
# Creates a new resource set.
|
32
|
+
# @param resources [Array<Resource>] List of all resources (including natives).
|
33
|
+
# @param windows_classifier [String, nil] Classifier for the Windows native.
|
34
|
+
# Specify +nil+ if there is no native for Windows.
|
35
|
+
# @param linux_classifier [String, nil] Classifier for the Linux native.
|
36
|
+
# Specify +nil+ if there is no native for Linux.
|
37
|
+
# @param osx_classifier [String, nil] Classifier for the OSX native.
|
38
|
+
# Specify +nil+ if there is no native for OSX.
|
39
|
+
def initialize(resources, windows_classifier = nil, linux_classifier = nil, osx_classifier = nil)
|
40
|
+
@windows_classifier = windows_classifier ? windows_classifier.dup.freeze : nil
|
41
|
+
@linux_classifier = linux_classifier ? linux_classifier.dup.freeze : nil
|
42
|
+
@osx_classifier = osx_classifier ? osx_classifier.dup.freeze : nil
|
43
|
+
@resources = resources.dup.freeze
|
44
|
+
end
|
45
|
+
|
46
|
+
# Compares one resource set to another.
|
47
|
+
# @param other [ResourceSet] Resource set to compare against.
|
48
|
+
# @return [true] The resource sets are the same.
|
49
|
+
# @return [false] The resource sets are different.
|
50
|
+
def ==(other)
|
51
|
+
other.windows_classifier == @windows_classifier &&
|
52
|
+
other.linux_classifier == @linux_classifier &&
|
53
|
+
other.osx_classifier == @osx_classifier &&
|
54
|
+
other.resources == @resources
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Lapis
|
2
|
+
module Minecraft
|
3
|
+
module Versioning
|
4
|
+
|
5
|
+
# Description of how resources can be chosen.
|
6
|
+
class Rule
|
7
|
+
|
8
|
+
# @!attribute [r] allowed?
|
9
|
+
# Indicates whether the resource should be included.
|
10
|
+
def allowed?
|
11
|
+
@is_allowed
|
12
|
+
end
|
13
|
+
|
14
|
+
# Creates a basic rule.
|
15
|
+
# @param is_allowed [Boolean] Indicates whether the resource should be included.
|
16
|
+
def initialize(is_allowed)
|
17
|
+
@is_allowed = !!is_allowed
|
18
|
+
end
|
19
|
+
|
20
|
+
# Compares one rule to another.
|
21
|
+
# @param other [Rule] Rule to compare against.
|
22
|
+
# @return [true] The rules are the same.
|
23
|
+
# @return [false] The rules are different.
|
24
|
+
def ==(other)
|
25
|
+
other.allowed? == @is_allowed
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'httpclient'
|
2
|
+
require_relative 'meta_server'
|
3
|
+
require_relative '../version'
|
4
|
+
|
5
|
+
module Lapis
|
6
|
+
module Minecraft
|
7
|
+
module Versioning
|
8
|
+
|
9
|
+
# Complete listing of Minecraft versions and detailed information about them.
|
10
|
+
class VersionList
|
11
|
+
include Enumerable
|
12
|
+
|
13
|
+
# URL of the official Mojang Minecraft version list.
|
14
|
+
OFFICIAL_MANIFEST_URL = 'https://launchermeta.mojang.com/mc/game/version_manifest.json'
|
15
|
+
|
16
|
+
# Singleton for retrieving information about official Minecraft versions.
|
17
|
+
# @return [VersionList] Access to official version information.
|
18
|
+
def self.official
|
19
|
+
@official ||= new(OFFICIAL_MANIFEST_URL)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Creates a version list.
|
23
|
+
# @param manifest_url [String] URL of the document listing all versions.
|
24
|
+
def initialize(manifest_url)
|
25
|
+
@manifest_url = manifest_url.dup.freeze
|
26
|
+
@meta_server = MetaServer.new(HTTPClient.new)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Iterates over all versions.
|
30
|
+
# @yieldparam version [Version] Next version in the list.
|
31
|
+
# @return [void]
|
32
|
+
def each
|
33
|
+
return enum_for(:each) unless block_given?
|
34
|
+
|
35
|
+
manifest.each do |basic|
|
36
|
+
yield Version.new(basic, @meta_server)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Retrieves the latest released version.
|
41
|
+
# @return [Version] Version information.
|
42
|
+
def latest_release
|
43
|
+
Version.new(manifest.latest_release, @meta_server)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Information about the latest snapshot version.
|
47
|
+
# @return [Version] Version information.
|
48
|
+
def latest_snapshot
|
49
|
+
Version.new(manifest.latest_snapshot, @meta_server)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
# Retrieves and caches the manifest data.
|
55
|
+
# @return [Manifest]
|
56
|
+
def manifest
|
57
|
+
@manifest ||= @meta_server.get_manifest(@manifest_url)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :asset, class: Lapis::Minecraft::Versioning::Asset do
|
3
|
+
transient do
|
4
|
+
sequence(:path) { |n| "foo/bar/baz/asset-#{n}" }
|
5
|
+
size { Random.rand(16777216).to_i }
|
6
|
+
sha1 { Digest::SHA1.hexdigest path.to_s }
|
7
|
+
end
|
8
|
+
|
9
|
+
initialize_with { new(size, sha1, path) }
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
FactoryGirl.define do
|
4
|
+
factory :asset_document_entry, class: Array do
|
5
|
+
transient do
|
6
|
+
asset { build(:asset) }
|
7
|
+
end
|
8
|
+
|
9
|
+
initialize_with { [asset.path, {:hash => asset.sha1, :size => asset.size}] }
|
10
|
+
end
|
11
|
+
|
12
|
+
IndexStruct = Struct.new(:assets, :document)
|
13
|
+
|
14
|
+
factory :asset_index_document, class: IndexStruct do
|
15
|
+
transient do
|
16
|
+
asset_count 10
|
17
|
+
assets { build_list(:asset, asset_count) }
|
18
|
+
asset_list { assets.map { |asset| build(:asset_document_entry, :asset => asset) } }
|
19
|
+
structure { { :objects => Hash[asset_list] } }
|
20
|
+
json { structure.to_json }
|
21
|
+
end
|
22
|
+
|
23
|
+
initialize_with { new(asset_list, json) }
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :asset_index, class: Lapis::Minecraft::Versioning::AssetIndex do
|
3
|
+
transient do
|
4
|
+
sequence(:id) { |n| "Assets-#{n}" }
|
5
|
+
asset_count 20
|
6
|
+
assets { build_list(:asset, asset_count) }
|
7
|
+
size 500
|
8
|
+
url { "http://example.com/minecraft/assets/#{id}.json" }
|
9
|
+
total_size { assets.lazy.map { |asset| asset.size }.inject(:+) }
|
10
|
+
sha1 { Digest::SHA1.hexdigest assets.lazy.map { |asset| asset.path }.inject(:+) }
|
11
|
+
end
|
12
|
+
|
13
|
+
initialize_with { new(id, sha1, size, url, total_size) }
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :basic, class: Lapis::Minecraft::Versioning::Basic do
|
3
|
+
transient do
|
4
|
+
sequence(:id) { |n| "Version-1.0.#{n}" }
|
5
|
+
sequence(:url) { |n| "https://example.com/minecraft/versions/1.0.#{n}.json" }
|
6
|
+
type :release
|
7
|
+
time { 10.days.ago.round }
|
8
|
+
end
|
9
|
+
|
10
|
+
trait :alpha do
|
11
|
+
type :alpha
|
12
|
+
end
|
13
|
+
|
14
|
+
trait :beta do
|
15
|
+
type :beta
|
16
|
+
end
|
17
|
+
|
18
|
+
trait :snapshot do
|
19
|
+
type :snapshot
|
20
|
+
end
|
21
|
+
|
22
|
+
trait :release do
|
23
|
+
type :release
|
24
|
+
end
|
25
|
+
|
26
|
+
initialize_with { new(id, type, time, url) }
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :detailed, parent: :basic, class: Lapis::Minecraft::Versioning::Detailed do
|
3
|
+
transient do
|
4
|
+
assets { build_list(:asset, 20) }
|
5
|
+
asset_index { build(:asset_index, :assets => assets) }
|
6
|
+
downloads { [build(:download, :client), build(:download, :server), build(:resource)] }
|
7
|
+
libraries { build_list(:library, 5) }
|
8
|
+
launcher_properties { build(:launcher) }
|
9
|
+
end
|
10
|
+
|
11
|
+
initialize_with do
|
12
|
+
basic = Lapis::Minecraft::Versioning::Basic.new(id, type, time, url)
|
13
|
+
new(basic, asset_index, downloads, libraries, launcher_properties)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :launcher, class: Lapis::Minecraft::Versioning::LauncherProperties do
|
3
|
+
transient do
|
4
|
+
main_class 'com.example.minecraft.client'
|
5
|
+
arguments %w(-user ${user} -key ${key})
|
6
|
+
minimum_version 7
|
7
|
+
end
|
8
|
+
|
9
|
+
initialize_with { new(main_class, arguments, minimum_version) }
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :library_path, class: String do
|
3
|
+
transient do
|
4
|
+
sequence(:path) { |n| "exclude-path-#{n}" }
|
5
|
+
end
|
6
|
+
|
7
|
+
initialize_with { path }
|
8
|
+
end
|
9
|
+
|
10
|
+
factory :library, class: Lapis::Minecraft::Versioning::Library do
|
11
|
+
transient do
|
12
|
+
sequence(:name) { |n| "mc-library-#{n}" }
|
13
|
+
exclude_path_count 1
|
14
|
+
resources { build(:resource_set) }
|
15
|
+
rules { [build(:rule), build(:os_rule)] }
|
16
|
+
paths { build_list(:library_path, exclude_path_count) }
|
17
|
+
end
|
18
|
+
|
19
|
+
initialize_with { new(name, resources, rules, paths) }
|
20
|
+
end
|
21
|
+
end
|