gameoverseer 0.1.2 → 0.1.3

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.
@@ -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