dsp_blueprint_parser 0.1.3 → 0.2.1

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.
@@ -1,40 +1,41 @@
1
- # frozen_string_literal: true
2
-
3
- module DspBlueprintParser
4
- # Data Sections
5
- #
6
- # Given a raw DSP Blueprint sting this returns readability
7
- # usable data on the string
8
- class DataSections
9
- # @param str_blueprint [String]
10
- def initialize(str_blueprint)
11
- @str_blueprint = str_blueprint
12
- @first_quote_loc = @str_blueprint.index('"')
13
- @second_quote_loc = @str_blueprint[(@first_quote_loc + 1)..].index('"') + @first_quote_loc
14
- end
15
-
16
- # @return [Array<String>]
17
- def header_segments
18
- @header_segments ||= @str_blueprint[10..@first_quote_loc - 1].split(',')
19
- end
20
-
21
- def hashed_string
22
- @str_blueprint[..@second_quote_loc]
23
- end
24
-
25
- def hash
26
- @str_blueprint[@second_quote_loc + 2..-1]
27
- end
28
-
29
- # @return [Array<Integer>] array of bytes, 0..255
30
- def decompressed_body
31
- @decompressed_body ||=
32
- @str_blueprint[@first_quote_loc + 1..@second_quote_loc]
33
- .then(&Base64.method(:decode64))
34
- .then(&StringIO.method(:new))
35
- .then(&Zlib::GzipReader.method(:new))
36
- .each_byte
37
- .to_a
38
- end
39
- end
40
- end
1
+ # frozen_string_literal: true
2
+
3
+ module DspBlueprintParser
4
+ # Data Sections
5
+ #
6
+ # Given a raw DSP Blueprint sting this returns readability
7
+ # usable data on the string
8
+ class DataSections
9
+ # @param str_blueprint [String]
10
+ def initialize(str_blueprint)
11
+ @str_blueprint = str_blueprint.strip
12
+ @blueprint_type_loc = @str_blueprint.index(':')
13
+ @first_quote_loc = @str_blueprint.index('"')
14
+ @second_quote_loc = @str_blueprint[(@first_quote_loc + 1)..].index('"') + @first_quote_loc + 1
15
+ end
16
+
17
+ # @return [Array<String>]
18
+ def header_segments
19
+ @header_segments ||= @str_blueprint[@blueprint_type_loc..@first_quote_loc - 1].split(',')
20
+ end
21
+
22
+ def hashed_string
23
+ @str_blueprint[..@second_quote_loc - 1]
24
+ end
25
+
26
+ def hash
27
+ @str_blueprint[@second_quote_loc + 1..-1]
28
+ end
29
+
30
+ # @return [Array<Integer>] array of bytes, 0..255
31
+ def decompressed_body
32
+ @decompressed_body ||=
33
+ @str_blueprint[@first_quote_loc + 1..@second_quote_loc - 1]
34
+ .then(&Base64.method(:decode64))
35
+ .then(&StringIO.method(:new))
36
+ .then(&Zlib::GzipReader.method(:new))
37
+ .each_byte
38
+ .to_a
39
+ end
40
+ end
41
+ end
@@ -1,23 +1,23 @@
1
- # frozen_string_literal: true
2
-
3
- module DspBlueprintParser
4
- module IconLayout
5
- NONE = 0
6
- NO_ICON = 1
7
- ONE_ICON = 10
8
- ONE_ICON_SMALL = 11
9
- TWO_ICON_46 = 20
10
- TWO_ICON_53 = 21
11
- TWO_ICON_59 = 22
12
- TWO_ICON_57 = 23
13
- TWO_ICON_51 = 24
14
- THREE_ICON_813 = 30
15
- THREE_ICON_279 = 31
16
- THREE_ICON_573 = 32
17
- THREE_ICON_591 = 33
18
- FOUR_ICON_7913 = 40
19
- FOUR_ICON_8462 = 41
20
- FIVE_ICON_57913 = 50
21
- FIVE_ICON_PENTA = 51
22
- end
23
- end
1
+ # frozen_string_literal: true
2
+
3
+ module DspBlueprintParser
4
+ module IconLayout
5
+ NONE = 0
6
+ NO_ICON = 1
7
+ ONE_ICON = 10
8
+ ONE_ICON_SMALL = 11
9
+ TWO_ICON_46 = 20
10
+ TWO_ICON_53 = 21
11
+ TWO_ICON_59 = 22
12
+ TWO_ICON_57 = 23
13
+ TWO_ICON_51 = 24
14
+ THREE_ICON_813 = 30
15
+ THREE_ICON_279 = 31
16
+ THREE_ICON_573 = 32
17
+ THREE_ICON_591 = 33
18
+ FOUR_ICON_7913 = 40
19
+ FOUR_ICON_8462 = 41
20
+ FIVE_ICON_57913 = 50
21
+ FIVE_ICON_PENTA = 51
22
+ end
23
+ end
@@ -1,119 +1,89 @@
1
- # frozen_string_literal: true
2
-
3
- module DspBlueprintParser
4
- # class to orchestrate parsing
5
- class Parser
6
- SECONDS_AT_EPOC = 62_135_596_800
7
-
8
- # @param [String] str_blueprint
9
- def initialize(str_blueprint)
10
- @data_sections = DataSections.new(str_blueprint)
11
- end
12
-
13
- # @return [BlueprintData]
14
- def blueprint
15
- @blueprint ||= BlueprintData.new.tap do |blueprint|
16
- parse_metadata(blueprint)
17
- parse_areas(blueprint)
18
- parse_buildings(blueprint)
19
- end
20
- end
21
-
22
- private
23
-
24
- # @return [Array<String>]
25
- def header_segments
26
- @header_segments ||= @data_sections.header_segments
27
- end
28
-
29
- # @return [BinaryReader]
30
- def reader
31
- @reader ||= BinaryReader.new(@data_sections.decompressed_body)
32
- end
33
-
34
- # @param ticks [Integer]
35
- # @return [Time]
36
- def ticks_to_epoch(ticks)
37
- # 10mil ticks per second
38
- seconds = ticks / 10_000_000
39
-
40
- Time.at(seconds - SECONDS_AT_EPOC)
41
- end
42
-
43
- # @param [BlueprintData] blueprint
44
- def parse_areas(blueprint)
45
- reader.read_i8.times do
46
- area = Area.new
47
- area.index = reader.read_i8
48
- area.parent_index = reader.read_i8
49
- area.tropic_anchor = reader.read_i16
50
- area.area_segments = reader.read_i16
51
- area.anchor_local_offset_x = reader.read_i16
52
- area.anchor_local_offset_y = reader.read_i16
53
- area.width = reader.read_i16
54
- area.height = reader.read_i16
55
-
56
- blueprint.areas << area
57
- end
58
- end
59
-
60
- # @param [BlueprintData] blueprint
61
- def parse_buildings(blueprint)
62
- reader.read_i32.times do
63
- building = Building.new
64
- building.index = reader.read_i32
65
- building.area_index = reader.read_i8
66
- building.local_offset_x = reader.read_single
67
- building.local_offset_y = reader.read_single
68
- building.local_offset_z = reader.read_single
69
- building.local_offset_x2 = reader.read_single
70
- building.local_offset_y2 = reader.read_single
71
- building.local_offset_z2 = reader.read_single
72
- building.yaw = reader.read_single
73
- building.yaw2 = reader.read_single
74
- building.item_id = reader.read_i16
75
- building.model_index = reader.read_i16
76
- building.temp_output_obj_idx = reader.read_i32
77
- building.temp_input_obj_idx = reader.read_i32
78
- building.output_to_slot = reader.read_i8
79
- building.input_from_slot = reader.read_i8
80
- building.output_from_slot = reader.read_i8
81
- building.input_to_slot = reader.read_i8
82
- building.output_offset = reader.read_i8
83
- building.input_offset = reader.read_i8
84
- building.recipe_id = reader.read_i16
85
- building.filter_fd = reader.read_i16
86
-
87
- reader.read_i16.times do
88
- building.parameters << reader.read_i32
89
- end
90
-
91
- blueprint.buildings << building
92
- end
93
- end
94
-
95
- # @param [BlueprintData] blueprint
96
- def parse_metadata(blueprint)
97
- blueprint.icon_layout = header_segments[1].to_i
98
- blueprint.icon0 = header_segments[2].to_i
99
- blueprint.icon1 = header_segments[3].to_i
100
- blueprint.icon2 = header_segments[4].to_i
101
- blueprint.icon3 = header_segments[5].to_i
102
- blueprint.icon4 = header_segments[6].to_i
103
-
104
- blueprint.time = ticks_to_epoch(header_segments[8].to_i)
105
- blueprint.game_version = header_segments[9]
106
-
107
- blueprint.short_description = CGI.unescape(header_segments[10]) if header_segments[10]
108
- blueprint.description = CGI.unescape(header_segments[11]) if header_segments[11]
109
-
110
- blueprint.version = reader.read_i32
111
- blueprint.cursor_offset_x = reader.read_i32
112
- blueprint.cursor_offset_y = reader.read_i32
113
- blueprint.cursor_target_area = reader.read_i32
114
- blueprint.drag_box_size_x = reader.read_i32
115
- blueprint.drag_box_size_y = reader.read_i32
116
- blueprint.primary_area_idx = reader.read_i32
117
- end
118
- end
119
- end
1
+ # frozen_string_literal: true
2
+
3
+ module DspBlueprintParser
4
+ # class to orchestrate parsing
5
+ class Parser
6
+ SECONDS_AT_EPOC = 62_135_596_800
7
+
8
+ # @param [String] str_blueprint
9
+ def initialize(str_blueprint)
10
+ @data_sections = DataSections.new(str_blueprint)
11
+ end
12
+
13
+ # @return [BlueprintData]
14
+ def blueprint
15
+ @blueprint ||= BlueprintData.new.tap do |blueprint|
16
+ parse_metadata(blueprint)
17
+ parse_areas(blueprint)
18
+ parse_buildings(blueprint)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ # @return [Array<String>]
25
+ def header_segments
26
+ @header_segments ||= @data_sections.header_segments
27
+ end
28
+
29
+ # @return [BinaryReader]
30
+ def reader
31
+ @reader ||= BinaryReader.new(@data_sections.decompressed_body)
32
+ end
33
+
34
+ # @param ticks [Integer]
35
+ # @return [Time]
36
+ def ticks_to_epoch(ticks)
37
+ # 10mil ticks per second
38
+ seconds = ticks / 10_000_000
39
+
40
+ Time.at(seconds - SECONDS_AT_EPOC)
41
+ end
42
+
43
+ # @param [BlueprintData] blueprint
44
+ def parse_areas(blueprint)
45
+ reader.read_i8.times do
46
+ area = Area.new
47
+ area.index = reader.read_i8
48
+ area.parent_index = reader.read_i8
49
+ area.tropic_anchor = reader.read_i16
50
+ area.area_segments = reader.read_i16
51
+ area.anchor_local_offset_x = reader.read_i16
52
+ area.anchor_local_offset_y = reader.read_i16
53
+ area.width = reader.read_i16
54
+ area.height = reader.read_i16
55
+
56
+ blueprint.areas << area
57
+ end
58
+ end
59
+
60
+ # @param [BlueprintData] blueprint
61
+ def parse_buildings(blueprint)
62
+ BuildingParser.process!(blueprint, reader)
63
+ end
64
+
65
+ # @param [BlueprintData] blueprint
66
+ def parse_metadata(blueprint)
67
+ blueprint.icon_layout = header_segments[1].to_i
68
+ blueprint.icon0 = header_segments[2].to_i
69
+ blueprint.icon1 = header_segments[3].to_i
70
+ blueprint.icon2 = header_segments[4].to_i
71
+ blueprint.icon3 = header_segments[5].to_i
72
+ blueprint.icon4 = header_segments[6].to_i
73
+
74
+ blueprint.time = ticks_to_epoch(header_segments[8].to_i)
75
+ blueprint.game_version = header_segments[9]
76
+
77
+ blueprint.short_description = CGI.unescape(header_segments[10]) if header_segments[10]
78
+ blueprint.description = CGI.unescape(header_segments[11]) if header_segments[11]
79
+
80
+ blueprint.version = reader.read_i32
81
+ blueprint.cursor_offset_x = reader.read_i32
82
+ blueprint.cursor_offset_y = reader.read_i32
83
+ blueprint.cursor_target_area = reader.read_i32
84
+ blueprint.drag_box_size_x = reader.read_i32
85
+ blueprint.drag_box_size_y = reader.read_i32
86
+ blueprint.primary_area_idx = reader.read_i32
87
+ end
88
+ end
89
+ end
@@ -1,5 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
- module DspBlueprintParser
4
- VERSION = '0.1.3'
5
- end
1
+ # frozen_string_literal: true
2
+
3
+ module DspBlueprintParser
4
+ VERSION = '0.2.1'
5
+ end
@@ -1,43 +1,46 @@
1
- # frozen_string_literal: true
2
-
3
- require 'date'
4
- require 'zlib'
5
- require 'stringio'
6
- require 'base64'
7
- require 'md5f'
8
-
9
- require_relative 'dsp_blueprint_parser/version'
10
- require_relative 'dsp_blueprint_parser/blueprint_data'
11
- require_relative 'dsp_blueprint_parser/icon_layout'
12
- require_relative 'dsp_blueprint_parser/area'
13
- require_relative 'dsp_blueprint_parser/building'
14
- require_relative 'dsp_blueprint_parser/binary_reader'
15
- require_relative 'dsp_blueprint_parser/parser'
16
- require_relative 'dsp_blueprint_parser/data_sections'
17
-
18
- # module to receive a Dyson Sphere Program blueprint string and parse it
19
- module DspBlueprintParser
20
- class Error < StandardError; end
21
-
22
- # @param str_blueprint [String]
23
- # @return [BlueprintData]
24
- def self.parse(str_blueprint)
25
- return if str_blueprint.size < 28
26
- return unless str_blueprint.start_with? 'BLUEPRINT:'
27
-
28
- parser = Parser.new(str_blueprint)
29
- parser.blueprint
30
- end
31
-
32
- # @param input [String]
33
- # @return [Boolean]
34
- def self.is_valid?(input)
35
- return false if input.size < 28
36
- return false unless input.start_with? 'BLUEPRINT:'
37
-
38
- sections = DataSections.new(input)
39
- hash = MD5F::compute(sections.hashed_string)
40
-
41
- return sections.hash == hash
42
- end
43
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+ require 'zlib'
5
+ require 'stringio'
6
+ require 'base64'
7
+ require 'md5f'
8
+
9
+ require_relative 'dsp_blueprint_parser/version'
10
+ require_relative 'dsp_blueprint_parser/blueprint_data'
11
+ require_relative 'dsp_blueprint_parser/icon_layout'
12
+ require_relative 'dsp_blueprint_parser/area'
13
+ require_relative 'dsp_blueprint_parser/building'
14
+ require_relative 'dsp_blueprint_parser/binary_reader'
15
+ require_relative 'dsp_blueprint_parser/parser'
16
+ require_relative 'dsp_blueprint_parser/building_parser'
17
+ require_relative 'dsp_blueprint_parser/data_sections'
18
+
19
+ BLUEPRINT_TYPE = /(BLUEPRINT|DYBP):/
20
+
21
+ # module to receive a Dyson Sphere Program blueprint string and parse it
22
+ module DspBlueprintParser
23
+ class Error < StandardError; end
24
+
25
+ # @param str_blueprint [String]
26
+ # @return [BlueprintData]
27
+ def self.parse(str_blueprint)
28
+ return if str_blueprint.size < 28
29
+ return unless str_blueprint.start_with? BLUEPRINT_TYPE
30
+
31
+ parser = Parser.new(str_blueprint)
32
+ parser.blueprint
33
+ end
34
+
35
+ # @param input [String]
36
+ # @return [Boolean]
37
+ def self.is_valid?(input)
38
+ return false if input.size < 28
39
+ return false unless input.start_with? BLUEPRINT_TYPE
40
+
41
+ sections = DataSections.new(input)
42
+ hash = MD5F::compute(sections.hashed_string)
43
+
44
+ return sections.hash == hash
45
+ end
46
+ end
data/lib/md5f.so CHANGED
Binary file
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dsp_blueprint_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Falk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-08 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2025-12-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake-compiler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
13
27
  description: Parse Dyson Sphere Program blueprint string
14
28
  email:
15
29
  - LRFalk01@gmail.com
@@ -37,6 +51,7 @@ files:
37
51
  - lib/dsp_blueprint_parser/binary_reader.rb
38
52
  - lib/dsp_blueprint_parser/blueprint_data.rb
39
53
  - lib/dsp_blueprint_parser/building.rb
54
+ - lib/dsp_blueprint_parser/building_parser.rb
40
55
  - lib/dsp_blueprint_parser/data_sections.rb
41
56
  - lib/dsp_blueprint_parser/icon_layout.rb
42
57
  - lib/dsp_blueprint_parser/parser.rb
@@ -63,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
63
78
  - !ruby/object:Gem::Version
64
79
  version: '0'
65
80
  requirements: []
66
- rubygems_version: 3.1.2
81
+ rubygems_version: 3.2.3
67
82
  signing_key:
68
83
  specification_version: 4
69
84
  summary: Parse Dyson Sphere Program blueprint string