rrb 0.0.4

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 41791058f4c6b1f6c6295182df8f1edae27a3aa6e89655bc11530863d7d136b5
4
+ data.tar.gz: 5457ead97de7f07f2bb09bdbd3254eaf6dc4ded42b08943f9fba860ad0af9149
5
+ SHA512:
6
+ metadata.gz: d1f5a2425a35ab452d24442399c31ea3e3bb1acb20dba030e6cc85458e929b6199de6074e02132f313f843fc3169af7c282038e2605f196dabe3e2221d32291c
7
+ data.tar.gz: 5f39f2186da44056283a23921b252b30efbb27a0c0dd3ada6b0f1875f4e8ecd30d8a45e36c1c7a740b058698cf92f977649eeef789494cc793877851b77b473e
@@ -0,0 +1,104 @@
1
+ # Overflow behavior for Integers that attempts to mimic the behavior of Java primitive overflow behavior.
2
+ module RuneRb::Patches::IntegerRefinements
3
+
4
+ refine Integer do
5
+ # Adjusts the value of the Integer to be unsigned.
6
+ # @param type [Symbol] the type of primitive the value will be returned as
7
+ def unsigned(type)
8
+ return 0 if negative?
9
+
10
+ case type
11
+ when :Byte, :byte, :b, :B then to_i > 0xFF ? 0xFF : to_i
12
+ when :Short, :short, :s, :S then to_i > 0xFFFF ? 0xFFFF : to_i
13
+ when :Integer, :Int, :int, :integer, :i, :I then to_i > 0xFFFFFFFF ? 0xFFFFFFFF : to_i
14
+ when :Long, :long, :l, :L then to_i > 0xFFFFFFFFFFFFFFFF ? 0xFFFFFFFFFFFFFFFF : to_i
15
+ else unsigned(:int)
16
+ end
17
+ end
18
+
19
+ alias_method :u, :unsigned
20
+
21
+ # Adjusts the value of the Integer to be signed.
22
+ # @param type [Symbol] the type of primitive the value will be returned as
23
+ def signed(type)
24
+ case type
25
+ when :Byte, :byte, :b, :B then adjust(:byte)
26
+ when :Short, :short, :s, :S then adjust(:short)
27
+ when :Integer, :Int, :int, :integer, :i, :I then adjust(:integer)
28
+ when :Long, :long, :l, :L then adjust(:long)
29
+ else adjust(:integer)
30
+ end
31
+ end
32
+
33
+ alias_method :s, :signed
34
+
35
+ def nibble
36
+ adjust(:nibble)
37
+ end
38
+
39
+ # Returns a string with a formatted representation of the Integer as a timestamp.
40
+ def to_ftime
41
+ mm, ss = divmod(60)
42
+ hh, mm = mm.divmod(60)
43
+ dd, hh = hh.divmod(24)
44
+ format('%d days, %d hours, %d minutes, and %d seconds', dd, hh, mm, ss)
45
+ end
46
+
47
+ private
48
+
49
+ # Adjusts the integer based on the passed type
50
+ # @param type [Symbol] the type of adjustment to make to the integer.
51
+ def adjust(type)
52
+ case type
53
+ when :Byte, :byte, :b, :B
54
+ primitive_max = 2**7 - 1
55
+ primitive_min = -2**7
56
+ when :Short, :short, :s, :S
57
+ primitive_max = 2**15 - 1
58
+ primitive_min = -2**15
59
+ when :Integer, :Int, :int, :i, :I
60
+ primitive_max = 2**31 - 1
61
+ primitive_min = -2**31
62
+ when :Long, :long, :l, :L
63
+ primitive_max = 2**63 - 1
64
+ primitive_min = -2**63
65
+ when :Nibble, :nibble, :n, :N
66
+ primitive_max = 2**4
67
+ primitive_min = -2**4
68
+ else
69
+ primitive_max = 2**31 - 1
70
+ primitive_min = -2**31
71
+ end
72
+ self < -primitive_max ? -1 * (-self & primitive_max) : self
73
+ self > primitive_min ? (self & primitive_max) : self
74
+ end
75
+ end
76
+ end
77
+
78
+ # Copyright (c) 2022, Patrick W.
79
+ # All rights reserved.
80
+ #
81
+ # Redistribution and use in source and binary forms, with or without
82
+ # modification, are permitted provided that the following conditions are met:
83
+ #
84
+ # * Redistributions of source code must retain the above copyright notice, this
85
+ # list of conditions and the following disclaimer.
86
+ #
87
+ # * Redistributions in binary form must reproduce the above copyright notice,
88
+ # this list of conditions and the following disclaimer in the documentation
89
+ # and/or other materials provided with the distribution.
90
+ #
91
+ # * Neither the name of the copyright holder nor the names of its
92
+ # contributors may be used to endorse or promote products derived from
93
+ # this software without specific prior written permission.
94
+ #
95
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
96
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
97
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
98
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
99
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
100
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
101
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
102
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
103
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
104
+ # 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) 2022, 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.
@@ -0,0 +1,172 @@
1
+ # Convenience functions to be used when a string is behaving as a buffer..
2
+ module RuneRb::Patches::StringRefinements
3
+ VALID_CHARS = %w{_ a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 ! @ # $ % ^ & * ( ) - + = : ; . > < , " [ ] | ? / `}.freeze
4
+
5
+ refine String do
6
+ using RuneRb::Patches::IntegerRefinements
7
+
8
+ # returns the next byte.
9
+ def next_byte
10
+ slice!(0)&.unpack1('c')
11
+ end
12
+
13
+ # Returns the next x amount of byte values.
14
+ # @param amount [Integer] the amount of bytes.
15
+ def next_bytes(amount)
16
+ amount.times.inject('') { |str| str << slice!(0) }.unpack('c*')
17
+ end
18
+
19
+ # returns the next byte from the provided position.
20
+ # @param position [Integer] the offset/position to begin reading from.
21
+ def byte_from(position)
22
+ slice!(position).unpack1('c')
23
+ end
24
+
25
+ # Returns x amount of bytes from a given position.
26
+ # @param position [Integer] the offset/position to begin reading from.
27
+ # @param amount [Integer] the amount of bytes to read.
28
+ def bytes_from(position, amount)
29
+ amount.times.inject('') { |str| str << slice!(position) }.unpack('c*')
30
+ end
31
+
32
+ # returns the next short.
33
+ def next_short
34
+ slice!(0..1).unpack1('n')
35
+ end
36
+
37
+ # Returns the next x amount of short values.
38
+ # @param amount [Integer] the amount of shorts.
39
+ def next_shorts(amount)
40
+ amount.times.inject('') { |str| str << slice!(0..1) }.unpack('n*')
41
+ end
42
+
43
+ # returns the next short from the provided position.
44
+ # @param position [Integer] the offset/position to begin reading from.
45
+ def short_from(position)
46
+ slice!(position..(position + 1)).unpack1('n')
47
+ end
48
+
49
+ # Returns x amount of shorts from a given position
50
+ # @param position [Integer] the offset/position to begin reading from.
51
+ # @param amount [Integer] the amount of shorts to read.
52
+ def shorts_from(position, amount)
53
+ amount.times.inject('') { |str| str << slice!(position..(position + 1)) }.unpack('n*')
54
+ end
55
+
56
+ # returns the next integer.
57
+ def next_int
58
+ slice!(0..3).unpack1('i')
59
+ end
60
+
61
+ # Returns the next x amount of integer values.
62
+ # @param amount [Integer] the amount of integers.
63
+ def next_ints(amount)
64
+ amount.times.inject('') { |str| str << slice!(0..3) }.unpack('l*')
65
+ end
66
+
67
+ # returns the next int from the provided position.
68
+ # @param position [Integer] the offset/position to begin reading from.
69
+ def int_from(position)
70
+ slice!(position..(position + 3)).unpack1('l')
71
+ end
72
+
73
+ # Returns x amount of integers from a given position
74
+ # @param position [Integer] the offset/position to begin reading from.
75
+ # @param amount [Integer] the amount of integers to read.
76
+ def ints_from(position, amount)
77
+ amount.times.inject('') { |str| str << slice!(position..(position + 3)) }.unpack('l*')
78
+ end
79
+
80
+ # returns the next long.
81
+ def next_long
82
+ slice!(0..7).unpack1('q')
83
+ end
84
+
85
+ # Returns the next x amount of long values.
86
+ # @param amount [Integer] the amount of longs.
87
+ def next_longs(amount)
88
+ amount.times.inject('') { |str| str << slice!(0..7) }.unpack('q*')
89
+ end
90
+
91
+ # returns the next long from the provided position.
92
+ # @param position [Integer] the offset/position to begin reading from.
93
+ def long_from(position)
94
+ slice!(position..(position + 7)).unpack1('q')
95
+ end
96
+
97
+ # Returns x amount of longs from a given position.
98
+ # @param position [Integer] the offset/position to begin reading from.
99
+ # @param amount [Integer] the amount of longs to read.
100
+ def longs_from(position, amount)
101
+ amount.times.inject('') { |str| str << slice!(position..(position + 7)) }.unpack('q*')
102
+ end
103
+
104
+ # Returns the next terminated string.
105
+ def next_tstring
106
+ val = ''
107
+ while (res = slice!(0))
108
+ break if res == "\n"
109
+
110
+ val << res
111
+ end
112
+ val
113
+ end
114
+
115
+ # Returns a base37 numeric representation of the String.
116
+ # @return [Integer] a base37 number representing the String
117
+ def to_base37
118
+ l = 0
119
+ (0...length).each do |i|
120
+ c = self[i].chr
121
+ l *= 37
122
+ l += (1 + self[i].bytes.first) - 65 if (c >= 'A') && (c <= 'Z')
123
+ l += (1 + self[i].bytes.first) - 97 if (c >= 'a') && (c <= 'z')
124
+ l += (27 + self[i].bytes.first) - 48 if (c >= '0') && (c <= '9')
125
+ end
126
+ l /= 37 while (l % 37).zero? && l != 0
127
+ l
128
+ end
129
+
130
+ # Returns a string from the provided b37 numeric
131
+ # @param base37 [Integer] the base_37 numeric to build a string from.
132
+ def from_base37(base37)
133
+ return self unless empty?
134
+
135
+ while base37 != 0
136
+ original = base37.signed(:long)
137
+ base37 = (base37 / 37).signed(:long)
138
+ self << RuneRb::Patches::StringRefinements::VALID_CHARS[(original - base37 * 37).signed(:int)]
139
+ end
140
+
141
+ reverse!
142
+ end
143
+ end
144
+ end
145
+
146
+ # Copyright (c) 2022, Patrick W.
147
+ # All rights reserved.
148
+ #
149
+ # Redistribution and use in source and binary forms, with or without
150
+ # modification, are permitted provided that the following conditions are met:
151
+ #
152
+ # * Redistributions of source code must retain the above copyright notice, this
153
+ # list of conditions and the following disclaimer.
154
+ #
155
+ # * Redistributions in binary form must reproduce the above copyright notice,
156
+ # this list of conditions and the following disclaimer in the documentation
157
+ # and/or other materials provided with the distribution.
158
+ #
159
+ # * Neither the name of the copyright holder nor the names of its
160
+ # contributors may be used to endorse or promote products derived from
161
+ # this software without specific prior written permission.
162
+ #
163
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
164
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
165
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
166
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
167
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
168
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
169
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
170
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
171
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
172
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,209 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rrb_data'
4
+ require 'rrb_game'
5
+ require 'rrb_net'
6
+
7
+ # Utility objects and modules.
8
+ module RuneRb::Utils
9
+
10
+ # The Controller instance facilitates the deployment of game world and server instances.
11
+ class Controller
12
+ using RuneRb::Patches::IntegerRefinements
13
+
14
+ include RuneRb::Utils::Logging
15
+
16
+ include Singleton
17
+
18
+ # @!attribute [r] sessions
19
+ # @return [Hash] a collection of sessions.
20
+ attr :sessions
21
+
22
+ # @!attribute [r] servers
23
+ # @return [Hash] a collection of server objects and signatures.
24
+ attr :servers
25
+
26
+ # @!attribute [r] worlds
27
+ # @return [Array] a map of World instances.
28
+ attr :worlds
29
+
30
+ # Constructs a new Controller object
31
+ def initialize
32
+ @queue = Queue.new
33
+ @servers = {}
34
+ @worlds = {}
35
+ @start = { time: Process.clock_gettime(Process::CLOCK_MONOTONIC), stamp: Time.now }
36
+
37
+ setup_trapping
38
+ end
39
+
40
+ def autorun(em: false)
41
+ EventMachine.run do
42
+ setup_queue
43
+
44
+ # Deploy a game world instance.
45
+ deploy_world
46
+ # deploy_world.run
47
+
48
+ # Deploy a server.
49
+ deploy_server(host: '0.0.0.0', em: em).run
50
+
51
+ # Deploy a console
52
+ # deploy_console
53
+ end
54
+ end
55
+
56
+ # Logs information about the worlds, servers, and session states.
57
+ def about
58
+ log COLORS.green("[Sessions]:\n#{@sessions.each(&:inspect)}")
59
+ log COLORS.green("[Servers]:\n#{@servers.each(&:inspect)}")
60
+ log COLORS.green("[Worlds]:\n#{@worlds.each(&:inspect)}")
61
+ end
62
+
63
+ # Deploys a single TCP Socket Server.
64
+ # @param host [String] the host address
65
+ # @param port [Integer] the port
66
+ # @param em [Boolean] should this be an EventMachine server?
67
+ # @param label [String, Integer] the label
68
+ # @return [Integer, RunRb::Network::Server] the constructed Server or a signature identifying the server.
69
+ def deploy_server(host: 'localhost', port: 43_594, em: false, label: @servers[ENV['RRB_NET_TARGET']] ? Druuid.gen : ENV['RRB_NET_TARGET'])
70
+ @servers[label] = if em
71
+ EventMachine.start_server(host, port, RuneRb::Network::SessionEM) do
72
+ if ENV['RRB_NET_TARGET'] == 'default'
73
+ raise 'No default server instance available to receive session!' if @servers.empty?
74
+
75
+ @servers.values.first.sessions[_1.sig] = _1
76
+ else
77
+ raise "No Server instance associated with label: #{ENV['RRB_NET_TARGET']}!" unless @servers[ENV['RRB_NET_TARGET']]
78
+
79
+ @servers[ENV['RRB_NET_TARGET']].sessions[_1.sig] = _1
80
+ end
81
+ end
82
+ else
83
+ RuneRb::Network::Server.new(host: host, port: port, controller: self)
84
+ end
85
+ log! "Deployed new Server instance. [label: #{label}]"
86
+ @servers[label]
87
+ end
88
+
89
+ # Deploys a singe instance of {RuneRb::Game::World}
90
+ # @param label [Integer, String] the label
91
+ # @return [RuneRb::Game::World] the constructed World
92
+ def deploy_world(label: @worlds[ENV['RRB_GAME_TARGET']] ? Druuid.gen : ENV['RRB_GAME_TARGET'])
93
+ @worlds[label] = RuneRb::Game::World.new
94
+ log! "Deployed new World instance. [label: #{label}]"
95
+ @worlds[label]
96
+ end
97
+
98
+ # Registers a session.
99
+ # @param req [RuneRb::Network::Gateway::Request] the request.
100
+ def enqueue(req)
101
+ @queue.push(req)
102
+ end
103
+
104
+ # Stop all server instances and close all connected sessions.
105
+ def shutdown(graceful: true)
106
+ return if @closed
107
+
108
+ @servers.each_value do |item|
109
+ case item
110
+ when Integer then EventMachine.stop_server(item) if EventMachine.reactor_running?
111
+ when RuneRb::Network::Server then graceful ? item.shutdown : item.worker.kill
112
+ else next
113
+ end
114
+ end
115
+ log! COLORS.red.bold("Closed #{@servers.length} server instances.")
116
+
117
+ @worlds.each_value { _1.shutdown(graceful: graceful) }
118
+ log! COLORS.red.bold("Closed #{@worlds.length} game instances.")
119
+
120
+ log! COLORS.blue.bold("Total Controller Up-time: #{up_time.to_i.to_ftime}")
121
+ ensure
122
+ @servers.clear
123
+ @closed = true
124
+ end
125
+
126
+ # The current up-time for the server.
127
+ def up_time
128
+ (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @start[:time]).round(3)
129
+ end
130
+
131
+ def deploy_console
132
+ Pry.start
133
+ end
134
+
135
+ private
136
+
137
+ def setup_trapping
138
+ # Trap Interrupt (INT) signals.
139
+ Signal.trap('INT') do
140
+ Thread.new do
141
+ log! COLORS.red('Caught INTERRUPT!')
142
+ log! COLORS.red.bold('Shutting Down...')
143
+ ensure
144
+ shutdown
145
+ end.join
146
+ end
147
+
148
+ # Trap Termination (TERM) signals.
149
+ Signal.trap('TERM') do
150
+ Thread.new do
151
+ log! COLORS.red('Caught TERMINATION!')
152
+ log! COLORS.red.bold('Shutting Down...')
153
+ ensure
154
+ shutdown
155
+ end.join
156
+ end
157
+ end
158
+
159
+ def setup_queue
160
+ @queue = Queue.new
161
+ EventMachine.add_periodic_timer(0.600) do
162
+ until @queue.empty?
163
+ new_request = @queue.pop
164
+
165
+ if ENV['RRB_GAME_TARGET'] == 'default'
166
+ raise 'No default World instance available to register context!' if @worlds.empty?
167
+
168
+
169
+ @worlds.values.first.receive(new_request.session, new_request.profile, new_request.profile.nil?)
170
+ else
171
+ raise "No World instance associated with label: #{ENV['RRB_GAME_TARGET']}!" unless @worlds[ENV['RRB_GAME_TARGET']]
172
+
173
+ @worlds[ENV['RRB_GAME_TARGET']].receive(new_request.session, new_request.profile, new_request.profile.nil?)
174
+ end
175
+ end
176
+ rescue StandardError => e
177
+ err 'An error occurred while processing session queue!', e.message, e.backtrace&.join("\n")
178
+ end
179
+ end
180
+ end
181
+ end
182
+
183
+ # Copyright (c) 2021, Patrick W.
184
+ # All rights reserved.
185
+ #
186
+ # Redistribution and use in source and binary forms, with or without
187
+ # modification, are permitted provided that the following conditions are met:
188
+ #
189
+ # * Redistributions of source code must retain the above copyright notice, this
190
+ # list of conditions and the following disclaimer.
191
+ #
192
+ # * Redistributions in binary form must reproduce the above copyright notice,
193
+ # this list of conditions and the following disclaimer in the documentation
194
+ # and/or other materials provided with the distribution.
195
+ #
196
+ # * Neither the name of the copyright holder nor the names of its
197
+ # contributors may be used to endorse or promote products derived from
198
+ # this software without specific prior written permission.
199
+ #
200
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
201
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
202
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
203
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
204
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
205
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
206
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
207
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
208
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
209
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A module responsible for loading environmental vars..
4
+ module RuneRb::Utils::Environment
5
+
6
+ # Loads environmental variables and creates necessary directories.
7
+ def init_env(fetch: false, force: false)
8
+ FileUtils.mkdir_p('data') unless File.exist?('data')
9
+ FileUtils.mkdir_p('data/logs') unless File.exist?('data/logs')
10
+ FileUtils.touch(RuneRb::Utils::Logging::LOG_FILE_PATH) unless File.exist?(RuneRb::Utils::Logging::LOG_FILE_PATH)
11
+ Dir['data/*.env'].each { FileUtils.rm(_1) } if force
12
+
13
+ if File.exist?('data/rrb.env') || File.exist?('data/sample-rrb.env')
14
+ Dotenv.load(File.exist?('data/rrb.env') ? 'data/rrb.env' : 'data/sample-rrb.env')
15
+ elsif fetch
16
+ IO.copy_stream(URI.open('https://git.repos.pw/rune.rb/app/-/snippets/1/raw/main/sample-rrb.env'), 'data/sample-rrb.env')
17
+ init_env(fetch: false)
18
+ else
19
+ raise(StandardError, 'No rrb.env file found!')
20
+ end
21
+ nil
22
+ end
23
+ end
24
+
25
+ # Copyright (c) 2022, Patrick W.
26
+ # All rights reserved.
27
+ #
28
+ # Redistribution and use in source and binary forms, with or without
29
+ # modification, are permitted provided that the following conditions are met:
30
+ #
31
+ # * Redistributions of source code must retain the above copyright notice, this
32
+ # list of conditions and the following disclaimer.
33
+ #
34
+ # * Redistributions in binary form must reproduce the above copyright notice,
35
+ # this list of conditions and the following disclaimer in the documentation
36
+ # and/or other materials provided with the distribution.
37
+ #
38
+ # * Neither the name of the copyright holder nor the names of its
39
+ # contributors may be used to endorse or promote products derived from
40
+ # this software without specific prior written permission.
41
+ #
42
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
45
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
46
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
51
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,114 @@
1
+ module RuneRb::Utils::Logging
2
+
3
+ # @!attribute [r] COLORS
4
+ # @return [Pastel] provides String coloring functions.
5
+ COLORS ||= RuneRb::COLORS ||= Pastel.new
6
+
7
+ # @!attribute [r] STDOUT
8
+ # @return [Logger] logger that writes to {$stdout}.
9
+ LOG_STDOUT ||= RuneRb::STDOUT ||= Logger.new($stdout)
10
+ LOG_STDOUT.formatter = proc do |sev, date, _prog, msg|
11
+ "#{COLORS.cyan("[#{date.strftime('%H:%M')}]")}|#{COLORS.blue("[#{sev}]")} -> #{msg}\n"
12
+ end
13
+
14
+ LOG_FILE_PATH = "#{ENV['RRB_LOG_PATH'] || 'data/logs'}/rune.rb-#{Time.now.strftime('%Y-%m-%d').chomp}.log".freeze
15
+
16
+ # @!attribute [r] LOG_FILE
17
+ # @return [Logger] logger that writes to a file.
18
+ LOG_FILE ||= RuneRb::LOG_FILE ||= Logger.new(LOG_FILE_PATH, progname: "rune.rb")
19
+
20
+ # The class name, un-nested, as a symbol
21
+ # @return [Symbol] the class name.
22
+ def class_name
23
+ self.class.name.split('::').last.to_sym
24
+ end
25
+
26
+ # Log info lines
27
+ # @param lines [Array] lines of text that are passed to the logger.
28
+ # @param app_name [String] the name of the application.
29
+ # @param to_file [Boolean] should the line be written to the Logging#LOG_FILE?
30
+ # @param to_stdout [Boolean] should the line(s) be written to $STDOUT?
31
+ def log(*lines, app_name: @label || 'rune.rb', to_file: true, to_stdout: true)
32
+ lines.each do |line|
33
+ LOG_STDOUT.info(COLORS.white("[#{class_name}] -> #{line}")) if to_stdout
34
+ LOG_FILE.info(app_name) { "[#{Time.now.strftime('%H:%M')}] #{COLORS.strip(line)}" } if to_file
35
+ end
36
+ nil
37
+ end
38
+
39
+ alias info log
40
+
41
+ # Log warning lines
42
+ # @param lines [Array] lines of text that are passed to the RuneRb::GLOBAL[:LOGGER].
43
+ # @param app_name [String] the name of the application.
44
+ # @param to_file [Boolean] should the line be written to the Logging#LOG_FILE?
45
+ # @param to_stdout [Boolean] should the line(s) be written to $STDOUT?
46
+ def log!(*lines, app_name: @label || 'rune.rb', to_file: true, to_stdout: true)
47
+ lines.each do |line|
48
+ LOG_STDOUT.warn(COLORS.yellow("[#{class_name}] -> #{line}")) if to_stdout
49
+ LOG_FILE.warn(app_name) { "[#{Time.now.strftime('%H:%M')}] #{COLORS.strip(line)}" } if to_file
50
+ end
51
+ nil
52
+ end
53
+
54
+ alias debug log!
55
+ alias warn log!
56
+
57
+ # Log error lines
58
+ # @param lines [Array] lines of text that are passed to the RuneRb::GLOBAL[:LOGGER].
59
+ # @param app_name [String] the name of the application.
60
+ # @param to_file [Boolean] should the line be written to the Logging#LOG_FILE?
61
+ # @param to_stdout [Boolean] should the line(s) be written to $STDOUT?
62
+ def err(*lines, app_name: @label || 'rune.rb', to_file: true, to_stdout: true)
63
+ lines.each do |line|
64
+ LOG_STDOUT.error(COLORS.magenta.bold("[#{class_name}] ~> #{line}")) if to_stdout
65
+ LOG_FILE.error(app_name) { "[#{Time.now.strftime('%H:%M')}] #{COLORS.strip(line)}" } if to_file
66
+ end
67
+ nil
68
+ end
69
+
70
+ alias error err
71
+
72
+ # Log fatal lines
73
+ # @param lines [Array] lines of text that are passed to the RuneRb::GLOBAL[:LOGGER].
74
+ # @param app_name [String] the name of the application.
75
+ # @param to_file [Boolean] should the line be written to the Logging#LOG_FILE?
76
+ # @param to_stdout [Boolean] should the line(s) be written to $STDOUT?
77
+ def err!(*lines, app_name: @label || 'rune.rb', to_file: true, to_stdout: true)
78
+ lines.each do |line|
79
+ LOG_STDOUT.error(COLORS.red.bold("[#{class_name}] ~> #{line}")) if to_stdout
80
+ LOG_FILE.fatal(app_name) { "[#{Time.now.strftime('%H:%M')}] #{COLORS.strip(line)}" } if to_file
81
+ end
82
+ nil
83
+ end
84
+
85
+ alias fatal err!
86
+ end
87
+
88
+ # Copyright (c) 2022, Patrick W.
89
+ # All rights reserved.
90
+ #
91
+ # Redistribution and use in source and binary forms, with or without
92
+ # modification, are permitted provided that the following conditions are met:
93
+ #
94
+ # * Redistributions of source code must retain the above copyright notice, this
95
+ # list of conditions and the following disclaimer.
96
+ #
97
+ # * Redistributions in binary form must reproduce the above copyright notice,
98
+ # this list of conditions and the following disclaimer in the documentation
99
+ # and/or other materials provided with the distribution.
100
+ #
101
+ # * Neither the name of the copyright holder nor the names of its
102
+ # contributors may be used to endorse or promote products derived from
103
+ # this software without specific prior written permission.
104
+ #
105
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
106
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
107
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
108
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
109
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
110
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
111
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
112
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
113
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
114
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,53 @@
1
+ module RuneRb::Utils
2
+
3
+ # Functions to retrieve version data for the Rune.rb project.
4
+ module Version
5
+ # The version.
6
+ # @return [String] the Rune.rb project version.
7
+ def version
8
+ raw[:version]
9
+ end
10
+
11
+ # The build string for the project.
12
+ # @return [String] the build string for the Rune.rb project.
13
+ def build
14
+ "#{version}-#{raw[:build]}"
15
+ end
16
+
17
+ private
18
+
19
+ # The raw version data.
20
+ # @return [Hash] the raw version data for the Rune.rb project.
21
+ def raw
22
+ Oj.load(URI.open("http://db.objects.pw:32960/api/v1/project/#{ENV['RRB_PROJECT_SIGNATURE'] || '13360515828940800000'}").read)
23
+ end
24
+ end
25
+ end
26
+
27
+ # Copyright (c) 2022, Patrick W.
28
+ # All rights reserved.
29
+ #
30
+ # Redistribution and use in source and binary forms, with or without
31
+ # modification, are permitted provided that the following conditions are met:
32
+ #
33
+ # * Redistributions of source code must retain the above copyright notice, this
34
+ # list of conditions and the following disclaimer.
35
+ #
36
+ # * Redistributions in binary form must reproduce the above copyright notice,
37
+ # this list of conditions and the following disclaimer in the documentation
38
+ # and/or other materials provided with the distribution.
39
+ #
40
+ # * Neither the name of the copyright holder nor the names of its
41
+ # contributors may be used to endorse or promote products derived from
42
+ # this software without specific prior written permission.
43
+ #
44
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
45
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
47
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
48
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
50
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
51
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
52
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/app/rrb.rb ADDED
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir[File.dirname(__FILE__)].each { |file| $LOAD_PATH.unshift(file) if File.directory? file }
4
+ $LOAD_PATH.unshift File.dirname(__FILE__)
5
+
6
+ require 'dotenv'
7
+ require 'druuid'
8
+ require 'eventmachine'
9
+ require 'logger'
10
+ require 'oj'
11
+ require 'open-uri'
12
+ require 'pastel'
13
+ require 'pry'
14
+ require 'singleton'
15
+ require 'set'
16
+
17
+ ##
18
+ # RuneRb -
19
+ # A gameserver framework written in Ruby targeting the 2006 era (or the 317-377 protocols) of the popular MMORPG, RuneScape.
20
+ #
21
+ # @author Patrick W.
22
+ # @since 0.0.1
23
+ module RuneRb
24
+
25
+ # Utility objects and modules.
26
+ module Utils
27
+ autoload :Controller, 'rrb/utils/controller'
28
+ autoload :Environment, 'rrb/utils/environment'
29
+ autoload :Logging, 'rrb/utils/logging'
30
+ autoload :Version, 'rrb/utils/version'
31
+ end
32
+
33
+ # Refinements to provide special functionality and behavior(s) to specific objects.
34
+ module Patches
35
+ autoload :IntegerRefinements, 'rrb/patches/integer'
36
+ autoload :StringRefinements, 'rrb/patches/string'
37
+ autoload :SetRefinements, 'rrb/patches/set'
38
+ end
39
+
40
+ RuneRb.extend(RuneRb::Utils::Version)
41
+ RuneRb.extend(RuneRb::Utils::Environment)
42
+ end
43
+
44
+ # Copyright (c) 2022, Patrick W.
45
+ # All rights reserved.
46
+ #
47
+ # Redistribution and use in source and binary forms, with or without
48
+ # modification, are permitted provided that the following conditions are met:
49
+ #
50
+ # * Redistributions of source code must retain the above copyright notice, this
51
+ # list of conditions and the following disclaimer.
52
+ #
53
+ # * Redistributions in binary form must reproduce the above copyright notice,
54
+ # this list of conditions and the following disclaimer in the documentation
55
+ # and/or other materials provided with the distribution.
56
+ #
57
+ # * Neither the name of the copyright holder nor the names of its
58
+ # contributors may be used to endorse or promote products derived from
59
+ # this software without specific prior written permission.
60
+ #
61
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
62
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
64
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
65
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
67
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
68
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
69
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
70
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
metadata ADDED
@@ -0,0 +1,233 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rrb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Patrick W.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-03-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dotenv
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.7'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.7.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.7'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.7.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: druuid
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.0'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.0.2
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.0'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.0.2
53
+ - !ruby/object:Gem::Dependency
54
+ name: eventmachine
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '1.2'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 1.2.7
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.2'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 1.2.7
73
+ - !ruby/object:Gem::Dependency
74
+ name: logger
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '1.5'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 1.5.0
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.5'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 1.5.0
93
+ - !ruby/object:Gem::Dependency
94
+ name: oj
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '3.13'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 3.13.10
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '3.13'
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 3.13.10
113
+ - !ruby/object:Gem::Dependency
114
+ name: open-uri
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '0.2'
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: 0.2.0
123
+ type: :runtime
124
+ prerelease: false
125
+ version_requirements: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '0.2'
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: 0.2.0
133
+ - !ruby/object:Gem::Dependency
134
+ name: pastel
135
+ requirement: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: '0.8'
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: 0.8.0
143
+ type: :runtime
144
+ prerelease: false
145
+ version_requirements: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - "~>"
148
+ - !ruby/object:Gem::Version
149
+ version: '0.8'
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: 0.8.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: pry
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '0.14'
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: 0.14.0
163
+ type: :runtime
164
+ prerelease: false
165
+ version_requirements: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - "~>"
168
+ - !ruby/object:Gem::Version
169
+ version: '0.14'
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: 0.14.0
173
+ - !ruby/object:Gem::Dependency
174
+ name: rake
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: '13.0'
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ version: 13.0.0
183
+ type: :runtime
184
+ prerelease: false
185
+ version_requirements: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - "~>"
188
+ - !ruby/object:Gem::Version
189
+ version: '13.0'
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: 13.0.0
193
+ description:
194
+ email: Sickday@pm.me
195
+ executables: []
196
+ extensions: []
197
+ extra_rdoc_files: []
198
+ files:
199
+ - app/rrb.rb
200
+ - app/rrb/patches/integer.rb
201
+ - app/rrb/patches/set.rb
202
+ - app/rrb/patches/string.rb
203
+ - app/rrb/utils/controller.rb
204
+ - app/rrb/utils/environment.rb
205
+ - app/rrb/utils/logging.rb
206
+ - app/rrb/utils/version.rb
207
+ homepage: https://git.repos.pw/rune.rb/app
208
+ licenses:
209
+ - BSD-3-Clause
210
+ metadata:
211
+ source_code_uri: https://git.repos.pw/rune.rb/app
212
+ post_install_message:
213
+ rdoc_options: []
214
+ require_paths:
215
+ - app
216
+ - app/rrb
217
+ required_ruby_version: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: 3.0.1
222
+ required_rubygems_version: !ruby/object:Gem::Requirement
223
+ requirements:
224
+ - - ">="
225
+ - !ruby/object:Gem::Version
226
+ version: '0'
227
+ requirements: []
228
+ rubygems_version: 3.3.3
229
+ signing_key:
230
+ specification_version: 4
231
+ summary: A gameserver framework written in Ruby targeting the 2006 era (or the 317-377
232
+ protocols) of the popular MMORPG, RuneScape.
233
+ test_files: []