rrb-common 0.1.6 → 0.1.7

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: 25249c7b5e3aa642c23637cc4e3bad8ce62434a1d77962287fe7cab331d016c9
4
- data.tar.gz: 7592bacd9ddfb0d7371bfd24f87a84de502e2500f7a81a5ca3f8bbd5f1d888a5
3
+ metadata.gz: 0ce1791f92b3956911a84c638f8c6b55b1dc41b250321f0ee14a3aa2e70771d0
4
+ data.tar.gz: 1d80809c5a7633e2f379a3c6df03ad0cd278d127775a2ad76fae52c31f4ae534
5
5
  SHA512:
6
- metadata.gz: 58a9a9da24f64061478f46982beb434b6a3e917c494bf36e437b50570593b2b05bb9870ad50bee4fb08cb82bfec4eb90e8377cae5504e513584582ce1030b6bf
7
- data.tar.gz: b4810f557135b53ba88e89850d59076f24650df965ec0b497868ec41d7a47e8d47c635c6b5797c5297d994446335a479e1dad3c0f22da04c810503a571af8460
6
+ metadata.gz: 59abbc5acfb4daad674f5555d23adf9714987a448fbc6c051aee422977672206550973039df89f85dd27adc31b872763b3c700983022bf91333fe46232d7af0b
7
+ data.tar.gz: af50e56189702d9c4820ec9a78e04ec0a4dc042a825ff7015d736938dd6119610d75df3e16792d7329eb2c7cc46f3dc8359fcdc8e2179ff96ec6cc7ceca94819
@@ -0,0 +1,63 @@
1
+ module RuneRb::Cache
2
+ # An archive of data in the Cache.
3
+ class Archive
4
+ include RuneRb::Core::Logging
5
+
6
+ # @!attribute [r] entries
7
+ # @return [Array<Hash>] the entries in the archive
8
+ attr_reader :entries
9
+
10
+ # Constructs a new CacheArchive
11
+ # @param entries [Array<Hash>] the entries in the archive
12
+ def initialize(entries)
13
+ @entries = entries
14
+ end
15
+
16
+ # Decodes an archive from the specified buffer.
17
+ # @param buffer [RuneRb::Core::Buffer] the buffer to decode
18
+ def self.decode(buffer)
19
+ extracted_size = buffer.read(type: :int24)
20
+ size = buffer.read(type: :int24)
21
+ extracted = false
22
+
23
+ if size != extracted_size
24
+ data = buffer.data.slice!(0..size)
25
+ data = StringIO.new(data)
26
+ decompressor = RBzip2.default_adapter::Decompressor.new(data)
27
+ buffer = RuneRb::Core::Buffer.new(mode: 'r')
28
+ buffer << decompressor.read
29
+ extracted = true
30
+ end
31
+
32
+ entry_count = buffer.read(type: :short)
33
+ identifiers = Array.new(entry_count)
34
+ extracted_sizes = Array.new(entry_count)
35
+ sizes = Array.new(entry_count)
36
+
37
+ entry_count.times do |i|
38
+ identifiers[i] = buffer.read(type: :int)
39
+ extracted_sizes[i] = buffer.read(type: :int24)
40
+ sizes[i] = buffer.read(type: :int24)
41
+ end
42
+
43
+ entries = Array.new(entry_count)
44
+ entry_count.times do |entry|
45
+ entry_buffer = RuneRb::Core::Buffer.new(mode: 'r')
46
+
47
+ if extracted == false
48
+ data = buffer.data.slice!(0..sizes[entry])
49
+ data = StringIO.new(data)
50
+ decompressor = RBzip2.default_adapter::Decompressor.new(data)
51
+ entry_buffer << decompressor.read
52
+ else
53
+ data = buffer.data.slice!(0..extracted_sizes[entry])
54
+ entry_buffer << data
55
+ end
56
+
57
+ entries[entry] = { id: identifiers[entry], buffer: entry_buffer }
58
+ end
59
+
60
+ RuneRb::Cache::Archive.new(entries)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,21 @@
1
+ module RuneRb::Cache::Constants
2
+ # The number of archives in the cache.
3
+ # @return [Integer]
4
+ ARCHIVE_COUNT = 0x9
5
+
6
+ # The size of a single index
7
+ # @return [Integer]
8
+ INDEX_SIZE = 0x6
9
+
10
+ # The size of a single data header
11
+ # @return [Integer]
12
+ HEADER_SIZE = 0x8
13
+
14
+ # The size of a chunk of data
15
+ # @return [Integer]
16
+ CHUNK_SIZE = 512
17
+
18
+ # The size of a single data block
19
+ # @return [Integer]
20
+ BLOCK_SIZE = HEADER_SIZE + CHUNK_SIZE;
21
+ end
@@ -0,0 +1,182 @@
1
+ module RuneRb::Cache
2
+ class FileSystem
3
+ include RuneRb::Core::Logging
4
+
5
+ # @attribute [r] cache
6
+ # @return [Hash<FileDescriptor, RuneRb::Cache::Archive>] a map of decoded archives.
7
+ attr_reader :cache
8
+
9
+ # @attribute [r] crc_table
10
+ # @return [RuneRb::Core::Buffer] the CRC table for the cache.
11
+ attr_reader :crc_table
12
+
13
+ # @attribute [r] crc
14
+ # @return [Array<Integer>] the CRC values for the cache.
15
+ attr_reader :crc
16
+
17
+ # @attribute [r] indicies
18
+ # @return [Array<StringIO>] the indicies for the cache.
19
+ attr_reader :indicies
20
+
21
+ # @attribute [r] data_file
22
+ # @return [StringIO] the data file for the cache.
23
+ attr_reader :data_file
24
+
25
+ # Constructs a new FileSystem instance.
26
+ # @param path [String] the path to the cache.
27
+ def initialize(path)
28
+ @indicies = Array.new
29
+ @crc_table = RuneRb::Core::Buffer.new(mode: 'r')
30
+ @crc = Array.new
31
+ @cache = Hash.new
32
+ @data_file = StringIO.new
33
+ read_layout(path)
34
+ end
35
+
36
+ # Retrieves an {RuneRb::Cache::Archive} by the specified {FileDescriptor}.
37
+ # @param type [Integer] the file type.
38
+ # @param file [Integer] the file identifier.
39
+ def archive(type, file)
40
+ descriptor = FileDescriptor.new(type, file)
41
+ cached = @cache[descriptor]
42
+
43
+ if cached == nil
44
+ file = cache_file(descriptor)
45
+ cached = RuneRb::Cache::Archive.decode(file)
46
+ @cache[descriptor] = cached
47
+ end
48
+
49
+ cached
50
+ end
51
+
52
+ # Retrieves a {RuneRb::Core::Buffer} that corresponds to the specified {FileDescriptor} in the cache.
53
+ # @param descriptor [FileDescriptor] the descriptor to retrieve.
54
+ # @raise [RuntimeError] if a Chunk id does not match what is expected during cache file read.
55
+ # @raise [RuntimeError] if a type does not match descriptor type during cache file read.
56
+ # @raise [RuntimeError] if a file identifier does not match descriptor file identifier during cache file read.
57
+ # @return [RuneRb::Core::Buffer] the buffer containing data that corresponds to the specified descriptor.
58
+ def cache_file(descriptor)
59
+ index = index_for(descriptor)
60
+ buffer = RuneRb::Core::Buffer.new(mode: 'r')
61
+
62
+ position = index.block * RuneRb::Cache::BLOCK_SIZE
63
+ read = 0
64
+ size = index.size
65
+ blocks = size / RuneRb::Cache::CHUNK_SIZE
66
+
67
+ if size % RuneRb::Cache::CHUNK_SIZE != 0
68
+ blocks += 1
69
+ end
70
+
71
+ info "Reading #{blocks} blocks from position #{position}."
72
+
73
+ blocks.times do |i|
74
+ @data_file.seek(position)
75
+ header = @data_file.read
76
+ header_data = header.unpack('C*')
77
+
78
+ position += RuneRb::Cache::HEADER_SIZE
79
+
80
+ next_file = header_data[0] << 8 | header_data[1]
81
+ current_chunk = header_data[2] << 8 | header_data[3]
82
+ next_block = header_data[4] << 16 | header_data[5] << 8 | header_data[6]
83
+ next_type = header_data[7]
84
+
85
+ raise "Chunk id mismatch! (Current #{current_chunk}, Expected #{i})" if current_chunk != i
86
+
87
+ chunk_size = size - read
88
+ chunk_size = RuneRb::Cache::CHUNK_SIZE if chunk_size > RuneRb::Cache::CHUNK_SIZE
89
+
90
+ @data_file.seek(position)
91
+ buffer << @data_file.read
92
+
93
+ read += chunk_size
94
+ position = next_block * RuneRb::Cache::BLOCK_SIZE
95
+
96
+ if size > read
97
+ raise "Next type (#{next_type}) does not match descriptor type (#{descriptor.type + 1})." if next_type != descriptor.type + 1
98
+ raise "Next file (#{next_file}) does not match descriptor file (#{descriptor.file})." if next_file != descriptor.file
99
+ end
100
+ end
101
+
102
+ info "Read #{buffer.length} from cache."
103
+
104
+ buffer
105
+ end
106
+
107
+ def index_for(descriptor)
108
+ idx = descriptor.type
109
+ raise "Index out of bounds. (#{idx})" if idx < 0 || idx >= @indicies.length
110
+
111
+ buffer = String.new
112
+ idx_file = @indicies[idx]
113
+ position = descriptor.file * RuneRb::Cache::INDEX_SIZE
114
+ info "Reading index from position #{position}"
115
+
116
+ if position >= 0 && (idx_file.length >= (position + RuneRb::Cache::INDEX_SIZE))
117
+ idx_file.seek(position, IO::SEEK_CUR)
118
+ buffer << idx_file.read
119
+ else
120
+ raise "Could not find index file at position #{position}."
121
+ end
122
+
123
+ info " Length: #{buffer.length}, Index data: #{buffer.bytes}"
124
+
125
+ RuneRb::Cache::Index.decode(buffer)
126
+ end
127
+
128
+ def close
129
+ @indicies.each(&:close)
130
+ @data_file.close
131
+ end
132
+
133
+ # The number of index files in the cache.
134
+ # @return [Integer] the number of index files in the cache.
135
+ def cache_count
136
+ @indicies.length
137
+ end
138
+
139
+ # The number of files in a cache.
140
+ # @param cache [Integer] the cache to check.
141
+ def file_count(cache)
142
+ (@indicies[cache].size / RuneRb::Core::INDEX_SIZE) - 1
143
+ end
144
+
145
+ # Reads the layout of the cache from the specified path.
146
+ # @param path [String] the path to the cache directory.
147
+ # @raise [RuntimeError] if the cache archive is not found.
148
+ def read_layout(path)
149
+ raise "Cache archive not found. Please install them into the #{path} directory." unless check_for_archives(path)
150
+
151
+ # Find how many index files exist
152
+ count = 0.upto(255).each do |i|
153
+ break i unless File.exist?(File.join(path, "main_file_cache.idx#{i}"))
154
+ end
155
+
156
+ # Gather file objects
157
+ @data_file = File.open(File.join(path, "main_file_cache.dat"), "r")
158
+
159
+ count.times do |i|
160
+ data = File.read("#{path}/main_file_cache.idx#{i}")
161
+ @indicies[i] = StringIO.new(data)
162
+ end
163
+ end
164
+
165
+ # Checks for the existence of cache archives in a path.
166
+ # @param path [String] the path to the cache directory.
167
+ def check_for_archives(path)
168
+ return false if path.nil?
169
+ return false unless File.directory?(path)
170
+ return false unless File.exist?(path)
171
+ return false unless File.readable?(path)
172
+ return false if Dir.empty?(path)
173
+ true
174
+ end
175
+
176
+ FileDescriptor = Struct.new(:type, :file) do
177
+ def equals(other)
178
+ other.file == file && other.type == type
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,37 @@
1
+ module RuneRb::Cache
2
+ # An instance of a {CacheIndex} points to a file in the `main_file_cache.dat` file.
3
+ class Index
4
+ include RuneRb::Core::Logging
5
+
6
+ # @!attribute [r] size
7
+ # @return [Integer] the size of the file.
8
+ # @note This attribute is read-only.
9
+ attr_reader :size
10
+
11
+ # @!attribute [r] block
12
+ # @return [Integer] the block of the file.
13
+ # @note This attribute is read-only.
14
+ attr_reader :block
15
+
16
+ # Constructs a new Cache Index given the block size and identifier.
17
+ # @param size [Integer] the size of the block file
18
+ # @param block [Integer] the first block of the file
19
+ def initialize(size, block)
20
+ @size = size
21
+ @block = block
22
+ end
23
+
24
+ # Decodes a buffer into an index.
25
+ # @param buffer [String] the buffer to decode.
26
+ def self.decode(buffer)
27
+ #raise "Unexpected buffer length. Buffer #{buffer.bytesize}, Expected: #{RuneRb::Core::INDEX_SIZE}" unless buffer.bytesize == RuneRb::Core::INDEX_SIZE
28
+
29
+ bytes = buffer.unpack('C*')
30
+ size = bytes[0] << 16 | bytes[1] << 8 | bytes[2]
31
+ block = bytes[3] << 16 | bytes[4] << 8 | bytes[5]
32
+ info "Decoded index: size: #{size}, block: #{block}"
33
+
34
+ RuneRb::Cache::Index.new(size, block)
35
+ end
36
+ end
37
+ end
data/lib/rune/common.rb CHANGED
@@ -35,6 +35,15 @@ module RuneRb
35
35
  autoload :SetRefinements, 'rune/patches/set_refinements'
36
36
  end
37
37
 
38
+ module Cache
39
+ autoload :Archive, 'rune/cache/archive'
40
+ autoload :Constants, 'rune/cache/constants'
41
+ autoload :FileSystem, 'rune/cache/file_system'
42
+ autoload :Index, 'rune/cache/index'
43
+
44
+ include RuneRb::Cache::Constants
45
+ end
46
+
38
47
  # The Logger utility for the RuneRb framework.
39
48
  # @return [Console::Logger] the logger instance.
40
49
  def self.logger
@@ -3,6 +3,11 @@ module RuneRb::Core
3
3
  # A Buffer encapsulates raw data in a String instance. Depending on the mode, the buffer can be read from or written to.
4
4
  class Buffer
5
5
 
6
+ # @!attribute [r] data
7
+ # @return [String] the data contained in the buffer.
8
+ # @note This attribute is read-only.
9
+ attr_reader :data
10
+
6
11
  # Constructs a new Buffer instance.
7
12
  # @param mode [String] the mode of the buffer.
8
13
  def initialize(mode: 'rw')
@@ -19,6 +19,10 @@ module RuneRb::Core::Constants
19
19
  # @return [Array<Integer>]
20
20
  BIT_MASK_OUT = (0...32).collect { (1 << _1) - 1 }.freeze
21
21
 
22
+ # The number of archives in the cache.
23
+ # @return [Integer]
24
+ ARCHIVE_COUNT = 0x9
25
+
22
26
  # The size of a single index
23
27
  # @return [Integer]
24
28
  INDEX_SIZE = 0x6
@@ -41,4 +45,4 @@ module RuneRb::Core::Constants
41
45
  BIG: [0, 1, 2].freeze,
42
46
  LITTLE: [2, 1, 0].freeze
43
47
  }.freeze
44
- end
48
+ end
@@ -10,11 +10,7 @@ module RuneRb::Core
10
10
  @cc = 0
11
11
  @mm = []
12
12
  @randrsl = Array.new(256, 0)
13
-
14
- seed.each_with_index do |element, i|
15
- @randrsl[i] = element
16
- end
17
-
13
+ seed.each_with_index { |element, i| @randrsl[i] = element }
18
14
  randinit
19
15
  end
20
16
 
@@ -52,18 +52,14 @@ module RuneRb::Core::WriteableBuffer
52
52
  # @param value [Integer] the medium value to write.
53
53
  # @param mutation [String] the mutation made to the byte.
54
54
  # @param order [String] the order in which bytes will be written.
55
- def write_int24(value, mutation: :STD, signed: false, order: :BIG)
55
+ def write_int24(value, mutation: :STD, order: :BIG)
56
56
  case order
57
57
  when :BIG
58
58
  write_byte(value >> 16)
59
59
  write_byte(value >> 8)
60
- write_byte(value, mutation: mutation, signed: signed)
61
- when :MIDDLE
62
- write_byte(value >> 8)
63
- write_byte(value, mutation: mutation, signed: signed)
64
- write_byte(value >> 16)
60
+ write_byte(value, mutation: mutation)
65
61
  when :LITTLE
66
- write_byte(value, mutation: mutation, signed: signed)
62
+ write_byte(value, mutation: mutation)
67
63
  write_byte(value >> 8)
68
64
  write_byte(value >> 16)
69
65
  else raise "Unrecognized byte order: #{order}"
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rrb-common
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick W.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-09 00:00:00.000000000 Z
11
+ date: 2024-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rbzip2
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.3'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: dotenv
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -156,6 +170,10 @@ executables: []
156
170
  extensions: []
157
171
  extra_rdoc_files: []
158
172
  files:
173
+ - lib/rune/cache/archive.rb
174
+ - lib/rune/cache/constants.rb
175
+ - lib/rune/cache/file_system.rb
176
+ - lib/rune/cache/index.rb
159
177
  - lib/rune/common.rb
160
178
  - lib/rune/core/archive.rb
161
179
  - lib/rune/core/buffer.rb
@@ -187,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
187
205
  - !ruby/object:Gem::Version
188
206
  version: '0'
189
207
  requirements: []
190
- rubygems_version: 3.4.10
208
+ rubygems_version: 3.5.3
191
209
  signing_key:
192
210
  specification_version: 4
193
211
  summary: Common utilities for RuneRb.