diff --git a/ServerManager.gd b/ServerManager.gd index d0ce7b2..66814c3 100644 --- a/ServerManager.gd +++ b/ServerManager.gd @@ -2,6 +2,14 @@ extends Node @export var Players = {} +@rpc("authority") +func get_players(): + return Players + +@rpc("call_remote") +func add_player(id: int, name: String): + Players[id] = {"name": name} + # Called when the node enters the scene tree for the first time. func _ready() -> void: pass # Replace with function body. diff --git a/project.godot b/project.godot index eb194fc..edcf2c9 100644 --- a/project.godot +++ b/project.godot @@ -82,6 +82,11 @@ crouch={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194326,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) ] } +tab={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} [physics] diff --git a/scenes/maps/el_test.gd b/scenes/maps/el_test.gd index 1499178..db93311 100644 --- a/scenes/maps/el_test.gd +++ b/scenes/maps/el_test.gd @@ -1,5 +1,6 @@ extends Node3D +const SPAWN_RANDOM := 5.0 var player_side: String @export var player : PackedScene @onready var intro_camera = $Intro/CameraMount/IntroCamera @@ -7,22 +8,56 @@ var player_side: String @onready var spawns = $Spawns @onready var root = $'.' # Called when the node enters the scene tree for the first time. + + func _ready() -> void: + print("level ready") + + if not multiplayer.is_server(): + return + multiplayer.peer_connected.connect(add_player) + multiplayer.peer_disconnected.connect(del_player) + + for id in multiplayer.get_peers(): + add_player(id) + if not OS.has_feature("dedicated_server"): + add_player(1) + var char : Node3D = null var red_spawn: Node3D = $Spawns/Blue/SpawnArea var position := red_spawn.global_position - for i in ServerManager.Players: - print("spawning player") - char = ResourceLoader.load("res://scenes/utils/character.tscn").instantiate() - var my_random_number = RandomNumberGenerator.new().randf_range(-10.0, 10.0) - char.name = str(my_random_number) - char.global_position = position - char.global_position.x += my_random_number - root.add_child(char) - for nodes in get_children(): - print(nodes) - + #for i in ServerManager.Players: + #print("spawning player") + #char = ResourceLoader.load("res://scenes/utils/character.tscn").instantiate() + #var my_random_number = RandomNumberGenerator.new().randf_range(-2.0, 2.0) + #char.name = str(my_random_number) + #char.global_position = position + #char.global_position.x += my_random_number + #char.add_to_group("players", true) + #root.add_child(char) + #for nodes in get_children(): + #print(nodes) +func add_player(id: int): + print("add player") + var character = ResourceLoader.load("res://scenes/utils/character.tscn").instantiate() + #character.player = id + var pos := Vector2.from_angle(randf() * 2 * PI) + character.position = Vector3(pos.x * SPAWN_RANDOM * randf(), 0, pos.y * SPAWN_RANDOM * randf()) + character.name = str(id) + $Players.add_child(character, true) +func del_player(id: int): + if not $Players.has_node(str(id)): + return + $Players.get_node(str(id)).queue_free() + # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: + #print(ServerManager.get_players()) pass + +func _exit_tree() -> void: + if not multiplayer.is_server(): + return + multiplayer.peer_connected.disconnect(add_player) + multiplayer.peer_disconnected.disconnect(del_player) diff --git a/scenes/maps/el_test.tscn b/scenes/maps/el_test.tscn index 68c113d..c3c2c2b 100644 --- a/scenes/maps/el_test.tscn +++ b/scenes/maps/el_test.tscn @@ -1,8 +1,10 @@ -[gd_scene load_steps=3 format=3 uid="uid://c1v6kb00y77ij"] +[gd_scene load_steps=4 format=3 uid="uid://c1v6kb00y77ij"] [ext_resource type="Script" path="res://scenes/maps/el_test.gd" id="1_d5e7i"] [ext_resource type="PackedScene" uid="uid://clp0pm3nxovxc" path="res://assets/models/maps/el_test.glb" id="2_cnkr5"] +[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_wnbcm"] + [node name="ElTest" type="Node3D"] script = ExtResource("1_d5e7i") @@ -24,3 +26,13 @@ size = Vector3(0.100647, 1, 6.02112) [node name="SpawnArea" type="CSGBox3D" parent="Spawns/Blue"] transform = Transform3D(5.70162, 0, 0, 0, 1, 0, 0, 0, 7.97817, 21.2099, 1.78438, 1.23551) size = Vector3(0.484497, 1, 5.99213) + +[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="."] +_spawnable_scenes = PackedStringArray("res://scenes/utils/character.tscn") +spawn_path = NodePath("../Players") +spawn_limit = 4 + +[node name="Players" type="Node3D" parent="."] + +[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."] +replication_config = SubResource("SceneReplicationConfig_wnbcm") diff --git a/scenes/utils/Menu.tscn b/scenes/utils/Menu.tscn index 500f7b5..f0f645d 100644 --- a/scenes/utils/Menu.tscn +++ b/scenes/utils/Menu.tscn @@ -11,13 +11,12 @@ grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_5mxqd") -[node name="Start" type="Button" parent="."] -layout_mode = 0 -offset_left = 230.0 -offset_top = 296.0 -offset_right = 339.0 -offset_bottom = 368.0 -text = "Start" +[node name="PublishPort" type="TextEdit" parent="."] +offset_left = 242.0 +offset_top = 63.0 +offset_right = 531.0 +offset_bottom = 134.0 +text = "8888" [node name="Host" type="Button" parent="."] layout_mode = 0 @@ -35,9 +34,15 @@ offset_right = 224.0 offset_bottom = 220.0 text = "Join" +[node name="HostToJoin" type="TextEdit" parent="."] +layout_mode = 0 +offset_left = 239.0 +offset_top = 147.0 +offset_right = 528.0 +offset_bottom = 218.0 + [connection signal="player_connected" from="." to="." method="_on_player_connected"] [connection signal="player_disconnected" from="." to="." method="_on_player_disconnected"] [connection signal="server_disconnected" from="." to="." method="_on_server_disconnected"] -[connection signal="pressed" from="Start" to="." method="_on_start_pressed"] [connection signal="pressed" from="Host" to="." method="_on_host_pressed"] [connection signal="pressed" from="Join" to="." method="_on_join_pressed"] diff --git a/scenes/utils/character.tscn b/scenes/utils/character.tscn index 140a6b1..3360a91 100644 --- a/scenes/utils/character.tscn +++ b/scenes/utils/character.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=6 format=3 uid="uid://ccm77j5rkh21w"] +[gd_scene load_steps=8 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,13 @@ radius = 0.368364 height = 1.8 +[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_e7ysa"] +properties/0/path = NodePath(".:position") +properties/0/spawn = true +properties/0/replication_mode = 1 + +[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_enush"] + [node name="Character" type="Node3D"] [node name="CharacterBody3D" type="CharacterBody3D" parent="."] @@ -30,3 +37,10 @@ script = ExtResource("4_uwcjh") 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_e7ysa") + +[node name="PlayerInput" type="MultiplayerSynchronizer" parent="."] +root_path = NodePath("../MultiplayerSynchronizer") +replication_config = SubResource("SceneReplicationConfig_enush") diff --git a/scenes/utils/menu.gd b/scenes/utils/menu.gd index 4d57467..1bf9951 100644 --- a/scenes/utils/menu.gd +++ b/scenes/utils/menu.gd @@ -1,18 +1,32 @@ extends Control - +@onready var lobby_container = $VBoxContainer +var current_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) + #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: + var labels : Array[Label] = [] + if current_players != ServerManager.Players: + for player in ServerManager.Players: + print("adding a player") + var label = Label.new() + label.text = str(player) + labels.push_back(label) + + for label in labels: + print(label) + lobby_container.add_child(label) + current_players = ServerManager.Players + pass var peer = ENetMultiplayerPeer.new() @@ -21,8 +35,6 @@ signal player_connected(peer_id, player_info) signal player_disconnected(peer_id) signal server_disconnected -const PORT = 7000 -const DEFAULT_SERVER_IP = "127.0.0.1" # IPv4 localhost const MAX_CONNECTIONS = 20 var players_loaded = 0 @@ -30,16 +42,26 @@ var players_loaded = 0 var player_info = {"name": "Name"} #var players = {} +# Create a server instance here func _on_host_pressed() -> void: + var PORT = $PublishPort.text + var SERVER_IP = $HostToJoin var peer = ENetMultiplayerPeer.new() - var error = peer.create_server(PORT, MAX_CONNECTIONS) + var error = peer.create_server(int(PORT), MAX_CONNECTIONS) if error: print(error) - multiplayer.multiplayer_peer = peer - send_player_information.rpc("host", multiplayer.get_unique_id()) - ServerManager.Players[1] = player_info - player_connected.emit(1, player_info) + if "--server" in OS.get_cmdline_user_args(): + print("headless") + multiplayer.get_unique_id() + ServerManager.Players[multiplayer.get_unique_id()] = {"name": "host"} + start_game() + #else: + #multiplayer.multiplayer_peer = peer + #send_player_information.rpc("main", multiplayer.get_unique_id()) + #ServerManager.Players[1] = player_info + #play er_connected.emit(1, player_info) + return func remove_multiplayer_peer(): multiplayer.multiplayer_peer = null @@ -62,17 +84,19 @@ func player_loaded(): func _on_join_pressed() -> void: var address = '127.0.0.1' var peer = ENetMultiplayerPeer.new() - var error = peer.create_client(address, PORT) + var PORT = $PublishPort.text + var error = peer.create_client(address, int(PORT)) if error: print(error) multiplayer.multiplayer_peer = peer + ServerManager.add_player.rpc_id(1, multiplayer.get_unique_id(), "test") + start_game() + #send_player_information.rpc_id(1, "test", multiplayer.get_unique_id()) + + - - func _on_player_connected(id: Variant, player_info: Variant) -> void: - print(player_info) - send_player_information.rpc_id(1, "test", multiplayer.get_unique_id()) - _register_player.rpc_id(id, player_info) + print_debug("a player is trying to connect") @rpc("any_peer", "reliable") func _register_player(new_player_info): @@ -104,6 +128,7 @@ func _on_server_disconnected() -> void: @rpc("call_local", "any_peer") func send_player_information(name, id): if !ServerManager.Players.has(id): + print(name) ServerManager.Players[id] = { "name": name, "id": id, @@ -115,7 +140,9 @@ func send_player_information(name, id): @rpc("call_local", "reliable", "any_peer") func start_game(): - get_tree().change_scene_to_file("res://scenes/maps/el_test.tscn") + print("test") + if multiplayer.is_server(): + get_tree().change_scene_to_file("res://scenes/maps/el_test.tscn") func _on_start_pressed() -> void: start_game.rpc() diff --git a/scripts/character_controller.gd b/scripts/character_controller.gd index 3fa0572..c5eac2b 100644 --- a/scripts/character_controller.gd +++ b/scripts/character_controller.gd @@ -27,31 +27,27 @@ var grav_vel: Vector3 # Gravity velocity var jump_vel: Vector3 # Jumping velocity var is_crouch: bool = false - @onready var camera: Node3D = $UpperTorso @onready var character: Node3D = $"." - -func get_current_camera() -> Camera3D: - return $UpperTorso/ViewModelCamera - +@onready var multiplayer_synchronizer = $"../MultiplayerSynchronizer" func _ready() -> void: + set_process(get_multiplayer_authority() == multiplayer.get_unique_id()) capture_mouse() + func _unhandled_input(event: InputEvent) -> void: if event is InputEventMouseMotion: look_dir = event.relative * 0.001 if mouse_captured: _rotate_camera() - if Input.is_action_just_pressed("jump"): jumping = true + if Input.is_action_just_pressed("jump"): _jump.rpc() if Input.is_action_just_pressed("exit"): get_tree().quit() if Input.is_action_just_pressed("shot"): $UpperTorso/ViewModelCamera.shot() - if Input.is_action_just_pressed("reload"): $Body/UpperTorso/CameraMount/Camera.reload() - if Input.is_action_just_pressed("crouch"): crouch() - if Input.is_action_just_released("crouch"): uncrouch() + #if Input.is_action_just_pressed("reload"): $Body/UpperTorso/CameraMount/Camera.reload() + #if Input.is_action_just_pressed("crouch"): crouch() + #if Input.is_action_just_released("crouch"): uncrouch() - func _physics_process(delta: float) -> void: if mouse_captured: _handle_joypad_camera_rotation(delta) velocity = _walk(delta) + _gravity(delta) + _jump(delta) - move_and_slide() func capture_mouse() -> void: @@ -105,10 +101,9 @@ func _gravity(delta: float) -> Vector3: grav_vel = Vector3.ZERO if is_on_floor() else grav_vel.move_toward(Vector3(0, velocity.y - gravity, 0), gravity * delta) return grav_vel +@rpc("call_local") func _jump(delta: float) -> Vector3: - if jumping: - if is_on_floor(): jump_vel = Vector3(0, sqrt(4 * jump_height * gravity), 0) - jumping = false - return jump_vel + #if is_on_floor(): jump_vel = Vector3(0, sqrt(4 * jump_height * gravity), 0) + #return jump_vel jump_vel = Vector3.ZERO if is_on_floor() else jump_vel.move_toward(Vector3.ZERO, gravity * delta) return jump_vel diff --git a/scripts/player_input.gd b/scripts/player_input.gd new file mode 100644 index 0000000..c26799f --- /dev/null +++ b/scripts/player_input.gd @@ -0,0 +1,11 @@ +extends MultiplayerSynchronizer + + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + pass