rrb 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,209 +0,0 @@
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.