rrb 0.0.4

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: 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: []