gameoverseer 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +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,30 +1,36 @@
1
- module GameOverseer
2
- class InputHandler
3
- def self.process_data(data, client_id)
4
- @data = data
5
- @client_id = client_id
6
- forward_to_channel_manager if data_valid?
7
- end
8
-
9
- def self.data_valid?
10
- if @data["channel"]
11
- if @data["mode"]
12
- true
13
- end
14
- end
15
- end
16
-
17
- def self.forward_to_channel_manager
18
- count = 0
19
- begin
20
- channel_manager = GameOverseer::ChannelManager.instance
21
- channel_manager.send_to_service(@data, @client_id)
22
- rescue NoMethodError => e
23
- GameOverseer::Console.log("InputHandler> #{e.to_s}")
24
- raise if count >=2
25
- count+=1
26
- retry unless count >= 2
27
- end
28
- end
29
- end
30
- 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,36 +1,42 @@
1
- module GameOverseer
2
- class MessageManager
3
- MESSAGES = []
4
- BROADCASTS = []
5
-
6
- def initialize
7
- MessageManager.instance = self
8
- end
9
-
10
- def message(client_id, string, reliable = false, channel = ChannelManager::CHAT)
11
- GameOverseer::ENetServer.instance.transmit(client_id, string, reliable, channel)
12
- GameOverseer::Console.log("MessageManager> #{string}-#{client_id}")
13
- end
14
-
15
- def broadcast(string, reliable = false, channel = ChannelManager::CHAT)
16
- GameOverseer::ENetServer.instance.broadcast(string, reliable, channel)
17
- GameOverseer::Console.log("MessageManager> #{string}-#{channel}")
18
- end
19
-
20
- def messages
21
- MESSAGES
22
- end
23
-
24
- def broadcasts
25
- BROADCASTS
26
- end
27
-
28
- def self.instance
29
- @instance
30
- end
31
-
32
- def self.instance=_instance
33
- @instance = _instance
34
- end
35
- end
36
- 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
+ GameOverseer::Console.log("MessageManager> #{string}-#{client_id}")
20
+ end
21
+
22
+
23
+ # Send a message to all connected clients
24
+ # @param string [String] message to send
25
+ # @param reliable [Boolean] whether or not packet delivery is reliable
26
+ # @param channel [Integer] What channel to send on
27
+ def broadcast(string, reliable = false, channel = ChannelManager::CHAT)
28
+ GameOverseer::ENetServer.instance.broadcast(string, reliable, channel)
29
+ GameOverseer::Console.log("MessageManager> #{string}-#{channel}")
30
+ end
31
+
32
+ # @return [MessageManager]
33
+ def self.instance
34
+ @instance
35
+ end
36
+
37
+ # @param _instance [MessageManager]
38
+ def self.instance=_instance
39
+ @instance = _instance
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,35 @@
1
+ module GameOverseer
2
+ class PacketHandler
3
+
4
+ def initialize
5
+ PacketHandler.instance = self
6
+ end
7
+
8
+ def pre_processor(packet, sending)
9
+ data = nil
10
+ if sending
11
+ data = MultiJson.dump(packet)
12
+ else
13
+ data = MultiJson.load(packet)
14
+ end
15
+
16
+ return data
17
+ end
18
+
19
+ def receive(client_id, packet)
20
+ _packet = pre_processor(packet, false)
21
+ end
22
+
23
+ def transmit(client_id, data)
24
+ _packet = pre_processor(data, true)
25
+ end
26
+
27
+ def self.instance
28
+ @instance
29
+ end
30
+
31
+ def self.instance=(_instance)
32
+ @instance = _instance
33
+ end
34
+ end
35
+ end
@@ -1,84 +1,126 @@
1
- module GameOverseer
2
- class ENetServer
3
- include Celluloid
4
-
5
- def initialize(host, port)
6
- GameOverseer::Console.log("Server> Started on: #{host}:#{port}.")
7
- GameOverseer::Services.enable
8
- GameOverseer::ENetServer.instance = self
9
-
10
- @message_manager = GameOverseer::MessageManager.instance
11
- @channel_manager = GameOverseer::ChannelManager.instance
12
- @client_manager = GameOverseer::ClientManager.instance
13
-
14
- @server = ENet::Server.new(port, 4, 4, 0, 0) # Port, max clients, channels, download bandwidth, upload bandwith
15
- @server.use_compression(true)
16
-
17
- @server.on_connection(method(:on_connect))
18
- @server.on_packet_receive(method(:on_packet))
19
- @server.on_disconnection(method(:on_disconnect))
20
-
21
- async.run
22
- end
23
-
24
- def run
25
- loop do
26
- @server.update(1000)
27
- end
28
- end
29
-
30
- def on_packet(client_id, data, channel)
31
- p "Packet: #{client_id}-#{data}-#{channel}"
32
- handle_connection(client_id, data, channel)
33
- end
34
-
35
- def on_connect(client_id, ip_address)
36
- p "Connect: #{client_id}-#{ip_address}"
37
- @client_manager.add(client_id, ip_address)
38
- end
39
-
40
- def on_disconnect(client_id)
41
- p "Disconnect: #{client_id}"
42
- @client_manager.remove(client_id)
43
- end
44
-
45
- # send message to a specific client
46
- def transmit(client_id, message, reliable = false, channel = ChannelManager::CHAT)
47
- @server.send_packet(client_id, message, reliable, channel)
48
- end
49
-
50
- # send message to all connected clients
51
- def broadcast(message, reliable = false, channel = ChannelManager::CHAT)
52
- @server.broadcast_packet(message, reliable, channel)
53
- end
54
-
55
- def process_data(data, client_id)
56
- GameOverseer::InputHandler.process_data(data, client_id)
57
- end
58
-
59
- def handle_connection(client_id, data, channel)
60
- begin
61
- data = MultiJson.load(data)
62
- process_data(data, client_id)
63
- rescue MultiJson::ParseError => e
64
- transmit(client_id, " \"channel\": \"__UNDEFINED__\", \"mode\": \"__UNDEFINED__\", \"data\": {\"code\": 400, \"message\": \"Invalid JSON received.\"}}", true, ChannelManager::FAULT)
65
- GameOverseer::Console.log("Server> Parse error: '#{e.to_s}'. Bad data: '#{data}' received from client.")
66
- end
67
- end
68
-
69
- def self.instance
70
- @instance
71
- end
72
-
73
- def self.instance=(_instance)
74
- @instance = _instance
75
- end
76
- end
77
-
78
- class ENetServerRunner
79
- attr_reader :supervisor
80
- def start(host, port)
81
- @supervisor = GameOverseer::ENetServer.new(host, port)
82
- end
83
- end
84
- 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
@@ -1,90 +1,111 @@
1
- module GameOverseer
2
- class Service
3
- attr_accessor :client_id
4
- attr_reader :safe_methods
5
-
6
- def self.inherited(subclass)
7
- Services.register(subclass)
8
- GameOverseer::Console.log "Service> added '#{subclass}' to Services::List."
9
- end
10
-
11
- def initialize
12
- if defined?(self.setup)
13
- @client_id = 0
14
- @safe_methods = []
15
- setup
16
- end
17
- end
18
-
19
- # Called before 'enable' there should be no active code here, only setup variables.
20
- def setup
21
- end
22
-
23
- # Called when services are first initialized, put active code here.
24
- def enable
25
- end
26
-
27
- # Called when a message is recieved for this channel.
28
- def process(data)
29
- end
30
-
31
- def version
32
- # Please use the sematic versioning system,
33
- # http://semver.org
34
- #
35
- # e.g.
36
- # "1.5.9"
37
- # (Major.Minor.Patch)
38
- "0.0.0-default"
39
- end
40
-
41
- # Sets methods that are safe for `data_to_method` to call
42
- def set_safe_methods(array)
43
- raise "argument must be an array or strings or symbols" unless array.is_a?(Array)
44
- @safe_methods = array
45
- end
46
-
47
- protected
48
- def channel_manager
49
- ChannelManager.instance
50
- end
51
-
52
- def message_manager
53
- MessageManager.instance
54
- end
55
-
56
- def client_manager
57
- ClientManager.instance
58
- end
59
-
60
- def data_to_method(data)
61
- @safe_methods.each do |method|
62
- if data['mode'] == method.to_s
63
- self.send(data['mode'], data)
64
- end
65
- end
66
- end
67
-
68
- # Calls Proc immediately then every milliseconds, async.
69
- def every(milliseconds, &block)
70
- Thread.new do
71
- loop do
72
- block.call
73
- sleep(milliseconds/1000.0)
74
- end
75
- end
76
- end
77
-
78
- # Calls Proc after milliseconds have passed, async.
79
- def after(milliseconds, &block)
80
- Thread.new do
81
- sleep(milliseconds/1000.0)
82
- block.call
83
- end
84
- end
85
-
86
- def log(string, color = Gosu::Color::RED)
87
- GameOverseer::Console.log_with_color(string, color)
88
- end
89
- end
90
- end
1
+ module GameOverseer
2
+
3
+ # Services are at the heart on GameOverseer
4
+ #
5
+ # Subclass this class to implement a service
6
+ class Service
7
+ attr_accessor :client_id
8
+ attr_reader :safe_methods
9
+
10
+ # Adds the class that subclassed this class to a list for activation later
11
+ # @param subclass [Service]
12
+ def self.inherited(subclass)
13
+ Services.register(subclass)
14
+ GameOverseer::Console.log "Service> added '#{subclass}' to Services::List."
15
+ end
16
+
17
+ # This method should not be overridden, you should instead implement {#setup} with no arguments
18
+ def initialize
19
+ if defined?(self.setup)
20
+ @client_id = 0
21
+ @safe_methods = []
22
+ setup
23
+ enable
24
+ end
25
+ end
26
+
27
+ # Called before {#enable} there should be no active code here, only setup variables.
28
+ def setup
29
+ end
30
+
31
+ # Called when services are first initialized, put active code here, in a thread.
32
+ def enable
33
+ end
34
+
35
+ # Called when a message is recieved for this channel.
36
+ # @param data [Hash] The data from the packet
37
+ def process(data)
38
+ end
39
+
40
+ def version
41
+ # Please use the sematic versioning system,
42
+ # http://semver.org
43
+ #
44
+ # e.g.
45
+ # "1.5.9"
46
+ # (Major.Minor.Patch)
47
+ "0.0.0-default"
48
+ end
49
+
50
+ # Sets methods that are safe for {#data_to_method} to call
51
+ # @param array [Array] Array of strings or symbols that match a method in the service class
52
+ def set_safe_methods(array)
53
+ raise "argument must be an array of strings or symbols" unless array.is_a?(Array)
54
+ @safe_methods = array
55
+ end
56
+
57
+ # @return [ChannelManager] Active instance of ChannelManager
58
+ def channel_manager
59
+ ChannelManager.instance
60
+ end
61
+
62
+ # @return [MessageManager] Instance of MessageManager
63
+ def message_manager
64
+ MessageManager.instance
65
+ end
66
+
67
+ # @return [ClientManager] Current instance of ClientManager
68
+ def client_manager
69
+ ClientManager.instance
70
+ end
71
+
72
+ # Uses the 'mode' from a packet to call the method of the same name
73
+ # @param data [Hash] data from packet
74
+ def data_to_method(data)
75
+ @safe_methods.each do |method|
76
+ if data['mode'] == method.to_s
77
+ self.send(data['mode'], data)
78
+ end
79
+ end
80
+ end
81
+
82
+ # Calls Proc immediately then every milliseconds, async.
83
+ # @param milliseconds [Integer][Float] Time to wait before calling the block
84
+ # @param block [Proc]
85
+ def every(milliseconds, &block)
86
+ Thread.new do
87
+ loop do
88
+ block.call
89
+ sleep(milliseconds/1000.0)
90
+ end
91
+ end
92
+ end
93
+
94
+ # Calls Proc after milliseconds have passed, async.
95
+ # @param milliseconds [Integer][Float] Time to wait before calling the block
96
+ # @param block [Proc]
97
+ def after(milliseconds, &block)
98
+ Thread.new do
99
+ sleep(milliseconds/1000.0)
100
+ block.call
101
+ end
102
+ end
103
+
104
+ # String to be logged
105
+ # @param string [String] text to log
106
+ # @param color [Gosu::Color] color of text in console
107
+ def log(string, color = Gosu::Color::RED)
108
+ GameOverseer::Console.log_with_color(string, color)
109
+ end
110
+ end
111
+ end