First working multiplayer implementation

This commit is contained in:
2025-01-23 20:24:42 +01:00
parent fe08da9d4c
commit 51842836ce
8 changed files with 129 additions and 64 deletions

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=6 format=3 uid="uid://ccm77j5rkh21w"]
[gd_scene load_steps=7 format=3 uid="uid://ccm77j5rkh21w"]
[ext_resource type="Script" path="res://scripts/character_controller.gd" id="1_sue4n"]
[ext_resource type="PackedScene" uid="uid://bmqutwuj28san" path="res://scenes/utils/view_model_camera.tscn" id="4_al83x"]
@ -9,6 +9,14 @@
radius = 0.368364
height = 1.8
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_csl3n"]
properties/0/path = NodePath(".:position")
properties/0/spawn = true
properties/0/replication_mode = 1
properties/1/path = NodePath("CharacterBody3D:position")
properties/1/spawn = true
properties/1/replication_mode = 1
[node name="Character" type="Node3D"]
[node name="CharacterBody3D" type="CharacterBody3D" parent="."]
@ -23,10 +31,12 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.71312, 0)
radius = 0.001
[node name="ViewModelCamera" parent="CharacterBody3D/UpperTorso" instance=ExtResource("4_al83x")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00122696, 0.093623, -0.179357)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00122696, 0.093623, -0.463804)
script = ExtResource("4_uwcjh")
[node name="Pistol" parent="CharacterBody3D/UpperTorso/ViewModelCamera" instance=ExtResource("5_6k7rq")]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, -0.0287516, -0.136104, -0.276055)
visible = false
script = null
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_csl3n")

View File

@ -1,22 +1,8 @@
extends Control
# Autoload named Lobby
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
multiplayer.peer_connected.connect(_on_player_connected)
multiplayer.peer_disconnected.connect(_on_player_disconnected)
multiplayer.connected_to_server.connect(_on_connected_ok)
multiplayer.connection_failed.connect(_on_connected_fail)
multiplayer.server_disconnected.connect(_on_server_disconnected)
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
pass
var peer = ENetMultiplayerPeer.new()
# These signals can be connected to by a UI lobby scene or the game scene.
signal player_connected(peer_id, player_info)
signal player_disconnected(peer_id)
signal server_disconnected
@ -25,20 +11,37 @@ const PORT = 7000
const DEFAULT_SERVER_IP = "127.0.0.1" # IPv4 localhost
const MAX_CONNECTIONS = 20
var players = {}
var my_random_number = RandomNumberGenerator.new().randf_range(-2.0, 2.0)
var player_info = {"name": str(my_random_number)}
var players_loaded = 0
var player_info = {"name": "Name"}
var players = {}
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
multiplayer.peer_connected.connect(_on_player_connected)
multiplayer.peer_disconnected.connect(_on_player_disconnected)
multiplayer.connected_to_server.connect(_on_connected_ok)
multiplayer.connection_failed.connect(_on_connected_fail)
multiplayer.server_disconnected.connect(_on_server_disconnected)
func _on_host_pressed() -> void:
func join_game(address = ""):
if address.is_empty():
address = DEFAULT_SERVER_IP
var peer = ENetMultiplayerPeer.new()
var error = peer.create_client(address, PORT)
if error:
return error
multiplayer.multiplayer_peer = peer
func create_game():
var peer = ENetMultiplayerPeer.new()
var error = peer.create_server(PORT, MAX_CONNECTIONS)
if error:
print(error)
return error
multiplayer.multiplayer_peer = peer
players[1] = player_info
player_connected.emit(1, player_info)
player_connected.emit(peer.get_unique_id(), player_info)
func remove_multiplayer_peer():
@ -47,7 +50,7 @@ func remove_multiplayer_peer():
# When the server decides to start the game from a UI scene,
# do Lobby.load_game.rpc(filepath)
@rpc("call_local", "reliable")
func load_game(game_scene_path):
func load_game():
get_tree().change_scene_to_file("res://scenes/maps/el_test.tscn")
# Every peer will call this when they have loaded the game scene.
@ -55,36 +58,35 @@ func load_game(game_scene_path):
func player_loaded():
if multiplayer.is_server():
players_loaded += 1
players_loaded = players.size()
if players_loaded == players.size():
#$/root/Game.start_game()
players_loaded = 0
func _on_join_pressed() -> void:
var address = '127.0.0.1'
var peer = ENetMultiplayerPeer.new()
var error = peer.create_client(address, PORT)
if error:
print(error)
multiplayer.multiplayer_peer = peer
func _on_player_connected(id: Variant, player_info: Variant) -> void:
print(player_info)
_register_player.rpc_id(id, player_info)
# When a peer connects, send them my player info.
# This allows transfer of all desired data for each player, not only the unique ID.
func _on_player_connected(id):
player_info = {"name": multiplayer.get_unique_id()}
_register_player.rpc_id(1, multiplayer.get_unique_id(), player_info)
@rpc("any_peer", "reliable")
func _register_player(new_player_info):
var new_player_id = multiplayer.get_remote_sender_id()
players[new_player_id] = new_player_info
player_connected.emit(new_player_id, new_player_info)
func _register_player(id: int, new_player_info):
var new_player_id: int = 1
if not multiplayer.is_server():
new_player_id = 1
else:
new_player_id = multiplayer.get_remote_sender_id()
players[id] = new_player_info
GameServerManager.players[id] = new_player_info
#player_info = {"name": str(multiplayer.get)}
player_connected.emit(id, new_player_info)
func _on_player_disconnected(id: Variant) -> void:
pass
func _on_player_disconnected(id):
players.erase(id)
player_disconnected.emit(id)
func _on_connected_ok():
var peer_id = multiplayer.get_unique_id()
players[peer_id] = player_info
@ -93,17 +95,23 @@ func _on_connected_ok():
func _on_connected_fail():
multiplayer.multiplayer_peer = null
func _on_server_disconnected() -> void:
func _on_server_disconnected():
multiplayer.multiplayer_peer = null
players.clear()
server_disconnected.emit()
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _on_host_pressed() -> void:
player_info = {"name": str(1)}
_register_player(1, player_info)
create_game()
@rpc("call_local", "reliable", "any_peer")
func start_game():
get_tree().change_scene_to_file("res://scenes/maps/el_test.tscn")
func _on_join_pressed() -> void:
join_game()
func _on_start_pressed() -> void:
start_game.rpc()
load_game.rpc()
func _process(delta: float) -> void:
pass