diff --git a/scenes/entities/player.tscn b/scenes/entities/player.tscn new file mode 100644 index 0000000..cd40b3d --- /dev/null +++ b/scenes/entities/player.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=4 format=3 uid="uid://dpdxe3muj2o26"] + +[ext_resource type="Script" path="res://scripts/entities/player.gd" id="1_r7f2r"] + +[sub_resource type="CapsuleMesh" id="CapsuleMesh_yly5q"] + +[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_7frjr"] + +[node name="Player" type="CharacterBody3D"] +script = ExtResource("1_r7f2r") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("CapsuleMesh_yly5q") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("CapsuleShape3D_7frjr") + +[node name="Camera3D" type="Camera3D" parent="."] diff --git a/scenes/maps/testmap.tscn b/scenes/maps/testmap.tscn index 94448c1..716da5f 100644 --- a/scenes/maps/testmap.tscn +++ b/scenes/maps/testmap.tscn @@ -1,3 +1,28 @@ -[gd_scene format=3 uid="uid://cbyee7drds7qu"] +[gd_scene load_steps=2 format=3 uid="uid://cbyee7drds7qu"] + +[ext_resource type="Script" path="res://scripts/maps/map.gd" id="1_4npcs"] [node name="Testmap" type="Node3D"] +script = ExtResource("1_4npcs") + +[node name="CSGBox3D" type="CSGBox3D" parent="."] +use_collision = true +size = Vector3(50, 1, 50) + +[node name="PlayerSpawn" type="Node3D" parent="."] + +[node name="0" type="Node3D" parent="PlayerSpawn"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -17, 3, 0) + +[node name="1" type="Node3D" parent="PlayerSpawn"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 16, 4, 0) + +[node name="2" type="Node3D" parent="PlayerSpawn"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 15) + +[node name="Camera3D" type="Camera3D" parent="."] +transform = Transform3D(0.707107, -0.353553, 0.612372, 0, 0.866025, 0.5, -0.707107, -0.353553, 0.612372, 43, 20, 43) +current = true + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(-0.965926, 0.258819, 0, -0.224144, -0.836516, 0.5, 0.12941, 0.482963, 0.866025, 0, 0, 0) diff --git a/scripts/entities/player.gd b/scripts/entities/player.gd new file mode 100644 index 0000000..2c03047 --- /dev/null +++ b/scripts/entities/player.gd @@ -0,0 +1,55 @@ +extends CharacterBody3D + + +const SPEED: float = 5.0 +const JUMP_VELOCITY: float = 4.5 + +var activated: bool = false + +@onready +var camera: Camera3D = $Camera3D +var camera_rotation: Vector2 = Vector2(0,0) + +func _ready() -> void: + if name == Game.username: + activated = true + camera.current = true + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + + +func _physics_process(delta: float) -> void: + if activated: + if not is_on_floor(): + velocity += get_gravity() * delta + + if Input.is_action_just_pressed("ui_accept") and is_on_floor(): + velocity.y = JUMP_VELOCITY + + var input_dir: Vector2 = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") + var direction: Vector3 = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() + + if direction: + velocity.x = direction.x * SPEED + velocity.z = direction.z * SPEED + else: + velocity.x = move_toward(velocity.x, 0, SPEED) + velocity.z = move_toward(velocity.z, 0, SPEED) + + if move_and_slide(): + pass + + Networking.player_sync_call(position, rotation) + +func _input(event: InputEvent) -> void: + if event is InputEventMouseMotion and activated: + var mouse_event: InputEventMouseMotion = event + camera_rotation = mouse_event.relative * 0.01 * 0.5 + if camera.rotation.x <= 1.6 && camera_rotation.y <= 0: + camera.rotate(Vector3.RIGHT, -camera_rotation.y) + elif camera.rotation.x >= -1.6 && camera_rotation.y >= 0: + camera.rotate(Vector3.RIGHT, -camera_rotation.y) + if camera.rotation.x >= 1.6: + camera.rotation.x = 1.6 + elif camera.rotation.x <= -1.6: + camera.rotation.x = -1.6 + rotate(Vector3.DOWN, camera_rotation.x) diff --git a/scripts/maps/map.gd b/scripts/maps/map.gd new file mode 100644 index 0000000..8b9d07a --- /dev/null +++ b/scripts/maps/map.gd @@ -0,0 +1,13 @@ +extends Node3D + +var player: PackedScene = preload("res://scenes/entities/player.tscn") + +func _ready() -> void: + var spawns: Array = $PlayerSpawn.get_children() + var i: int = 0 + for peer: String in Networking.peers: + var instance: CharacterBody3D = player.instantiate() + instance.position = spawns[i].position + instance.name = peer + add_child(instance) + i += 1 diff --git a/scripts/ui/lobby.gd b/scripts/ui/lobby.gd index 2eaa977..d922988 100644 --- a/scripts/ui/lobby.gd +++ b/scripts/ui/lobby.gd @@ -24,4 +24,4 @@ func _on_playerlist_changed() -> void: func _on_start_button_pressed() -> void: - Networking.send_rpcs("start_game", ["hello", " world"]) + Networking.start_game_call() diff --git a/scripts/utils/game.gd b/scripts/utils/game.gd index c20b085..e1b4770 100644 --- a/scripts/utils/game.gd +++ b/scripts/utils/game.gd @@ -14,6 +14,7 @@ var max_clients: int = 1024 var roomname: String = "sample" var username: String = "sample" +var mapname: String = "Testmap" func _ready() -> void: var args: PackedStringArray = OS.get_cmdline_args() diff --git a/scripts/utils/networking.gd b/scripts/utils/networking.gd index 7fd3553..b092c2f 100644 --- a/scripts/utils/networking.gd +++ b/scripts/utils/networking.gd @@ -240,15 +240,40 @@ func send_playerlist(status: int, newPeers: Dictionary) -> void: ## General Game RPCs # Does RPCs to all clients. -func send_rpcs(method: String, args: Array) -> void: +func get_ids() -> Array: + var ret: Array = [] for peer: String in peers: - var id: int = peers[peer] - if rpc_id(id, method, args) != OK: - Log.warning("Failed to send the rpc %s to %d." % [method, id]) + ret.append(peers[peer]) + return ret + +func verify_id(id: int) -> bool: + if id in get_ids(): + return true + return false + +func start_game_call() -> void: + for peer: int in Networking.get_ids(): + if rpc_id(peer, "start_game") != OK: + Log.warning("Couldn't send RPC to %d!" % peer) # Starts the game. -@rpc("any_peer", "call_remote", "reliable") +@rpc("any_peer", "call_local", "reliable") func start_game() -> void: if multiplayer.get_remote_sender_id() == managerID: - if !get_tree().change_scene_to_file("res://scenes/maps/testmap.tscn"): + if get_tree().change_scene_to_file("res://scenes/maps/testmap.tscn") != OK: Log.warning("Couldn't load the map!") + +func player_sync_call(position: Vector3, rotation: Vector3) -> void: + for peer: int in Networking.get_ids(): + if rpc_id(peer, "player_sync", position, rotation) != OK: + Log.warning("Couldn't send RPC to %d!" % peer) + +# Starts the game. +@rpc("any_peer", "call_local", "reliable") +func player_sync(position: Vector3, rotation: Vector3) -> void: + if verify_id(multiplayer.get_remote_sender_id()): + for peer: String in peers: + if peers[peer] == multiplayer.get_remote_sender_id() and has_node("/root/"+Game.mapname+"/"+peer): + var player: CharacterBody3D = get_node("/root/"+Game.mapname+"/"+peer) + player.position = position + player.rotation = rotation