rrb-common 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 339ea3353a55193acc1cbe6fcb8dc51f9731f72e9ffffeb864c10f4167c1cd84
4
+ data.tar.gz: eff3b5a43e2efaed07990b15be1dfb42547bfbdc16cd980f6589f193cc91b258
5
+ SHA512:
6
+ metadata.gz: 7e2a4ccef86a0fbea08fc8c2ab5a143e350225df42d6d1a8ca56e1d97723429c8294fc2c1802c5dbde2b683e7c5f09e88989f829e0ef73a8c23b03e6d0a2083d
7
+ data.tar.gz: 58aca74385f3e52b34d9252954481ddc388bcadd47b2203a58ca46033db0f851efba59fc6fb11193f3e9ad7726d6cbe2155b0f328e31c7b1f105d41374566725
@@ -0,0 +1,75 @@
1
+ module RuneRb::Network
2
+
3
+ # A Buffer encapsulates raw data in a String instance. Depending on the mode, the buffer can be read from or written to.
4
+ class Buffer
5
+
6
+ # Constructs a new Buffer instance.
7
+ # @param capacity [Integer] the capacity of the buffer.
8
+ # @param mode [String] the mode of the buffer.
9
+ def initialize(mode: 'rw')
10
+ @data = String.new
11
+ @mode = mode
12
+ raise StandardError, 'Buffer mode must include "r" or "w".' unless @mode.include?('r') || @mode.include?('w')
13
+
14
+ enable_readable if @mode.include?('r')
15
+ enable_writeable if @mode.include?('w')
16
+ end
17
+
18
+ # Returns a snapshot of the buffer.
19
+ # @return [String] a snapshot of the buffer.
20
+ def snapshot
21
+ @data.dup
22
+ end
23
+
24
+ # Returns the limit of the buffer.
25
+ # @return [Integer] the limit of the buffer.
26
+ def length
27
+ @data.bytesize
28
+ end
29
+
30
+ # Adds raw data to the buffer. Flips the buffer if it is readable.
31
+ # @param data [String] the data to add.
32
+ def <<(data)
33
+ @data << data
34
+ end
35
+
36
+ # Is the <Buffer> instance readable?
37
+ # @return [Boolean] true if the <Buffer> instance is readable, false otherwise.
38
+ def readable?
39
+ @mode.include?('r')
40
+ end
41
+
42
+ # Is the <Buffer> instance writeable?
43
+ # @return [Boolean] true if the <Buffer> instance is writeable, false otherwise.
44
+ def writeable?
45
+ @mode.include?('w')
46
+ end
47
+
48
+ # Mutates the value according to the passed mutation
49
+ # @param value [Integer] the value to mutate
50
+ # @param mutation [Symbol] the mutation to apply to the value.
51
+ def mutate(value, mutation)
52
+ case mutation
53
+ when :STD then value
54
+ when :ADD then value + 128
55
+ when :NEG then -value
56
+ when :SUB then value - 128
57
+ else mutate(value, :STD)
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ # Enables read functions on the buffer instance. Bit Access is disabled by default. Sets the bit position to 0.
64
+ def enable_readable
65
+ singleton_class.include(RuneRb::Network::Readable)
66
+ @bit_access = false
67
+ @bit_position = 0
68
+ end
69
+
70
+ # Enables write functions on the buffer instance.
71
+ def enable_writeable
72
+ singleton_class.include(RuneRb::Network::Writeable)
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,21 @@
1
+ module RuneRb::Network::Constants
2
+ # Acceptable byte orders in which multi-byte values can be read.
3
+ # @return [Array<Symbol>]
4
+ BYTE_ORDERS = %i[BIG MIDDLE INVERSE_MIDDLE LITTLE].freeze
5
+
6
+ # The size of one byte
7
+ # @return [Integer]
8
+ BYTE_SIZE = 8
9
+
10
+ # Valid byte mutations
11
+ # @return [Array<Symbol>]
12
+ BYTE_MUTATIONS = %i[ADD NEG SUB STD].freeze
13
+
14
+ # Valid types for reading/writing
15
+ # @return [Array<Symbol>]
16
+ RW_TYPES = %i[bits bit byte bytes medium int long reverse_bytes short smart string].freeze
17
+
18
+ # Bit masks for bit packing
19
+ # @return [Array<Integer>]
20
+ BIT_MASK_OUT = (0...32).collect { (1 << _1) - 1 }.freeze
21
+ end
@@ -0,0 +1,219 @@
1
+ module RuneRb::Network
2
+ # An implementation of an ISAAC cipher used to generate random numbers for message interchange.
3
+ class ISAAC
4
+ using RuneRb::Patches::IntegerRefinements
5
+
6
+ # Called when a new ISAAC Cipher is created.
7
+ def initialize(seed)
8
+ @aa = 0
9
+ @bb = 0
10
+ @cc = 0
11
+ @mm = []
12
+ @randrsl = Array.new(256, 0)
13
+
14
+ seed.each_with_index do |element, i|
15
+ @randrsl[i] = element
16
+ end
17
+
18
+ randinit
19
+ end
20
+
21
+ # Gets the next random value.
22
+ # If 256 cycles have occurred, the results array is regenerated.
23
+ def next_value
24
+ if @randcnt.zero?
25
+ isaac
26
+ @randcnt = 256
27
+ end
28
+ @randcnt -= 1
29
+ @randrsl[@randcnt].signed(:i)
30
+ end
31
+
32
+ private
33
+
34
+ # Generates 256 new results.
35
+ def isaac
36
+ r = @randrsl
37
+ aa = @aa
38
+ @cc += 1
39
+ bb = (@bb + (@cc)) & 0xffffffff
40
+ x = y = 0
41
+
42
+ (0...256).step(4) do |i|
43
+ x = @mm[i]
44
+ aa = ((aa ^ (aa << 13)) + @mm[(i + 128) & 0xff])
45
+ aa &= 0xffffffff
46
+ @mm[i] = y = (@mm[(x >> 2) & 0xff] + aa + bb) & 0xffffffff
47
+ r[i] = bb = (@mm[(y >> 10) & 0xff] + x) & 0xffffffff
48
+ x = @mm[i + 1]
49
+ aa = ((aa ^ (0x03ffffff & (aa >> 6))) + @mm[(i + 1 + 128) & 0xff])
50
+ aa &= 0xffffffff
51
+ @mm[i + 1] = y = (@mm[(x >> 2) & 0xff] + aa + bb) & 0xffffffff
52
+ r[i + 1] = bb = (@mm[(y >> 10) & 0xff] + x) & 0xffffffff
53
+ x = @mm[i + 2]
54
+ aa = ((aa ^ (aa << 2)) + @mm[(i + 2 + 128) & 0xff])
55
+ aa &= 0xffffffff
56
+ @mm[i + 2] = y = (@mm[(x >> 2) & 0xff] + aa + bb) & 0xffffffff
57
+ r[i + 2] = bb = (@mm[(y >> 10) & 0xff] + x) & 0xffffffff
58
+ x = @mm[i + 3]
59
+ aa = ((aa ^ (0x0000ffff & (aa >> 16))) + @mm[(i + 3 + 128) & 0xff])
60
+ aa &= 0xffffffff
61
+ @mm[i + 3] = y = (@mm[(x >> 2) & 0xff] + aa + bb) & 0xffffffff
62
+ r[i + 3] = bb = (@mm[(y >> 10) & 0xff] + x) & 0xffffffff
63
+ end
64
+
65
+ @bb = bb
66
+ @aa = aa
67
+ end
68
+
69
+ # Initializes the memory array.
70
+ def randinit
71
+ c = d = e = f = g = h = j = k = 0x9e3779b9
72
+ r = @randrsl
73
+
74
+ 4.times do
75
+ c = c ^ (d << 11)
76
+ f += c
77
+ d += e
78
+ d = d ^ (0x3fffffff & (e >> 2))
79
+ g += d
80
+ e += f
81
+ e = e ^ (f << 8)
82
+ h += e
83
+ f += g
84
+ f = f ^ (0x0000ffff & (g >> 16))
85
+ j += f
86
+ g += h
87
+ g = g ^ (h << 10)
88
+ k += g
89
+ h += j
90
+ h = h ^ (0x0fffffff & (j >> 4))
91
+ c += h
92
+ j += k
93
+ j = j ^ (k << 8)
94
+ d += j
95
+ k += c
96
+ k = k ^ (0x007fffff & (c >> 9))
97
+ e += k
98
+ c += d
99
+ end
100
+
101
+ (0...256).step(8) do |i|
102
+ c += r[i]
103
+ d += r[i + 1]
104
+ e += r[i + 2]
105
+ f += r[i + 3]
106
+ g += r[i + 4]
107
+ h += r[i + 5]
108
+ j += r[i + 6]
109
+ k += r[i + 7]
110
+ c = c ^ (d << 11)
111
+ f += c
112
+ d += e
113
+ d = d ^ (0x3fffffff & (e >> 2))
114
+ g += d
115
+ e += f
116
+ e = e ^ (f << 8)
117
+ h += e
118
+ f += g
119
+ f = f ^ (0x0000ffff & (g >> 16))
120
+ j += f
121
+ g += h
122
+ g = g ^ (h << 10)
123
+ k += g
124
+ h += j
125
+ h = h ^ (0x0fffffff & (j >> 4))
126
+ c += h
127
+ j += k
128
+ j = j ^ (k << 8)
129
+ d += j
130
+ k += c
131
+ k = k ^ (0x007fffff & (c >> 9))
132
+ e += k
133
+ c += d
134
+ @mm[i] = c
135
+ @mm[i + 1] = d
136
+ @mm[i + 2] = e
137
+ @mm[i + 3] = f
138
+ @mm[i + 4] = g
139
+ @mm[i + 5] = h
140
+ @mm[i + 6] = j
141
+ @mm[i + 7] = k
142
+ end
143
+
144
+ (0...256).step(8) do |i|
145
+ c += @mm[i]
146
+ d += @mm[i + 1]
147
+ e += @mm[i + 2]
148
+ f += @mm[i + 3]
149
+ g += @mm[i + 4]
150
+ h += @mm[i + 5]
151
+ j += @mm[i + 6]
152
+ k += @mm[i + 7]
153
+ c = c ^ (d << 11)
154
+ f += c
155
+ d += e
156
+ d = d ^ (0x3fffffff & (e >> 2))
157
+ g += d
158
+ e += f
159
+ e = e ^ (f << 8)
160
+ h += e
161
+ f += g
162
+ f = f ^ (0x0000ffff & (g >> 16))
163
+ j += f
164
+ g += h
165
+ g = g ^ (h << 10)
166
+ k += g
167
+ h += j
168
+ h = h ^ (0x0fffffff & (j >> 4))
169
+ c += h
170
+ j += k
171
+ j = j ^ (k << 8)
172
+ d += j
173
+ k += c
174
+ k = k ^ (0x007fffff & (c >> 9))
175
+ e += k
176
+ c += d
177
+ @mm[i] = c
178
+ @mm[i + 1] = d
179
+ @mm[i + 2] = e
180
+ @mm[i + 3] = f
181
+ @mm[i + 4] = g
182
+ @mm[i + 5] = h
183
+ @mm[i + 6] = j
184
+ @mm[i + 7] = k
185
+ end
186
+
187
+ isaac
188
+ @randcnt = 256
189
+ end
190
+ end
191
+ end
192
+
193
+ # Copyright (c) 2021, Patrick W.
194
+ # All rights reserved.
195
+ #
196
+ # Redistribution and use in source and binary forms, with or without
197
+ # modification, are permitted provided that the following conditions are met:
198
+ #
199
+ # * Redistributions of source code must retain the above copyright notice, this
200
+ # list of conditions and the following disclaimer.
201
+ #
202
+ # * Redistributions in binary form must reproduce the above copyright notice,
203
+ # this list of conditions and the following disclaimer in the documentation
204
+ # and/or other materials provided with the distribution.
205
+ #
206
+ # * Neither the name of the copyright holder nor the names of its
207
+ # contributors may be used to endorse or promote products derived from
208
+ # this software without specific prior written permission.
209
+ #
210
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
211
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
212
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
213
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
214
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
215
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
216
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
217
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
218
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
219
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,220 @@
1
+ # The Readable module contains the functions used to read data from a {Buffer} object.
2
+ module RuneRb::Network::Readable
3
+ using RuneRb::Patches::IntegerRefinements
4
+
5
+ # @!attribute [r] bit_access
6
+ # @return [Boolean] is {bit_access} enabled?
7
+ attr_reader :bit_access
8
+
9
+ # @!attribute [r] bit_position
10
+ # @return [Integer] the current bit position.
11
+ attr_reader :bit_position
12
+
13
+
14
+ # Read data from the payload according to the option parameter.
15
+ # @param type [Symbol] the type of database to read
16
+ # @param mutation [Symbol] an option mutation to apply to the read value.
17
+ def read(type: :byte, signed: false, mutation: :STD, order: :BIG, options: nil)
18
+ case type
19
+ when :bits then read_bits(options[:amount])
20
+ when :byte then read_byte(signed:, mutation:)
21
+ when :bytes then read_bytes(options[:amount] || 1, mutation:)
22
+ when :short then read_short(signed:, mutation:, order:)
23
+ when :int24 then read_int24(signed:, mutation:, order:)
24
+ when :int then read_int(signed:, mutation:, order:)
25
+ when :long then read_long(signed:, mutation:, order:)
26
+ when :smart then read_smart(signed:, mutation:)
27
+ when :string then read_string
28
+ when :reverse_bytes then read_bytes_reverse(options[:amount] || 1, mutation:)
29
+ else raise "Unrecognized read type! #{type}"
30
+ end
31
+ end
32
+
33
+ # Enables or Disables bit reading by setting the {Buffer#bit_access} variable.
34
+ def switch_access
35
+ @bit_access = !@bit_access
36
+ end
37
+
38
+ # Completes a bit access by setting the {Buffer#bit_position} to the start of the next byte, then toggling {bit_access}.
39
+ def finish_access
40
+ @bit_position = (@bit_position + 7) / 8
41
+ switch_access
42
+ end
43
+
44
+ private
45
+
46
+ # Read multiple bytes from the {Buffer#data}
47
+ # @param amount [Integer] the amount of bytes to read
48
+ # @param mutation [Symbol] the mutation to apply to read bytes.
49
+ def read_bytes(amount, mutation)
50
+ amount.times.each_with_object([]) { |_idx, arr| arr << read_byte(signed: false, mutation:) }
51
+ end
52
+
53
+ # Probably did this wrong
54
+ # @param amount [Integer] the amount of bytes to read
55
+ # @param mutation [Symbol] an optional mutation to apply to the result.
56
+ def read_bytes_reverse(amount, mutation)
57
+ @data.flip
58
+ value = amount.times.each_with_object([]) { value << read_byte(signed: false, mutation:) }
59
+ @data.flip
60
+ value
61
+ end
62
+
63
+ # Read a byte value from the {Buffer#data}
64
+ # @param signed [Boolean] should the value be signed.
65
+ # @param mutation [Symbol] mutation that should be applied to the byte value.
66
+ # @return [Integer] the read byte value.
67
+ def read_byte(mutation: :STD, signed: false)
68
+ directive = signed ? 'c' : 'C'
69
+ value = @data.slice!(0).unpack1(directive)
70
+ mutate(value, mutation)
71
+ end
72
+
73
+ # Reads a short value from the {Buffer#data}
74
+ # @param signed [Boolean] should the value be signed.
75
+ # @param mutation [String] mutation that should be applied to the short value
76
+ # @param order [Symbol] they byte order to read the short value
77
+ def read_short(signed: false, mutation: :STD, order: :BIG)
78
+ directive = "#{signed ? 's' : 'S'}"
79
+ directive << case order
80
+ when :BIG then '>'
81
+ when :LITTLE then '<'
82
+ else ''
83
+ end
84
+ value = @data.slice!(0..1).unpack1(directive)
85
+ mutate(value, mutation)
86
+ end
87
+
88
+ # Reads a 24-Bit Integer value from the {Buffer#data}
89
+ # @param signed [Boolean] should the value be signed.
90
+ # @param mutation [Symbol] mutation that should be applied to the value
91
+ # @param order [String] they byte order to read the value
92
+ def read_int24(signed: false, mutation: :STD, order: :BIG)
93
+ unpacked = @data.slice!(0..2).unpack('C3')
94
+ case order
95
+ when :BIG
96
+ if signed
97
+ value = (unpacked[0] << 16) | (unpacked[1] << 8) | unpacked[2]
98
+ unpacked[0] & 0x80 != 0 ? value - 0x10000 : value
99
+ else
100
+ (unpacked[0] << 16) | (unpacked[1] << 8) | unpacked[2]
101
+ end
102
+ when :MIDDLE
103
+ if signed
104
+ value = (unpacked[1] << 16) | (unpacked[2] << 8) | unpacked[0]
105
+ unpacked[1] & 0x80 != 0 ? value - 0x10000 : value
106
+ else
107
+ (unpacked[1] << 16) | (unpacked[2] << 8) | unpacked[0]
108
+ end
109
+ when :LITTLE
110
+ if signed
111
+ value = (unpacked[2] << 16) | (unpacked[1] << 8) | unpacked[0]
112
+ unpacked[0] & 0x80 != 0 ? value - 0x10000 : value
113
+ else
114
+ (unpacked[2] << 16) | (unpacked[1] << 8) | unpacked[0]
115
+ end
116
+ else read_int24(signed:, mutation:, order: :BIG)
117
+ end
118
+ end
119
+
120
+ # Reads a integer value from the {Buffer#data}
121
+ # @param signed [Boolean] should the value be signed.
122
+ # @param mutation [Symbol] mutation that should be applied to the integer value
123
+ # @param order [String] they byte order to read the integer value
124
+ def read_int(signed: false, mutation: :STD, order: :BIG)
125
+ case order
126
+ when :BIG
127
+ directive = signed ? 'l>' : 'L>'
128
+ value = @data.slice!(0..3).unpack1(directive)
129
+ mutate(value, mutation)
130
+ when :MIDDLE
131
+ (read_byte(signed:) << 8) | read_byte(signed:, mutation:) | (read_byte(signed:) << 24) | (read_byte(signed:) << 16)
132
+ when :INVERSE_MIDDLE
133
+ (read_byte(signed:) << 16) | (read_byte(signed:) << 24) | read_byte(signed:, mutation:) | (read_byte(signed:) << 8)
134
+ when :LITTLE
135
+ directive = signed ? 'l<' : 'L<'
136
+ value = @data.slice!(0..3).unpack1(directive)
137
+ mutate(value, mutation)
138
+ else read_int(signed:, mutation:, order: :BIG)
139
+ end
140
+ end
141
+
142
+ # Reads a long value from the {Buffer#data}
143
+ # @param signed [Boolean] should the value be signed.
144
+ # @param mutation [Symbol] mutation that should be applied to the long value
145
+ # @param order [String] they byte order to read the long value
146
+ def read_long(signed: false, mutation: :STD, order: :BIG)
147
+ case order
148
+ when :BIG
149
+ directive = signed ? 'q>' : 'Q>'
150
+ value = @data.slice!(0..7).unpack1(directive)
151
+ mutate(value, mutation)
152
+ when :LITTLE
153
+ directive = signed ? 'q<' : 'Q<'
154
+ value = @data.slice!(0..7).unpack1(directive)
155
+ mutate(value, mutation)
156
+ else read_long(signed:, mutation:, order: :BIG)
157
+ end
158
+ end
159
+
160
+ # Read a smart value from the {Buffer#data}
161
+ # @param signed [Boolean] should the value be signed.
162
+ # @param mutation [Symbol] mutation that should be applied to the long value
163
+ def read_smart(signed: false, mutation: :STD)
164
+ peek = read_byte(signed:, mutation:)
165
+
166
+ if signed
167
+ if peek < 128
168
+ read_byte(signed:, mutation:) - 64
169
+ else
170
+ read_short(signed:, mutation:, order: :BIG) - 49_152
171
+ end
172
+ else
173
+ if peek < 128
174
+ read_byte(mutation:, signed:)
175
+ else
176
+ read_short(mutation:, signed:, order: :BIG) - 32_768
177
+ end
178
+ end
179
+ end
180
+
181
+ # Reads a string from the {Buffer#data}
182
+ # @return [String] the resulting string.
183
+ def read_string
184
+ val = ''
185
+ while (res = @data.slice!(0))
186
+ break if res == "\n"
187
+
188
+ val << res
189
+ end
190
+ val
191
+ end
192
+ end
193
+
194
+ # Copyright (c) 2021, Patrick W.
195
+ # All rights reserved.
196
+ #
197
+ # Redistribution and use in source and binary forms, with or without
198
+ # modification, are permitted provided that the following conditions are met:
199
+ #
200
+ # * Redistributions of source code must retain the above copyright notice, this
201
+ # list of conditions and the following disclaimer.
202
+ #
203
+ # * Redistributions in binary form must reproduce the above copyright notice,
204
+ # this list of conditions and the following disclaimer in the documentation
205
+ # and/or other materials provided with the distribution.
206
+ #
207
+ # * Neither the name of the copyright holder nor the names of its
208
+ # contributors may be used to endorse or promote products derived from
209
+ # this software without specific prior written permission.
210
+ #
211
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
212
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
213
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
214
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
215
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
216
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
217
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
218
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
219
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
220
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,224 @@
1
+ # The Writeable module contains functions for writing data to a {Buffer} object.
2
+ module RuneRb::Network::Writeable
3
+
4
+ # Write data to the payload.
5
+ # @param value [Integer, String, Message, Array] the value to write.
6
+ # @param type [Symbol] the type of value to write.
7
+ # @param mutation [Symbol] an option mutation to apply to the value.
8
+ # @param order [Symbol] the byte order to write the value.
9
+ def write(value, type: :byte, mutation: :STD, signed: false, order: :BIG, options: {})
10
+ case type
11
+ when :bits then write_bits(value, options[:amount] || 1)
12
+ when :bit then write_bit(value)
13
+ when :byte then write_byte(value, mutation: mutation)
14
+ when :bytes then write_bytes(value)
15
+ when :short then write_short(value, mutation: mutation, order: order)
16
+ when :int24 then write_int24(value, mutation: mutation, order: order)
17
+ when :int then write_int(value, mutation: mutation, order: order)
18
+ when :long then write_long(value, mutation: mutation, order: order)
19
+ when :smart then write_smart(value, mutation: mutation, signed: signed)
20
+ when :string then write_string(value)
21
+ when :reverse_bytes then write_reverse_bytes(value)
22
+ else raise "Unrecognized write type! #{type}"
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ # Write a byte value to the payload.
29
+ # @param value [Integer] the byte value to write.
30
+ # @param mutation [String] mutations made to the byte.
31
+ def write_byte(value, mutation: :STD, signed: false)
32
+ @data << [mutate(value, mutation)].pack(signed ? 'c' : 'C')
33
+ end
34
+
35
+ # Write a short value to the payload.
36
+ # @param value [Integer] the short value to write.
37
+ # @param mutation [String] the type of byte to write.
38
+ # @param order [String] the order in which bytes will be written.
39
+ def write_short(value, mutation: :STD, signed: false, order: :BIG)
40
+ case order
41
+ when :BIG
42
+ write_byte(value >> 8)
43
+ write_byte(value, mutation: mutation, signed: signed)
44
+ when :LITTLE
45
+ write_byte(value, mutation: mutation, signed: signed)
46
+ write_byte(value >> 8)
47
+ else raise "Unrecognized bit order: #{order}"
48
+ end
49
+ end
50
+
51
+ # Write a int24 value to the payload.
52
+ # @param value [Integer] the medium value to write.
53
+ # @param mutation [String] the mutation made to the byte.
54
+ # @param order [String] the order in which bytes will be written.
55
+ def write_int24(value, mutation: :STD, signed: false, order: :BIG)
56
+ case order
57
+ when :BIG
58
+ write_byte(value >> 16)
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)
65
+ when :LITTLE
66
+ write_byte(value, mutation: mutation, signed: signed)
67
+ write_byte(value >> 8)
68
+ write_byte(value >> 16)
69
+ else raise "Unrecognized byte order: #{order}"
70
+ end
71
+ end
72
+
73
+ # Write a integer value to the payload.
74
+ # @param value [Integer] the integer value to write.
75
+ # @param mutation [String] the type of byte to write.
76
+ # @param order [String] the order in which bytes will be written.
77
+ def write_int(value, mutation: :STD, signed: false, order: :BIG)
78
+ case order
79
+ when :BIG
80
+ write_byte(value >> 24)
81
+ write_byte(value >> 16)
82
+ write_byte(value >> 8)
83
+ write_byte(value, mutation: mutation, signed: signed)
84
+ when :MIDDLE
85
+ write_byte(value >> 8)
86
+ write_byte(value, mutation: mutation, signed: signed)
87
+ write_byte(value >> 24)
88
+ write_byte(value >> 16)
89
+ when :INVERSE_MIDDLE
90
+ write_byte(value >> 16)
91
+ write_byte(value >> 24)
92
+ write_byte(value, mutation: mutation, signed: signed)
93
+ write_byte(value >> 8)
94
+ when :LITTLE
95
+ write_byte(value, mutation: mutation, signed: signed)
96
+ write_byte(value >> 8)
97
+ write_byte(value >> 16)
98
+ write_byte(value >> 24)
99
+ else raise "Unrecognized byte order: #{order}"
100
+ end
101
+ end
102
+
103
+ # Write a long value to the payload.
104
+ # @param value [Integer] the long value to write.
105
+ # @param mutation [String] the type of byte to write.
106
+ # @param order [String] the order in which bytes will be written.
107
+ def write_long(value, mutation: :STD, signed: false, order: :BIG)
108
+ case order
109
+ when :BIG
110
+ (RuneRb::Network::BYTE_SIZE * 7).downto(0) { |div| ((div % 8).zero? and div.positive?) ? write_byte(value >> div) : next }
111
+ write_byte(value, mutation: mutation, signed: signed)
112
+ when :LITTLE
113
+ write_byte(value, mutation: mutation, signed: signed)
114
+ (0).upto(RuneRb::Network::BYTE_SIZE * 7) { |div| ((div % 8).zero? and div.positive?) ? write_byte(value >> div) : next }
115
+ else raise "Unrecognized byte order: #{order}"
116
+ end
117
+ end
118
+
119
+ # Write a string value to the payload. This will be escaped/terminated with a \n[10] value.
120
+ # @param string [String, StringIO] the byte to write to the payload.
121
+ def write_string(string)
122
+ send(:<<, string)
123
+ send(:<<, [10].pack('C'))
124
+ end
125
+
126
+ # Write a 'smart' value to the payload.
127
+ #
128
+ # @param value [Integer] the smart value to write.
129
+ # @param mutation [String] an optional mutation to apply to the written smart value.
130
+ def write_smart(value, mutation: :STD, signed: false)
131
+ case signed
132
+ when true
133
+ value > 128 ? write_byte(value + 64, mutation: mutation, signed: signed) : write_short(value + 49_152, mutation: mutation, signed: signed)
134
+ when false
135
+ value > 128 ? write_byte(value, mutation: mutation, signed: signed) : write_short(value + 32_768, mutation: mutation, signed: signed)
136
+ end
137
+ end
138
+
139
+ # Writes multiple bytes to the payload.
140
+ # @param values [String, Array, Rune::Network::Buffer] the values whose bytes will be written.
141
+ def write_bytes(values)
142
+ case values
143
+ when Array then values.each { |byte| write_byte(byte.to_i) }
144
+ when RuneRb::Network::Packet then send(:put, values.snapshot)
145
+ when RuneRb::Network::Buffer then send(:put, values)
146
+ when String then send(:<<, values)
147
+ end
148
+ end
149
+
150
+ # Write a collection of bytes in reverse. *Not sure if I did this right.
151
+ # @param values [Array, String] the values to write.
152
+ def write_reverse_bytes(values)
153
+ case values
154
+ when Array then write(values.reverse, type: :bytes)
155
+ when String then write(values.bytes.reverse, type: :bytes)
156
+ end
157
+ end
158
+
159
+ # Write a single bit with a value of 1 or 0 depending on the flag parameter.
160
+ # @param flag [Boolean] the flag
161
+ def write_bit(flag)
162
+ write_bits(flag == true ? 1 : 0, 1)
163
+ self
164
+ end
165
+
166
+ # Write multiple bits to the payload
167
+ # @param amount [Integer] the amount of bits to occupy.
168
+ # @param value [Integer] the value to write.
169
+ def write_bits(value, amount)
170
+ byte_pos = @bit_position >> 3
171
+ bit_offset = 8 - (@bit_position & 7)
172
+ @bit_position += amount
173
+
174
+ while amount > bit_offset
175
+ @buffer[byte_pos] = [0].pack('c') if @buffer[byte_pos].nil?
176
+ @buffer[byte_pos] = [(@buffer[byte_pos].unpack1('c') & ~RuneRb::Network::BIT_MASK_OUT[bit_offset])].pack('c')
177
+ @buffer[byte_pos] = [(@buffer[byte_pos].unpack1('c') | (value >> (amount - bit_offset)) & RuneRb::Network::BIT_MASK_OUT[bit_offset])].pack('c')
178
+ byte_pos += 1
179
+ amount -= bit_offset
180
+ bit_offset = 8
181
+ end
182
+
183
+ @buffer[byte_pos] = [0].pack('c') if @buffer[byte_pos].nil?
184
+
185
+ if amount == bit_offset
186
+ @buffer[byte_pos] = [(@buffer[byte_pos].unpack1('c') & ~RuneRb::Network::BIT_MASK_OUT[bit_offset])].pack('c')
187
+ @buffer[byte_pos] = [(@buffer[byte_pos].unpack1('c') | (value & Rune::Network::BIT_MASK_OUT[bit_offset]))].pack('c')
188
+ else
189
+ @buffer[byte_pos] = [(@buffer[byte_pos].unpack1('c') & ~(RuneRb::Network::BIT_MASK_OUT[amount] << (bit_offset - amount)))].pack('c')
190
+ @buffer[byte_pos] = [(@buffer[byte_pos].unpack1('c') | ((value & RuneRb::Network::BIT_MASK_OUT[amount]) << (bit_offset - amount)))].pack('c')
191
+ end
192
+ end
193
+ end
194
+
195
+ ############################################################################################################
196
+ # Copyright (c) 2023, Patrick W. #
197
+ # All rights reserved. #
198
+ # #
199
+ # Redistribution and use in source and binary forms, with or without #
200
+ # modification, are permitted provided that the following conditions are met: #
201
+ # #
202
+ # * Redistributions of source code must retain the above copyright notice, this #
203
+ # list of conditions and the following disclaimer. #
204
+ # #
205
+ # * Redistributions in binary form must reproduce the above copyright notice, #
206
+ # this list of conditions and the following disclaimer in the documentation #
207
+ # and/or other materials provided with the distribution. #
208
+ # #
209
+ # * Neither the name of the copyright holder nor the names of its #
210
+ # contributors may be used to endorse or promote products derived from #
211
+ # this software without specific prior written permission. #
212
+ # #
213
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #
214
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #
215
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE #
216
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE #
217
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL #
218
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR #
219
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER #
220
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, #
221
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE #
222
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #
223
+ # #
224
+ ############################################################################################################
@@ -0,0 +1,123 @@
1
+ # A module adding overflow functions to integers to mimic the behavior of Java primitive overflow behavior.
2
+ module RuneRb::Patches::IntegerRefinements
3
+ refine Integer do
4
+ # Returns a binary representation in the form of an array of 1's and 0's in their respective digits.
5
+ # @return [Array] the binary representation
6
+ def binary_representation
7
+ to_s(2).chars.map(&:to_i)
8
+ end
9
+
10
+ alias_method :brep, :binary_representation
11
+
12
+ # Returns a base 10 numeric from the passed array representation
13
+ # @param representation [Array] the representation used to generate the numeric
14
+ # @returns [Integer] the base 10 numeric of the representation.
15
+ def from_binary_rep(representation)
16
+ res = 0
17
+ representation.each_with_index do |bit, idx|
18
+ res += bit * (2**idx)
19
+ end
20
+ res
21
+ end
22
+
23
+ alias_method :from_brep, :from_binary_rep
24
+
25
+ # Adjusts the value of the Integer to be unsigned.
26
+ # @param type [Symbol] the type of primitive the value will be returned as
27
+ def unsigned(type)
28
+ return 0 if negative?
29
+ case type
30
+ when :Byte, :byte, :b, :B then to_i > 0xFF ? 0xFF : to_i
31
+ when :Short, :short, :s, :S then to_i > 0xFFFF ? 0xFFFF : to_i
32
+ when :Integer, :Int, :int, :integer, :i, :I then to_i > 0xFFFFFFFF ? 0xFFFFFFFF : to_i
33
+ when :Long, :long, :l, :L then to_i > 0xFFFFFFFFFFFFFFFF ? 0xFFFFFFFFFFFFFFFF : to_i
34
+ else unsigned(:int)
35
+ end
36
+ end
37
+
38
+ alias_method :u, :unsigned
39
+
40
+ # Adjusts the value of the Integer to be signed.
41
+ # @param type [Symbol] the type of primitive the value will be returned as
42
+ def signed(type)
43
+ case type
44
+ when :Byte, :byte, :b, :B then adjust(:byte)
45
+ when :Short, :short, :s, :S then adjust(:short)
46
+ when :Integer, :Int, :int, :integer, :i, :I then adjust(:integer)
47
+ when :Long, :long, :l, :L then adjust(:long)
48
+ else adjust(:integer)
49
+ end
50
+ end
51
+
52
+ alias_method :s, :signed
53
+
54
+ def nibble
55
+ adjust(:nibble)
56
+ end
57
+
58
+ # Returns a string with a formatted representation of the Integer as a timestamp.
59
+ def to_ftime
60
+ mm, ss = divmod(60)
61
+ hh, mm = mm.divmod(60)
62
+ dd, hh = hh.divmod(24)
63
+ format('%d days, %d hours, %d minutes, and %d seconds', dd, hh, mm, ss)
64
+ end
65
+
66
+ private
67
+
68
+ # Adjusts the integer based on the passed type
69
+ # @param type [Symbol] the type of adjustment to make to the integer.
70
+ def adjust(type)
71
+ case type
72
+ when :Byte, :byte, :b, :B
73
+ primitive_max = 2**7 - 1
74
+ primitive_min = -2**7
75
+ when :Short, :short, :s, :S
76
+ primitive_max = 2**15 - 1
77
+ primitive_min = -2**15
78
+ when :Integer, :Int, :int, :i, :I
79
+ primitive_max = 2**31 - 1
80
+ primitive_min = -2**31
81
+ when :Long, :long, :l, :L
82
+ primitive_max = 2**63 - 1
83
+ primitive_min = -2**63
84
+ when :Nibble, :nibble, :n, :N
85
+ primitive_max = 2**4
86
+ primitive_min = -2**4
87
+ else
88
+ primitive_max = 2**31 - 1
89
+ primitive_min = -2**31
90
+ end
91
+ self < -primitive_max ? -1 * (-self & primitive_max) : self
92
+ self > primitive_min ? (self & primitive_max) : self
93
+ end
94
+ end
95
+ end
96
+
97
+ # Copyright (c) 2021, Patrick W.
98
+ # All rights reserved.
99
+ #
100
+ # Redistribution and use in source and binary forms, with or without
101
+ # modification, are permitted provided that the following conditions are met:
102
+ #
103
+ # * Redistributions of source code must retain the above copyright notice, this
104
+ # list of conditions and the following disclaimer.
105
+ #
106
+ # * Redistributions in binary form must reproduce the above copyright notice,
107
+ # this list of conditions and the following disclaimer in the documentation
108
+ # and/or other materials provided with the distribution.
109
+ #
110
+ # * Neither the name of the copyright holder nor the names of its
111
+ # contributors may be used to endorse or promote products derived from
112
+ # this software without specific prior written permission.
113
+ #
114
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
115
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
116
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
117
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
118
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
119
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
120
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
121
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
122
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
123
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,43 @@
1
+ # Refinements made to the Set class of the ruby Core module.
2
+ module RuneRb::Patches::SetRefinements
3
+ refine Set do
4
+ # Consumes elements as they're passed to execution block.
5
+ # @param _ [Proc] the execution block
6
+ def each_consume(&_)
7
+ raise 'Nil block passed to Set#each_consume.' unless block_given?
8
+
9
+ each do |item|
10
+ yield(item)
11
+ delete(item)
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ # Copyright (c) 2021, Patrick W.
18
+ # All rights reserved.
19
+ #
20
+ # Redistribution and use in source and binary forms, with or without
21
+ # modification, are permitted provided that the following conditions are met:
22
+ #
23
+ # * Redistributions of source code must retain the above copyright notice, this
24
+ # list of conditions and the following disclaimer.
25
+ #
26
+ # * Redistributions in binary form must reproduce the above copyright notice,
27
+ # this list of conditions and the following disclaimer in the documentation
28
+ # and/or other materials provided with the distribution.
29
+ #
30
+ # * Neither the name of the copyright holder nor the names of its
31
+ # contributors may be used to endorse or promote products derived from
32
+ # this software without specific prior written permission.
33
+ #
34
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
35
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
38
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
40
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
41
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
43
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/lib/rune.rb ADDED
@@ -0,0 +1,29 @@
1
+ Dir[File.dirname(__FILE__)].each { |file| $LOAD_PATH.unshift(file) if File.directory? file }
2
+
3
+ require 'nio/bytebuffer'
4
+
5
+ # <h1>RuneRb</h1>
6
+ # <p>A game server written in Ruby targeting the 2006 era (or the 317-377 protocols) of the popular MMORPG, RuneScape.</p>
7
+ #
8
+ #
9
+ # @author Patrick W.
10
+ # @since 0.0.1
11
+ module RuneRb
12
+
13
+ # The Network module contains all common network related classes and modules.
14
+ module Network
15
+ autoload :Buffer, 'rune/network/buffer'
16
+ autoload :Constants, 'rune/network/constants'
17
+ autoload :ISAAC, 'rune/network/isaac'
18
+ autoload :Readable, 'rune/network/readable'
19
+ autoload :Writeable, 'rune/network/writeable'
20
+
21
+ include Constants
22
+ end
23
+
24
+ # The Patches module contains all common patches to core classes.
25
+ module Patches
26
+ autoload :IntegerRefinements, 'rune/patches/integer_refinements'
27
+ autoload :SetRefinements, 'rune/patches/set_refinements'
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rrb-common
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Patrick W.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-11-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nio4r
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.5.9
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.5.9
27
+ - !ruby/object:Gem::Dependency
28
+ name: dotenv
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.8'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: benchmark
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '13.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '13.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.12'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.12'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5.19'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '5.19'
97
+ - !ruby/object:Gem::Dependency
98
+ name: terminal-table
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.0'
111
+ description: A set of common classes, modules, and functions for Rune.rb.
112
+ email: Sickday@pm.me
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - lib/rune.rb
118
+ - lib/rune/network/buffer.rb
119
+ - lib/rune/network/constants.rb
120
+ - lib/rune/network/isaac.rb
121
+ - lib/rune/network/readable.rb
122
+ - lib/rune/network/writeable.rb
123
+ - lib/rune/patches/integer_refinements.rb
124
+ - lib/rune/patches/set_refinements.rb
125
+ homepage:
126
+ licenses:
127
+ - BSD-3-Clause
128
+ metadata: {}
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: 3.1.0
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubygems_version: 3.4.10
145
+ signing_key:
146
+ specification_version: 4
147
+ summary: Common utilities for RuneRb.
148
+ test_files: []