Skip to content

Commit

Permalink
Merge pull request #1 from argosopentech/server_refactoring
Browse files Browse the repository at this point in the history
Server refactoring
  • Loading branch information
wamiqurrehman093 authored Feb 16, 2023
2 parents 758f55a + c1eeecd commit 7589edd
Show file tree
Hide file tree
Showing 6 changed files with 304 additions and 102 deletions.
65 changes: 65 additions & 0 deletions Source/Server/HighLevelServer.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
extends Node
class_name HighLevelServer

var server = NetworkedMultiplayerENet.new()
var request_handler = null

signal user_connected(user_id)
signal user_disconnected(user_id)

func set_request_handler(new_handler):
request_handler = new_handler

func start_server(port = 1909, max_players=2000):
if server.create_server(port, max_players) == OK:
connect_server_signals()
print("The server has started.")
get_tree().network_peer = server
return true
else:
print("Unable to start the server.")
return false

func connect_server_signals():
if get_tree().is_connected("network_peer_connected", self, "client_connected"):
return
get_tree().connect("network_peer_connected", self, "client_connected")
get_tree().connect("network_peer_disconnected", self, "client_disconnected")

func client_connected(id):
print("Client %d has just connected." % [id])
emit_signal("user_connected", id)

func client_disconnected(id):
print("Client %d has just disconnected." % [id])
emit_signal("user_disconnected", id)

func send_data_to_client(id, method, data=null):
var method_info = {"purpose": "response", "method": method, "data": data}
rpc_id(id, "received_data_from_server", method_info)

remote func received_data_from_client(method_info):
var id = get_tree().get_rpc_sender_id()
print("Just received data from client %d: %s." % [id, method_info])
process_method_info(id, method_info)

func process_method_info(id, method_info):
if !request_handler: return
# method_info = {"purpose": "request", "method": "method", "data": data}
if method_info is Dictionary and method_info.has("purpose") and method_info["purpose"] == "request":
if request_handler.has_method(method_info["method"]):
if method_info["data"]:
request_handler.call_deferred(method_info["method"], id, method_info["data"])
else:
request_handler.call_deferred(method_info["method"], id)

func stop_server():
disconnect_server_signals()
server.close_connection()
get_tree().network_peer = null

func disconnect_server_signals():
if !get_tree().is_connected("network_peer_connected", self, "client_connected"):
return
get_tree().disconnect("network_peer_connected", self, "client_connected")
get_tree().disconnect("network_peer_disconnected", self, "client_disconnected")
6 changes: 6 additions & 0 deletions Source/Server/HighLevelServer.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]

[ext_resource path="res://Source/Server/HighLevelServer.gd" type="Script" id=1]

[node name="HighLevelServer" type="Node"]
script = ExtResource( 1 )
241 changes: 139 additions & 102 deletions Source/Server/Server.gd
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
extends Node

export var websockets_server = true

var server = null
var hl_server = preload("res://Source/Server/HighLevelServer.tscn")
var ws_server = preload("res://Source/Server/WebSocketsServer.tscn")

const SERVER_PORT = 1909
const MAX_PLAYERS = 2000

Expand All @@ -24,136 +30,167 @@ var colors = {
}

func _ready():
connect_signals()
start_server()

func connect_signals():
get_tree().connect("network_peer_connected", self, "_player_connected")
get_tree().connect("network_peer_disconnected", self, "_player_disconnected")

func start_server():
var peer = NetworkedMultiplayerENet.new()
var error = peer.create_server(SERVER_PORT, MAX_PLAYERS)
if error == OK:
get_tree().network_peer = peer
if websockets_server:
server = ws_server.instance()
else:
print("Error creating the server: ", str(error))

func _player_connected(player_id):
server = hl_server.instance()
connect_connection_signals()
server.set_request_handler(self)
add_child(server)
server.start_server()

func connect_connection_signals():
if server.is_connected("user_connected", self, "player_connected"):
return
server.connect("user_connected", self, "player_connected")
server.connect("user_disconnected", self, "player_disconnected")

func player_connected(player_id):
players_online.append(player_id)
rpc_id(player_id, "send_player_name")
print("Plyer: " + str(player_id) + " connected.")
server.send_data_to_client(player_id, "set_player_id", player_id)
server.send_data_to_client(player_id, "send_player_name")

func _player_disconnected(player_id):
func player_disconnected(player_id):
if players_in_lobbies.has(player_id):
var reason = players_names[player_id] + " disconnected."
remove_player_from_lobby(players_in_lobbies[player_id], player_id, reason)
var data = {"lobby_code": players_in_lobbies[player_id], "lobby": lobbies[players_in_lobbies[player_id]], "reason": reason}
remove_player_from_game_lobby(player_id, data)
players_online.erase(player_id)
players_names.erase(player_id)
print("Plyer: " + str(player_id) + " disconnected.")

remote func get_player_name(player_name):
var player_id = get_tree().get_rpc_sender_id()
players_names[player_id] = player_name
print("Plyer " + str(player_id) + " has name " + player_name + ".")
func set_player_name(player_id, data):
players_names[player_id] = data["player_name"]
print("%s is set as the name for player with id: %d." % [data["player_name"], player_id])

remote func create_lobby(lobby_data: Dictionary):
# Lobby Code [ID]
func create_game_lobby(player_id, lobby_data: Dictionary):
lobby_data["code"] = lobbies.size()

# Setting players data for lobby
var player_id = get_tree().get_rpc_sender_id()
var player_number = 0 #lobby_data["players"].size()
var player_number = player_id

lobby_data["players"][player_number]["id"] = player_id
lobby_data["players"][player_number]["name"] = players_names[player_id]
lobby_data["players"][player_number]["color"] = colors[player_number]
lobby_data["players"][player_number]["color"] = get_random_color(lobby_data["players"])
lobby_data["players"][player_number]["host"] = true
lobby_data["current_players"] += 1
# Append lobbies list
lobbies[lobbies.size()] = lobby_data

players_in_lobbies[player_id] = lobby_data["code"]

# Notify player
rpc_id(player_id, "lobby_created", lobby_data)
var data = {"lobby_data": lobby_data, "player_number": player_number}
server.send_data_to_client(player_id, "game_lobby_created", data)

remote func join_lobby(lobby_code, lobby_pass):
var player_id = get_tree().get_rpc_sender_id()
func join_game_lobby(player_id, lobby_auth_info):
var reason = "Lobby does not exist!"
var lobby_code = lobby_auth_info["lobby_code"]
var lobby_pass = lobby_auth_info["lobby_pass"]
if lobbies.has(lobby_code):
if lobbies[lobby_code]["current_players"] < lobbies[lobby_code]["max_players"]:
if lobbies[lobby_code]["pass"] == lobby_pass:
var player_number = lobbies[lobby_code]["current_players"]
lobbies[lobby_code]["players"][player_number]["id"] = player_id
lobbies[lobby_code]["players"][player_number]["name"] = players_names[player_id]
lobbies[lobby_code]["players"][player_number]["color"] = colors[player_number]
var lobby = lobbies[lobby_code]
if lobby["current_players"] < lobby["max_players"]:
if lobby["pass"] == lobby_pass:
var player_number = player_id
lobby["players"][player_number] = {
"id": player_id, "name": players_names[player_id],
"color": get_random_color(lobby["players"]), "host": false
}
players_in_lobbies[player_id] = lobby_code
reason = players_names[player_id] + " has joined."
lobbies[lobby_code]["current_players"] += 1
update_lobby_to_players(lobby_code, reason)
lobby["current_players"] += 1
var data = {"lobby": lobby, "reason": reason, "player_number": player_number}
update_game_lobby_to_players(data)
return
else:
reason = "Invalid Password!"
rpc_id(player_id, "failed_to_join_lobby", reason)
else:
reason = "Lobby is full!"
rpc_id(player_id, "failed_to_join_lobby", reason)
server.send_data_to_client(player_id, "failed_to_join_game_lobby", reason)

func update_game_lobby_to_players(data):
var lobby = data["lobby"]
for p_id in lobby["players"]:
var player_id = lobby["players"][p_id]["id"]
if data.has("player_number"):
data["player_number"] = p_id
if player_id:
server.send_data_to_client(player_id, "update_game_lobby", data)

func leave_game_lobby(player_id, data):
remove_player_from_game_lobby(
player_id, {"lobby_code": data["lobby_code"], "lobby": lobbies[data["lobby_code"]], "reason": ""}
)

func kick_player_from_game_lobby(player_id, data):
var reason = "kicked"
server.send_data_to_client(data["kicked_player_id"], "kicked_from_lobby", reason)
remove_player_from_game_lobby(
data["kicked_player_id"], {"lobby_code": data["lobby_code"], "lobby": lobbies[data["lobby_code"]], "reason": reason}
)

func remove_player_from_game_lobby(player_id, data):
if not data["reason"]:
data["reason"] = players_names[player_id] + " left."
var lobby = data["lobby"]
var player_number = null
var is_host = false
for p_id in lobby["players"].keys():
if p_id != player_id:
continue
player_number = player_id
is_host = lobby["players"][player_number]["host"]
players_in_lobbies.erase(player_number)
if lobby["current_players"] == 1:
lobbies.erase(data["lobby_code"])
else:
rpc_id(player_id, "failed_to_join_lobby", reason)

func update_lobby_to_players(lobby_code, reason = ""):
for p_id in range(lobbies[lobby_code]["players"].size()):
if lobbies[lobby_code]["players"][p_id]["id"]:
rpc_id(lobbies[lobby_code]["players"][p_id]["id"], "update_lobby", lobbies[lobby_code], reason)

remote func leave_lobby(lobby_code):
var player_id = get_tree().get_rpc_sender_id()
remove_player_from_lobby(lobby_code, player_id)

remote func kick_player_from_lobby(lobby_code, player_id):
var kicker_id = get_tree().get_rpc_sender_id()
var reason = players_names[player_id] + " kicked by " + players_names[kicker_id] + "."
rpc_id(player_id, "kicked_from_lobby", reason)
remove_player_from_lobby(lobby_code, player_id, reason)

func remove_player_from_lobby(lobby_code, player_id, reason = ""):
if not reason:
reason = players_names[player_id] + " left."
if lobbies.has(lobby_code):
for p_id in range(lobbies[lobby_code]["players"].size()):
if lobbies[lobby_code]["players"][p_id]["id"] == player_id:
players_in_lobbies.erase(player_id)
for other_p_id in range(p_id, lobbies[lobby_code]["players"].size() - 1):
var color = lobbies[lobby_code]["players"][other_p_id].color
lobbies[lobby_code]["players"][other_p_id] = lobbies[lobby_code]["players"][other_p_id+1]
lobbies[lobby_code]["players"][other_p_id].color = color
lobbies[lobby_code]["players"][lobbies[lobby_code]["players"].size() - 1] = player_dictionary_template
if lobbies[lobby_code]["current_players"] == 1:
lobbies.erase(lobby_code)
else:
lobbies[lobby_code]["current_players"] -= 1
update_lobby_to_players(lobby_code, reason)
break

remote func send_active_lobbies():
var player_id = get_tree().get_rpc_sender_id()
rpc_id(player_id, "get_active_lobbies", lobbies)

func update_colors(lobby_code):
pass

remote func send_message(lobby_code, message, sender):
for i in range(lobbies[lobby_code].current_players):
var player_id = lobbies[lobby_code].players[i].id
rpc_id(player_id, "get_message", message, sender)

remote func start_game(lobby_code):
for i in range(lobbies[lobby_code].current_players):
var player_id = lobbies[lobby_code].players[i].id
rpc_id(player_id, "game_started")

remote func send_node_func_call(lobby_code, node_path, function, parameter=null):
var sender_id = get_tree().get_rpc_sender_id()
for i in range(lobbies[lobby_code].current_players):
var player_id = lobbies[lobby_code].players[i].id
if player_id != sender_id:
rpc_id(player_id, "get_node_func_call", node_path, function, parameter)
lobby["current_players"] -= 1
lobby["players"].erase(player_number)
if is_host:
lobby["players"][lobby["players"].keys()[0]]["host"] = true
update_game_lobby_to_players(data)

func send_active_game_lobbies(player_id, data=null):
server.send_data_to_client(player_id, "get_active_lobbies", lobbies)

func send_message_in_game_lobby(sender_id, data):
var lobby = lobbies[data["lobby_code"]]
for i in lobby.players:
var player_id = lobby.players[i].id
var message_info = {"sender": data["sender"], "message": data["message"]}
server.send_data_to_client(player_id, "get_message", message_info)

func start_the_game(sender_id, data):
var lobby = lobbies[data["lobby_code"]]
for i in lobby.players:
var player_id = lobby.players[i].id
server.send_data_to_client(player_id, "game_started")

func send_node_method_call(sender_id, data):
var lobby = lobbies[data["lobby_code"]]
for i in lobby.players:
var player_id = lobby.players[i].id
if player_id == sender_id: continue
server.send_data_to_client(
player_id,
"get_node_method_call", data
)

func stop_server():
server.stop_server()
disconnect_connection_signals()
server.queue_free()

func disconnect_connection_signals():
if !server.is_connected("user_connected", self, "player_connected"):
return
server.disconnect("user_connected", self, "player_connected")
server.disconnect("user_disconnected", self, "player_disconnected")

func get_random_color(players_dict):
randomize()
var color = colors[randi() % colors.size()]
var players_colors = []
for player in players_dict:
players_colors.append(players_dict[player].color)
while color in colors:
color = colors[randi() % colors.size()]
return color
Loading

0 comments on commit 7589edd

Please sign in to comment.