gameoverseer 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +4 -4
- data/Gemfile +3 -3
- data/Gemfile.lock +30 -30
- data/README.md +53 -51
- data/Rakefile +2 -0
- data/gameoverseer.gemspec +22 -22
- data/lib/gameoverseer.rb +73 -73
- data/lib/gameoverseer/channels/channel_manager.rb +48 -48
- data/lib/gameoverseer/clients/client_manager.rb +68 -68
- data/lib/gameoverseer/console/console.rb +206 -206
- data/lib/gameoverseer/console/namespace_creator.rb +4 -4
- data/lib/gameoverseer/encryption_handler/encryption_handler.rb +40 -40
- data/lib/gameoverseer/input_handler/input_handler.rb +36 -36
- data/lib/gameoverseer/messages/message_manager.rb +40 -40
- data/lib/gameoverseer/packet_handler/json_packet_handler.rb +34 -31
- data/lib/gameoverseer/packet_handler/messagepack_packet_handler.rb +31 -31
- data/lib/gameoverseer/packet_handler/packet_handler.rb +29 -29
- data/lib/gameoverseer/server/renet_server.rb +126 -126
- data/lib/gameoverseer/services/service.rb +112 -111
- data/lib/gameoverseer/services/services.rb +38 -38
- data/lib/gameoverseer/version.rb +4 -4
- data/license.md +9 -9
- data/test-clients/test-client-gamma.rb +62 -62
- data/test/test_helper.rb +1 -1
- metadata +4 -4
@@ -1,4 +1,4 @@
|
|
1
|
-
module Gosu
|
2
|
-
class Window
|
3
|
-
end
|
4
|
-
end
|
1
|
+
module Gosu
|
2
|
+
class Window
|
3
|
+
end
|
4
|
+
end
|
@@ -1,40 +1,40 @@
|
|
1
|
-
module GameOverseer
|
2
|
-
class EncryptionHandler
|
3
|
-
|
4
|
-
def initialize(key_size: 128, keypair_size: 2048)
|
5
|
-
EncryptionHandler.instance = self
|
6
|
-
generate_server_keypair(keypair_size)
|
7
|
-
end
|
8
|
-
|
9
|
-
def generate_server_keypair(keypair_size)
|
10
|
-
@server_keypair = OpenSSL::PKey::RSA.generate(keypair_size)
|
11
|
-
end
|
12
|
-
|
13
|
-
def encrypt_keypair(client_id, string)
|
14
|
-
end
|
15
|
-
|
16
|
-
def decrypt_keypair(string)
|
17
|
-
end
|
18
|
-
|
19
|
-
def encrypt(client_id, string)
|
20
|
-
end
|
21
|
-
|
22
|
-
def decrypt(client_id, string)
|
23
|
-
end
|
24
|
-
|
25
|
-
def set_client_keypair(client_id, public_key_pem)
|
26
|
-
end
|
27
|
-
|
28
|
-
def set_client_key(client_id)
|
29
|
-
ClientManager.instance.update(client_id, '_aes_key', 'In progress, not ready.')
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.instance
|
33
|
-
@instance
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.instance=(_instance)
|
37
|
-
@instance = _instance
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
1
|
+
module GameOverseer
|
2
|
+
class EncryptionHandler
|
3
|
+
|
4
|
+
def initialize(key_size: 128, keypair_size: 2048)
|
5
|
+
EncryptionHandler.instance = self
|
6
|
+
generate_server_keypair(keypair_size)
|
7
|
+
end
|
8
|
+
|
9
|
+
def generate_server_keypair(keypair_size)
|
10
|
+
@server_keypair = OpenSSL::PKey::RSA.generate(keypair_size)
|
11
|
+
end
|
12
|
+
|
13
|
+
def encrypt_keypair(client_id, string)
|
14
|
+
end
|
15
|
+
|
16
|
+
def decrypt_keypair(string)
|
17
|
+
end
|
18
|
+
|
19
|
+
def encrypt(client_id, string)
|
20
|
+
end
|
21
|
+
|
22
|
+
def decrypt(client_id, string)
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_client_keypair(client_id, public_key_pem)
|
26
|
+
end
|
27
|
+
|
28
|
+
def set_client_key(client_id)
|
29
|
+
ClientManager.instance.update(client_id, '_aes_key', 'In progress, not ready.')
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.instance
|
33
|
+
@instance
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.instance=(_instance)
|
37
|
+
@instance = _instance
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,36 +1,36 @@
|
|
1
|
-
module GameOverseer
|
2
|
-
class InputHandler
|
3
|
-
|
4
|
-
# @param client_id [Integer]
|
5
|
-
# @param data [Hash]
|
6
|
-
def self.process_data(client_id, data)
|
7
|
-
@data = data
|
8
|
-
@client_id = client_id
|
9
|
-
forward_to_channel_manager if data_valid?
|
10
|
-
end
|
11
|
-
|
12
|
-
# Checks if hash contains 'channel' and 'mode'
|
13
|
-
# @return [Boolean]
|
14
|
-
def self.data_valid?
|
15
|
-
if @data["channel"]
|
16
|
-
if @data["mode"]
|
17
|
-
true
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Sends data and client_id to {ChannelManager}
|
23
|
-
def self.forward_to_channel_manager
|
24
|
-
count = 0
|
25
|
-
begin
|
26
|
-
channel_manager = GameOverseer::ChannelManager.instance
|
27
|
-
channel_manager.send_to_service(@client_id, @data)
|
28
|
-
rescue NoMethodError => e
|
29
|
-
GameOverseer::Console.log("InputHandler> #{e.to_s}")
|
30
|
-
raise if count >=2
|
31
|
-
count+=1
|
32
|
-
retry unless count >= 2
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
1
|
+
module GameOverseer
|
2
|
+
class InputHandler
|
3
|
+
|
4
|
+
# @param client_id [Integer]
|
5
|
+
# @param data [Hash]
|
6
|
+
def self.process_data(client_id, data)
|
7
|
+
@data = data
|
8
|
+
@client_id = client_id
|
9
|
+
forward_to_channel_manager if data_valid?
|
10
|
+
end
|
11
|
+
|
12
|
+
# Checks if hash contains 'channel' and 'mode'
|
13
|
+
# @return [Boolean]
|
14
|
+
def self.data_valid?
|
15
|
+
if @data["channel"]
|
16
|
+
if @data["mode"]
|
17
|
+
true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sends data and client_id to {ChannelManager}
|
23
|
+
def self.forward_to_channel_manager
|
24
|
+
count = 0
|
25
|
+
begin
|
26
|
+
channel_manager = GameOverseer::ChannelManager.instance
|
27
|
+
channel_manager.send_to_service(@client_id, @data)
|
28
|
+
rescue NoMethodError => e
|
29
|
+
GameOverseer::Console.log("InputHandler> #{e.to_s}")
|
30
|
+
raise if count >=2
|
31
|
+
count+=1
|
32
|
+
retry unless count >= 2
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,40 +1,40 @@
|
|
1
|
-
module GameOverseer
|
2
|
-
|
3
|
-
# Handles sending messages to clients on behalf of services
|
4
|
-
class MessageManager
|
5
|
-
MESSAGES = []
|
6
|
-
BROADCASTS = []
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
MessageManager.instance = self
|
10
|
-
end
|
11
|
-
|
12
|
-
# Send a message to a specific client
|
13
|
-
# @param client_id [Integer] ID of client
|
14
|
-
# @param string [String] message to send
|
15
|
-
# @param reliable [Boolean] whether or not packet delivery is reliable
|
16
|
-
# @param channel [Integer] What channel to send on
|
17
|
-
def message(client_id, string, reliable = false, channel = ChannelManager::CHAT)
|
18
|
-
GameOverseer::ENetServer.instance.transmit(client_id, string, reliable, channel)
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
# Send a message to all connected clients
|
23
|
-
# @param string [String] message to send
|
24
|
-
# @param reliable [Boolean] whether or not packet delivery is reliable
|
25
|
-
# @param channel [Integer] What channel to send on
|
26
|
-
def broadcast(string, reliable = false, channel = ChannelManager::CHAT)
|
27
|
-
GameOverseer::ENetServer.instance.broadcast(string, reliable, channel)
|
28
|
-
end
|
29
|
-
|
30
|
-
# @return [MessageManager]
|
31
|
-
def self.instance
|
32
|
-
@instance
|
33
|
-
end
|
34
|
-
|
35
|
-
# @param _instance [MessageManager]
|
36
|
-
def self.instance=_instance
|
37
|
-
@instance = _instance
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
1
|
+
module GameOverseer
|
2
|
+
|
3
|
+
# Handles sending messages to clients on behalf of services
|
4
|
+
class MessageManager
|
5
|
+
MESSAGES = []
|
6
|
+
BROADCASTS = []
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
MessageManager.instance = self
|
10
|
+
end
|
11
|
+
|
12
|
+
# Send a message to a specific client
|
13
|
+
# @param client_id [Integer] ID of client
|
14
|
+
# @param string [String] message to send
|
15
|
+
# @param reliable [Boolean] whether or not packet delivery is reliable
|
16
|
+
# @param channel [Integer] What channel to send on
|
17
|
+
def message(client_id, string, reliable = false, channel = ChannelManager::CHAT)
|
18
|
+
GameOverseer::ENetServer.instance.transmit(client_id, string, reliable, channel)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
# Send a message to all connected clients
|
23
|
+
# @param string [String] message to send
|
24
|
+
# @param reliable [Boolean] whether or not packet delivery is reliable
|
25
|
+
# @param channel [Integer] What channel to send on
|
26
|
+
def broadcast(string, reliable = false, channel = ChannelManager::CHAT)
|
27
|
+
GameOverseer::ENetServer.instance.broadcast(string, reliable, channel)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [MessageManager]
|
31
|
+
def self.instance
|
32
|
+
@instance
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param _instance [MessageManager]
|
36
|
+
def self.instance=_instance
|
37
|
+
@instance = _instance
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,31 +1,34 @@
|
|
1
|
-
module GameOverseer
|
2
|
-
class JsonPacketHandler < PacketHandler
|
3
|
-
|
4
|
-
def setup
|
5
|
-
begin
|
6
|
-
require "multi_json"
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
1
|
+
module GameOverseer
|
2
|
+
class JsonPacketHandler < PacketHandler
|
3
|
+
|
4
|
+
def setup
|
5
|
+
begin
|
6
|
+
require "multi_json"
|
7
|
+
if defined?(Oj)
|
8
|
+
Oj.default_options={mode: :strict}
|
9
|
+
end
|
10
|
+
rescue LoadError
|
11
|
+
abort "MultiJson is not installed."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def pre_processor(packet, sending)
|
16
|
+
data = nil
|
17
|
+
if sending
|
18
|
+
data = MultiJson.dump(packet)
|
19
|
+
else
|
20
|
+
data = MultiJson.load(packet)
|
21
|
+
end
|
22
|
+
|
23
|
+
return data
|
24
|
+
end
|
25
|
+
|
26
|
+
def receive(client_id, packet)
|
27
|
+
_packet = pre_processor(packet, false)
|
28
|
+
end
|
29
|
+
|
30
|
+
def transmit(client_id, data)
|
31
|
+
_packet = pre_processor(data, true)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,31 +1,31 @@
|
|
1
|
-
module GameOverseer
|
2
|
-
class MessagePackPacketHandler < PacketHandler
|
3
|
-
|
4
|
-
def setup
|
5
|
-
begin
|
6
|
-
require "msgpack"
|
7
|
-
rescue LoadError
|
8
|
-
abort "msgpack is not installed."
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def pre_processor(packet, sending)
|
13
|
-
data = nil
|
14
|
-
if sending
|
15
|
-
data = packet.to_msgpack
|
16
|
-
else
|
17
|
-
data = MessagePack.unpack(packet)
|
18
|
-
end
|
19
|
-
|
20
|
-
return data
|
21
|
-
end
|
22
|
-
|
23
|
-
def receive(client_id, packet)
|
24
|
-
_packet = pre_processor(packet, false)
|
25
|
-
end
|
26
|
-
|
27
|
-
def transmit(client_id, data)
|
28
|
-
_packet = pre_processor(data, true)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
1
|
+
module GameOverseer
|
2
|
+
class MessagePackPacketHandler < PacketHandler
|
3
|
+
|
4
|
+
def setup
|
5
|
+
begin
|
6
|
+
require "msgpack"
|
7
|
+
rescue LoadError
|
8
|
+
abort "msgpack is not installed."
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def pre_processor(packet, sending)
|
13
|
+
data = nil
|
14
|
+
if sending
|
15
|
+
data = packet.to_msgpack
|
16
|
+
else
|
17
|
+
data = MessagePack.unpack(packet)
|
18
|
+
end
|
19
|
+
|
20
|
+
return data
|
21
|
+
end
|
22
|
+
|
23
|
+
def receive(client_id, packet)
|
24
|
+
_packet = pre_processor(packet, false)
|
25
|
+
end
|
26
|
+
|
27
|
+
def transmit(client_id, data)
|
28
|
+
_packet = pre_processor(data, true)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,29 +1,29 @@
|
|
1
|
-
module GameOverseer
|
2
|
-
class PacketHandler
|
3
|
-
|
4
|
-
def initialize
|
5
|
-
PacketHandler.instance = self
|
6
|
-
setup
|
7
|
-
end
|
8
|
-
|
9
|
-
def setup
|
10
|
-
end
|
11
|
-
|
12
|
-
def pre_processor(packet, sending)
|
13
|
-
end
|
14
|
-
|
15
|
-
def receive(client_id, packet)
|
16
|
-
end
|
17
|
-
|
18
|
-
def transmit(client_id, data)
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.instance
|
22
|
-
@instance
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.instance=(_instance)
|
26
|
-
@instance = _instance
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
1
|
+
module GameOverseer
|
2
|
+
class PacketHandler
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
PacketHandler.instance = self
|
6
|
+
setup
|
7
|
+
end
|
8
|
+
|
9
|
+
def setup
|
10
|
+
end
|
11
|
+
|
12
|
+
def pre_processor(packet, sending)
|
13
|
+
end
|
14
|
+
|
15
|
+
def receive(client_id, packet)
|
16
|
+
end
|
17
|
+
|
18
|
+
def transmit(client_id, data)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.instance
|
22
|
+
@instance
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.instance=(_instance)
|
26
|
+
@instance = _instance
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,126 +1,126 @@
|
|
1
|
-
module GameOverseer
|
2
|
-
|
3
|
-
# GameOverseers' connection to the world
|
4
|
-
#
|
5
|
-
# This server uses the renet library, which is C bindings for the Enet networking library
|
6
|
-
class ENetServer
|
7
|
-
# @param host [String] host or ip for the server to run on
|
8
|
-
# @param port [Integer] port for the server to run on
|
9
|
-
# @param max_clients [Integer] max number of clients that can be connected at one time
|
10
|
-
# @param channels [Integer] number of channels (See Enet documentation)
|
11
|
-
# @param download_bandwidth [Integer] max bandwidth for downloading per-second (0 is unlimited)
|
12
|
-
# @param upload_bandwidth [Integer] max bandwidth for uploading per-second (0 is unlimited)
|
13
|
-
# @return [Thread]
|
14
|
-
def initialize(host, port, packet_handler, encryption_handler, max_clients = 4, channels = 4, download_bandwidth = 0, upload_bandwidth = 0)
|
15
|
-
GameOverseer::Console.log("Server> Started on: #{host}:#{port}.")
|
16
|
-
GameOverseer::Services.enable
|
17
|
-
GameOverseer::ENetServer.instance = self
|
18
|
-
|
19
|
-
@message_manager = GameOverseer::MessageManager.instance
|
20
|
-
@channel_manager = GameOverseer::ChannelManager.instance
|
21
|
-
@client_manager = GameOverseer::ClientManager.instance
|
22
|
-
@packet_handler = packet_handler.new
|
23
|
-
@encryption_handler = encryption_handler.instance if encryption_handler
|
24
|
-
|
25
|
-
@server = ENet::Server.new(port, max_clients, channels, download_bandwidth, upload_bandwidth) # Port, max clients, channels, download bandwidth, upload bandwith
|
26
|
-
@server.use_compression(true)
|
27
|
-
@terminate = false
|
28
|
-
|
29
|
-
@server.on_connection(method(:on_connect))
|
30
|
-
@server.on_packet_receive(method(:on_packet))
|
31
|
-
@server.on_disconnection(method(:on_disconnect))
|
32
|
-
|
33
|
-
run
|
34
|
-
end
|
35
|
-
|
36
|
-
# Runs the server in a Thread,, in a loop, calling update on the server.
|
37
|
-
#
|
38
|
-
# @return [Thread]
|
39
|
-
def run
|
40
|
-
Thread.new {
|
41
|
-
loop do
|
42
|
-
@server.update(1000)
|
43
|
-
break if @terminate
|
44
|
-
end
|
45
|
-
}
|
46
|
-
end
|
47
|
-
|
48
|
-
# Called when a packet is received
|
49
|
-
# @param client_id [Integer] ID of client
|
50
|
-
# @param data [String] data client sent
|
51
|
-
# @param channel [Integer] channel that this was sent to
|
52
|
-
def on_packet(client_id, data, channel)
|
53
|
-
handle_connection(client_id, data, channel)
|
54
|
-
end
|
55
|
-
|
56
|
-
# callled when a client connects
|
57
|
-
# @param client_id [Integer] ID of client
|
58
|
-
# @param ip_address [String] address of client
|
59
|
-
def on_connect(client_id, ip_address)
|
60
|
-
@client_manager.add(client_id, ip_address)
|
61
|
-
end
|
62
|
-
|
63
|
-
# callled when a client disconnects
|
64
|
-
# @param client_id [Integer] ID of client
|
65
|
-
def on_disconnect(client_id)
|
66
|
-
@client_manager.remove(client_id)
|
67
|
-
end
|
68
|
-
|
69
|
-
# send message to a specific client
|
70
|
-
# @param client_id [Integer] ID of client
|
71
|
-
# @param message [String] message to be sent to client
|
72
|
-
# @param reliable [Boolean] whether or not the packet is guaranteed to be received by the client
|
73
|
-
# @param channel [Integer] what channel to send on
|
74
|
-
def transmit(client_id, message, reliable = false, channel = ChannelManager::CHAT)
|
75
|
-
@server.send_packet(client_id, message, reliable, channel)
|
76
|
-
end
|
77
|
-
|
78
|
-
# send message to all connected clients
|
79
|
-
# @param message [String] message to be sent to clients
|
80
|
-
# @param reliable [Boolean] whether or not the packet is guaranteed to be received by the clients
|
81
|
-
# @param channel [Integer] what channel to send on
|
82
|
-
def broadcast(message, reliable = false, channel = ChannelManager::CHAT)
|
83
|
-
@server.broadcast_packet(message, reliable, channel)
|
84
|
-
end
|
85
|
-
|
86
|
-
# send data to the InputHandler for processing
|
87
|
-
# @param data [Hash]
|
88
|
-
# @param client_id [Integer] ID of client that sent the data
|
89
|
-
def process_data(client_id, data)
|
90
|
-
GameOverseer::InputHandler.process_data(client_id, data)
|
91
|
-
end
|
92
|
-
|
93
|
-
# Handles received packets from clients and sends them through the {PacketHandler} for pre-processing, then sends it on to {#process_data}
|
94
|
-
# @param client_id [Integer]
|
95
|
-
# @param data [String] data received from client
|
96
|
-
# @param channel [Integer] channel that this packet was sent along
|
97
|
-
def handle_connection(client_id, data, channel)
|
98
|
-
_data = @packet_handler.receive(client_id, data)
|
99
|
-
if _data
|
100
|
-
process_data(client_id, _data)
|
101
|
-
else
|
102
|
-
# TODO: Better error handling :D
|
103
|
-
transmit(client_id, '{"channel":"_error", "mode":"_error", "data":{"code":400, "message":"something went wrong, likely bad data!"}}', true, ChannelManager::FAULT)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def terminate
|
108
|
-
@terminate = true
|
109
|
-
end
|
110
|
-
|
111
|
-
def self.instance
|
112
|
-
@instance
|
113
|
-
end
|
114
|
-
|
115
|
-
def self.instance=(_instance)
|
116
|
-
@instance = _instance
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
class ENetServerRunner
|
121
|
-
attr_reader :supervisor
|
122
|
-
def start(host, port, packet_handler = PacketHandler, encryption_handler = nil)
|
123
|
-
@supervisor = GameOverseer::ENetServer.new(host, port, packet_handler, encryption_handler)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
1
|
+
module GameOverseer
|
2
|
+
|
3
|
+
# GameOverseers' connection to the world
|
4
|
+
#
|
5
|
+
# This server uses the renet library, which is C bindings for the Enet networking library
|
6
|
+
class ENetServer
|
7
|
+
# @param host [String] host or ip for the server to run on
|
8
|
+
# @param port [Integer] port for the server to run on
|
9
|
+
# @param max_clients [Integer] max number of clients that can be connected at one time
|
10
|
+
# @param channels [Integer] number of channels (See Enet documentation)
|
11
|
+
# @param download_bandwidth [Integer] max bandwidth for downloading per-second (0 is unlimited)
|
12
|
+
# @param upload_bandwidth [Integer] max bandwidth for uploading per-second (0 is unlimited)
|
13
|
+
# @return [Thread]
|
14
|
+
def initialize(host, port, packet_handler, encryption_handler, max_clients = 4, channels = 4, download_bandwidth = 0, upload_bandwidth = 0)
|
15
|
+
GameOverseer::Console.log("Server> Started on: #{host}:#{port}.")
|
16
|
+
GameOverseer::Services.enable
|
17
|
+
GameOverseer::ENetServer.instance = self
|
18
|
+
|
19
|
+
@message_manager = GameOverseer::MessageManager.instance
|
20
|
+
@channel_manager = GameOverseer::ChannelManager.instance
|
21
|
+
@client_manager = GameOverseer::ClientManager.instance
|
22
|
+
@packet_handler = packet_handler.new
|
23
|
+
@encryption_handler = encryption_handler.instance if encryption_handler
|
24
|
+
|
25
|
+
@server = ENet::Server.new(port, max_clients, channels, download_bandwidth, upload_bandwidth) # Port, max clients, channels, download bandwidth, upload bandwith
|
26
|
+
@server.use_compression(true)
|
27
|
+
@terminate = false
|
28
|
+
|
29
|
+
@server.on_connection(method(:on_connect))
|
30
|
+
@server.on_packet_receive(method(:on_packet))
|
31
|
+
@server.on_disconnection(method(:on_disconnect))
|
32
|
+
|
33
|
+
run
|
34
|
+
end
|
35
|
+
|
36
|
+
# Runs the server in a Thread,, in a loop, calling update on the server.
|
37
|
+
#
|
38
|
+
# @return [Thread]
|
39
|
+
def run
|
40
|
+
Thread.new {
|
41
|
+
loop do
|
42
|
+
@server.update(1000)
|
43
|
+
break if @terminate
|
44
|
+
end
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Called when a packet is received
|
49
|
+
# @param client_id [Integer] ID of client
|
50
|
+
# @param data [String] data client sent
|
51
|
+
# @param channel [Integer] channel that this was sent to
|
52
|
+
def on_packet(client_id, data, channel)
|
53
|
+
handle_connection(client_id, data, channel)
|
54
|
+
end
|
55
|
+
|
56
|
+
# callled when a client connects
|
57
|
+
# @param client_id [Integer] ID of client
|
58
|
+
# @param ip_address [String] address of client
|
59
|
+
def on_connect(client_id, ip_address)
|
60
|
+
@client_manager.add(client_id, ip_address)
|
61
|
+
end
|
62
|
+
|
63
|
+
# callled when a client disconnects
|
64
|
+
# @param client_id [Integer] ID of client
|
65
|
+
def on_disconnect(client_id)
|
66
|
+
@client_manager.remove(client_id)
|
67
|
+
end
|
68
|
+
|
69
|
+
# send message to a specific client
|
70
|
+
# @param client_id [Integer] ID of client
|
71
|
+
# @param message [String] message to be sent to client
|
72
|
+
# @param reliable [Boolean] whether or not the packet is guaranteed to be received by the client
|
73
|
+
# @param channel [Integer] what channel to send on
|
74
|
+
def transmit(client_id, message, reliable = false, channel = ChannelManager::CHAT)
|
75
|
+
@server.send_packet(client_id, message, reliable, channel)
|
76
|
+
end
|
77
|
+
|
78
|
+
# send message to all connected clients
|
79
|
+
# @param message [String] message to be sent to clients
|
80
|
+
# @param reliable [Boolean] whether or not the packet is guaranteed to be received by the clients
|
81
|
+
# @param channel [Integer] what channel to send on
|
82
|
+
def broadcast(message, reliable = false, channel = ChannelManager::CHAT)
|
83
|
+
@server.broadcast_packet(message, reliable, channel)
|
84
|
+
end
|
85
|
+
|
86
|
+
# send data to the InputHandler for processing
|
87
|
+
# @param data [Hash]
|
88
|
+
# @param client_id [Integer] ID of client that sent the data
|
89
|
+
def process_data(client_id, data)
|
90
|
+
GameOverseer::InputHandler.process_data(client_id, data)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Handles received packets from clients and sends them through the {PacketHandler} for pre-processing, then sends it on to {#process_data}
|
94
|
+
# @param client_id [Integer]
|
95
|
+
# @param data [String] data received from client
|
96
|
+
# @param channel [Integer] channel that this packet was sent along
|
97
|
+
def handle_connection(client_id, data, channel)
|
98
|
+
_data = @packet_handler.receive(client_id, data)
|
99
|
+
if _data
|
100
|
+
process_data(client_id, _data)
|
101
|
+
else
|
102
|
+
# TODO: Better error handling :D
|
103
|
+
transmit(client_id, '{"channel":"_error", "mode":"_error", "data":{"code":400, "message":"something went wrong, likely bad data!"}}', true, ChannelManager::FAULT)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def terminate
|
108
|
+
@terminate = true
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.instance
|
112
|
+
@instance
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.instance=(_instance)
|
116
|
+
@instance = _instance
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class ENetServerRunner
|
121
|
+
attr_reader :supervisor
|
122
|
+
def start(host, port, packet_handler = PacketHandler, encryption_handler = nil)
|
123
|
+
@supervisor = GameOverseer::ENetServer.new(host, port, packet_handler, encryption_handler)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|