rrb 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.