Multiplayer: Finalized matchmaking system.
This commit is contained in:
parent
09461d8167
commit
390db61bb6
7 changed files with 168 additions and 12 deletions
|
@ -66,6 +66,13 @@ gdscript/warnings/property_used_as_function=2
|
|||
gdscript/warnings/constant_used_as_function=2
|
||||
gdscript/warnings/function_used_as_property=2
|
||||
|
||||
[editor]
|
||||
[display]
|
||||
|
||||
run/main_run_args="--client"
|
||||
window/size/viewport_width=800
|
||||
window/size/viewport_height=600
|
||||
window/stretch/mode="canvas_items"
|
||||
window/stretch/aspect="expand"
|
||||
|
||||
[rendering]
|
||||
|
||||
environment/defaults/default_clear_color=Color(0, 0, 0, 1)
|
||||
|
|
10
scenes/ui/elements/name_label.tscn
Normal file
10
scenes/ui/elements/name_label.tscn
Normal file
|
@ -0,0 +1,10 @@
|
|||
[gd_scene format=3 uid="uid://ormc7s6yhyck"]
|
||||
|
||||
[node name="NameLabel" type="Label"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
text = "SamplePlayer"
|
||||
vertical_alignment = 1
|
20
scenes/ui/lobby.tscn
Normal file
20
scenes/ui/lobby.tscn
Normal file
|
@ -0,0 +1,20 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://dq4exc1bdyahe"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/ui/lobby.gd" id="1_gd585"]
|
||||
|
||||
[node name="Lobby" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_gd585")
|
||||
|
||||
[node name="NameContainer" type="VBoxContainer" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
16
scripts/ui/lobby.gd
Normal file
16
scripts/ui/lobby.gd
Normal file
|
@ -0,0 +1,16 @@
|
|||
extends Control
|
||||
|
||||
var label: PackedScene = preload("res://scenes/ui/elements/name_label.tscn")
|
||||
|
||||
func _ready() -> void:
|
||||
if Networking.playerlist_changed.connect(_on_playerlist_changed) != OK:
|
||||
Log.error("FAILED to connect the playerlist_changed signal to _on_playerlist_changed!", "Internal Error: Failed to connect signal.")
|
||||
_on_playerlist_changed()
|
||||
|
||||
func _on_playerlist_changed() -> void:
|
||||
for child: Label in $NameContainer.get_children():
|
||||
child.free()
|
||||
for peer: String in Networking.peers:
|
||||
var instance: Label = label.instantiate()
|
||||
instance.text = peer
|
||||
$NameContainer.add_child(instance)
|
|
@ -6,7 +6,8 @@ var ip: String = "127.0.0.1"
|
|||
var port: int = 25262
|
||||
var max_clients: int = 1024
|
||||
|
||||
var room_name: String = "sample"
|
||||
var roomname: String = "sample"
|
||||
var username: String = "sample"
|
||||
|
||||
func _ready() -> void:
|
||||
var args: PackedStringArray = OS.get_cmdline_args()
|
||||
|
@ -18,6 +19,9 @@ func _ready() -> void:
|
|||
"--logmode":
|
||||
logmode = int(args[i+1])
|
||||
skip = true
|
||||
"--username":
|
||||
username = args[i+1]
|
||||
skip = true
|
||||
"--server":
|
||||
if Networking.start_server() != OK:
|
||||
Log.error("Failed to start server! Closing application.", "Failed to start server!")
|
||||
|
@ -27,3 +31,5 @@ func _ready() -> void:
|
|||
pass # Catch in order to prevent a warning.
|
||||
_:
|
||||
Log.warning("Unknown argument: %s!" % args[i])
|
||||
else:
|
||||
skip = false
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
extends Node
|
||||
|
||||
signal playerlist_changed()
|
||||
|
||||
## Connection Code
|
||||
|
||||
# Connect the signals.
|
||||
|
@ -12,6 +14,11 @@ func _ready() -> void:
|
|||
Log.error("FAILED to connect the server_disconnected signal to _on_server_disconnected!", "Internal Error: Failed to connect signal.")
|
||||
if multiplayer.peer_disconnected.connect(_on_peer_disconnected) != OK:
|
||||
Log.error("FAILED to connect the peer_disconnected signal to _on_peer_disconnected!", "Internal Error: Failed to connect signal.")
|
||||
if playerlist_changed.connect(_on_playerlist_changed) != OK:
|
||||
Log.error("FAILED to connect the playerlist_changed signal to _on_playerlist_changed!", "Internal Error: Failed to connect signal.")
|
||||
|
||||
func _on_playerlist_changed() -> void:
|
||||
pass
|
||||
|
||||
# Start the network listener.
|
||||
func start_server() -> Error:
|
||||
|
@ -42,14 +49,17 @@ func close_network() -> void:
|
|||
|
||||
var mutex: Mutex = Mutex.new()
|
||||
var rooms: Dictionary = {}
|
||||
# peers has two different uses: On the server it is an index of all rooms with their peers, while on the client it is just a lookup table for peers and their usernames.
|
||||
var peers: Dictionary = {}
|
||||
var isManager: bool = false
|
||||
var managerID: int
|
||||
|
||||
func join_room() -> void:
|
||||
if join_server() != OK:
|
||||
Log.warning("Failed to connect to sever.")
|
||||
|
||||
func _on_connected_ok() -> void:
|
||||
if rpc_id(1, "send_roomname", Game.room_name) != OK:
|
||||
if rpc_id(1, "send_roomname", Game.roomname) != OK:
|
||||
Log.warning("Failed to send roomname!")
|
||||
|
||||
func _on_peer_disconnected(id: int) -> void:
|
||||
|
@ -91,19 +101,19 @@ func send_roomname(roomname: String) -> void:
|
|||
rooms[multiplayer.get_remote_sender_id()] = roomname
|
||||
peers[roomname] = [multiplayer.get_remote_sender_id()]
|
||||
Log.info("Room %s registered." % roomname)
|
||||
if rpc_id(multiplayer.get_remote_sender_id(), "server_response", 0) != OK:
|
||||
if rpc_id(multiplayer.get_remote_sender_id(), "server_response", 0, rooms[roomname]) != OK:
|
||||
Log.warning("Failed to send elevation reply to %d!")
|
||||
elif peers[roomname] is Array:
|
||||
# For some odd reason, Godot doesn't allow casting peers[roomname] to an Array, but this works?
|
||||
var peer_array: Array = peers[roomname]
|
||||
peer_array.append(multiplayer.get_remote_sender_id())
|
||||
peers[roomname] = peer_array
|
||||
if rpc_id(multiplayer.get_remote_sender_id(), "server_response", 1) != OK:
|
||||
if rpc_id(multiplayer.get_remote_sender_id(), "server_response", 1, rooms[roomname]) != OK:
|
||||
Log.warning("Failed to send join reply to %d!")
|
||||
Log.debug("Room %s joined by peer %d." % [roomname, multiplayer.get_remote_sender_id()])
|
||||
else:
|
||||
Log.warning("Peer %d tried to send this client a request meant for the authority!" % multiplayer.get_remote_sender_id())
|
||||
if rpc_id(multiplayer.get_remote_sender_id(), "server_response", 2) != OK:
|
||||
if rpc_id(multiplayer.get_remote_sender_id(), "server_response", 2, 0) != OK:
|
||||
Log.warning("Failed to send fail reply to %d!")
|
||||
mutex.unlock()
|
||||
|
||||
|
@ -119,11 +129,80 @@ func peer_disconnected_message() -> void:
|
|||
|
||||
# This is the initial server response, which tells the client what its role is.
|
||||
@rpc("authority", "call_remote", "reliable")
|
||||
func server_response(status: int) -> void:
|
||||
func server_response(status: int, manager: int) -> void:
|
||||
match status:
|
||||
0:
|
||||
pass # TODO: makes new room manager
|
||||
# create new room host
|
||||
isManager = true
|
||||
if get_tree().change_scene_to_file("res://scenes/ui/lobby.tscn") != OK:
|
||||
Log.error("Couldn't change to the lobby scene! Closing application.", "Couldn't change to the lobby scene!")
|
||||
peers[Game.username] = manager
|
||||
managerID = manager
|
||||
1:
|
||||
pass # TODO: makes new room member
|
||||
# create new room member
|
||||
managerID = manager
|
||||
if rpc_id(managerID, "request_playerlist", Game.username) != OK:
|
||||
Log.warning("Failed to send username to room host %d." % multiplayer.get_remote_sender_id())
|
||||
2:
|
||||
pass # TODO: server error
|
||||
Log.warning("Sent a join request to a regular peer, not the server!")
|
||||
|
||||
# This informs the server of the recently joined player.
|
||||
@rpc("any_peer", "call_remote", "reliable")
|
||||
func inform_server(roomname: String) -> void:
|
||||
mutex.lock()
|
||||
if multiplayer.get_unique_id() == 1:
|
||||
if multiplayer.get_remote_sender_id() == rooms[roomname]:
|
||||
var peer_array: Array = peers[roomname]
|
||||
peer_array.append(multiplayer.get_remote_sender_id())
|
||||
peers[roomname] = peer_array
|
||||
else:
|
||||
Log.warning("Peer %d attempted to trick the server into adding it to the room!" % multiplayer.get_remote_sender_id())
|
||||
else:
|
||||
Log.warning("Peer %d tried to send this client a request meant for the authority!" % multiplayer.get_remote_sender_id())
|
||||
mutex.unlock()
|
||||
|
||||
# Get the playerlist from the room host.
|
||||
@rpc("any_peer", "call_remote", "reliable")
|
||||
func request_playerlist(peername: String) -> void:
|
||||
if isManager:
|
||||
if !peers.has(peername):
|
||||
peers[peername] = multiplayer.get_remote_sender_id()
|
||||
if rpc_id(multiplayer.get_remote_sender_id(), "send_playerlist", 0, peers) != OK:
|
||||
Log.warning("Failed to send join status to %d." % multiplayer.get_remote_sender_id())
|
||||
if rpc_id(1, "inform_server", Game.roomname) != OK:
|
||||
Log.warning("Failed to send playerinfo to server.")
|
||||
for peer: String in peers:
|
||||
var remote_id: int = peers[peer]
|
||||
if remote_id != multiplayer.get_unique_id():
|
||||
if rpc_id(remote_id, "send_playerlist", 1, peers) != OK:
|
||||
Log.warning("Failed to send playerlist to %d." % multiplayer.get_remote_sender_id())
|
||||
if emit_signal("playerlist_changed") != OK:
|
||||
Log.warning("Couldn't emit playerlist_changed signal.")
|
||||
else:
|
||||
if rpc_id(multiplayer.get_remote_sender_id(), "send_playerlist", 2, {}) != OK:
|
||||
Log.warning("Couldn't send failure response to peer %d!" % multiplayer.get_remote_sender_id())
|
||||
Log.warning("Peer %d tried to register with name %s, which already exists!" % [multiplayer.get_remote_sender_id(), peername])
|
||||
else:
|
||||
if rpc_id(multiplayer.get_remote_sender_id(), "send_playerlist", 3, {}) != OK:
|
||||
Log.warning("Couldn't send failure response to peer %d!" % multiplayer.get_remote_sender_id())
|
||||
Log.warning("Peer %d tried to send this client a request meant for the room host!" % multiplayer.get_remote_sender_id())
|
||||
|
||||
# Recive the playerlist on the client.
|
||||
@rpc("any_peer", "call_remote", "reliable")
|
||||
func send_playerlist(status: int, newPeers: Dictionary) -> void:
|
||||
if multiplayer.get_remote_sender_id() == managerID:
|
||||
match status:
|
||||
0:
|
||||
peers = newPeers
|
||||
Log.info("Room %s successfully joined." % Game.roomname)
|
||||
if get_tree().change_scene_to_file("res://scenes/ui/lobby.tscn") != OK:
|
||||
Log.error("Couldn't change to the lobby scene! Closing application.", "Couldn't change to the lobby scene!")
|
||||
1:
|
||||
peers = newPeers
|
||||
Log.debug("Playerlist recived.")
|
||||
if emit_signal("playerlist_changed") != OK:
|
||||
Log.warning("Couldn't emit playerlist_changed signal.")
|
||||
2:
|
||||
Log.warning("Name %s is already taken in the room!" % Game.username)
|
||||
3:
|
||||
Log.warning("Sent a playerlist request to a regular peer, not the host!")
|
||||
|
|
20
start.tscn
20
start.tscn
|
@ -1,3 +1,21 @@
|
|||
[gd_scene format=3 uid="uid://dhi34ugxtgmlg"]
|
||||
|
||||
[node name="Start" type="Node2D"]
|
||||
[node name="Start" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="LoadingText" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_font_sizes/font_size = 64
|
||||
text = "Loading, Please Wait . . ."
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
|
Loading…
Reference in a new issue