diff --git a/project.godot b/project.godot index fa05b0a..45937fb 100644 --- a/project.godot +++ b/project.godot @@ -11,7 +11,7 @@ config_version=5 [application] config/name="Open Strike" -run/main_scene="res://scenes/utils/Menu.tscn" +run/main_scene="res://scenes/utils/menus/main/main_menu.tscn" config/features=PackedStringArray("4.3", "Forward Plus") run/max_fps=120 config/icon="res://icon.svg" diff --git a/scenes/characters/placeholder.tscn b/scenes/characters/placeholder.tscn index e47b9da..1960c5d 100644 --- a/scenes/characters/placeholder.tscn +++ b/scenes/characters/placeholder.tscn @@ -10,13 +10,13 @@ height = 1.6 [sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_tl74a"] properties/0/path = NodePath(".:position") -properties/0/spawn = true +properties/0/spawn = false properties/0/replication_mode = 1 properties/1/path = NodePath(".:rotation") -properties/1/spawn = true +properties/1/spawn = false properties/1/replication_mode = 1 properties/2/path = NodePath(".:health") -properties/2/spawn = true +properties/2/spawn = false properties/2/replication_mode = 2 [sub_resource type="Animation" id="Animation_falg4"] diff --git a/scenes/maps/base/map_loader.gd b/scenes/maps/base/map_loader.gd index 3438193..69ebadf 100644 --- a/scenes/maps/base/map_loader.gd +++ b/scenes/maps/base/map_loader.gd @@ -8,6 +8,10 @@ var player_spawner: PlayerSpawnerController var object_spawner: Node3D @onready var spawn_locations: SpawnController = $SpawnLocations +func _on_player_connected(id): + if multiplayer.is_server(): + GameServerManager.load_map.rpc_id(id, GameServerManager.current_map) + # add the player to the # Called when the node enters the scene tree for the first time. func _ready() -> void: @@ -23,18 +27,22 @@ func _ready() -> void: print("Couldn't load object spawner") # add objects spawner if multiplayer.is_server(): - _spawn_player() + _spawn_player(1) + else: + _request_spawn.rpc_id(1, multiplayer.get_unique_id()) pass # Replace with function body. - # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass +@rpc("call_local", "reliable", "any_peer") +func _request_spawn(id: int): + _spawn_player(id) -func _spawn_player(): +func _spawn_player(id: int): var char : Node3D = null - player_spawner.spawn_players(spawn_locations) + player_spawner.spawn_players(spawn_locations, id) func _add_player_spawner() -> Error : if not ResourceLoader.exists(PLAYER_SPAWNER): diff --git a/scenes/maps/base/player_spawner/player_spawner.gd b/scenes/maps/base/player_spawner/player_spawner.gd index ea66f65..cb5eaaa 100644 --- a/scenes/maps/base/player_spawner/player_spawner.gd +++ b/scenes/maps/base/player_spawner/player_spawner.gd @@ -17,17 +17,17 @@ func _get_root() -> Node3D: return $Players # -- Spawn a player node and sync it across all peers -func spawn_players(spawn_location: SpawnController) -> Error: - print("spawning players") - var char : Node3D = null - print(GameServerManager.players) - for i in GameServerManager.players: - var player_data = GameServerManager.players[i] +func spawn_players(spawn_location: SpawnController, id: int) -> Error: + if multiplayer.is_server(): + var char : Node3D = null + var player_data: PlayerState = GameServerManager.players[id] char = ResourceLoader.load("res://scenes/characters/placeholder.tscn").instantiate() - char.name = "PlayerPlaceholder_" + str(player_data.name) + char.name = "PlayerPlaceholder_" + str(player_data.id) + print(player_data) var position = spawn_location.get_spawner(SpawnController.Sides.BLUE) char.global_position = position char.global_position = position - _get_spawner().spawn(char) + #_get_spawner().spawn(char) _get_root().add_child(char) - return OK + return OK + return ERR_UNAUTHORIZED diff --git a/scenes/maps/maps/lowpoly_tdm_2.tscn b/scenes/maps/maps/lowpoly_tdm_2.tscn index 482b7c4..8a03531 100644 --- a/scenes/maps/maps/lowpoly_tdm_2.tscn +++ b/scenes/maps/maps/lowpoly_tdm_2.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=73 format=4 uid="uid://dddu0t2sdcy8h"] +[gd_scene load_steps=76 format=4 uid="uid://dddu0t2sdcy8h"] [ext_resource type="Script" path="res://scenes/maps/base/map_loader.gd" id="1_innhj"] [ext_resource type="Script" path="res://scenes/maps/base/spawn_controller.gd" id="2_1ss1b"] @@ -743,6 +743,23 @@ shadow_mesh = SubResource("ArrayMesh_nywwq") [sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_ssowb"] data = PackedVector3Array(-50, -50, 50, -50, 50, 50, 50, 50, 50, -50, -50, 50, 50, 50, 50, 50, -50, 50, -50, 50, 50, -50, 50, -50, 50, 50, -50, -50, 50, 50, 50, 50, -50, 50, 50, 50, -50, 50, -50, -50, -50, -50, 50, -50, -50, -50, 50, -50, 50, -50, -50, 50, 50, -50, -50, -50, -50, -50, -50, 50, 50, -50, 50, -50, -50, -50, 50, -50, 50, 50, -50, -50, 50, -50, 50, 50, 50, 50, 50, 50, -50, 50, -50, 50, 50, 50, -50, 50, -50, -50, -50, -50, -50, -50, 50, -50, -50, 50, 50, -50, -50, -50, -50, 50, 50, -50, -50, 50) +[sub_resource type="PhysicalSkyMaterial" id="PhysicalSkyMaterial_m15vo"] + +[sub_resource type="Sky" id="Sky_8ov8p"] +sky_material = SubResource("PhysicalSkyMaterial_m15vo") +process_mode = 3 + +[sub_resource type="Environment" id="Environment_3ha0j"] +background_mode = 2 +sky = SubResource("Sky_8ov8p") +ambient_light_source = 3 +ambient_light_color = Color(1, 1, 1, 1) +reflected_light_source = 2 +glow_enabled = true +volumetric_fog_enabled = true +volumetric_fog_density = 0.4 +volumetric_fog_albedo = Color(0.574998, 0.574998, 0.574998, 1) + [node name="Map" type="Node3D"] script = ExtResource("1_innhj") @@ -935,6 +952,9 @@ shape = SubResource("ConcavePolygonShape3D_ssowb") [node name="MainLight" type="DirectionalLight3D" parent="Light"] transform = Transform3D(-0.080856, -0.707107, 0.702469, -0.0808559, 0.707107, 0.702469, -0.993441, 1.60778e-07, -0.114348, 79.2354, 89.2354, -3.02637e-06) +light_energy = 2.029 +light_indirect_energy = 3.457 +light_volumetric_fog_energy = 1.64 [node name="SpawnLocations" type="Node3D" parent="."] script = ExtResource("2_1ss1b") @@ -948,3 +968,6 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.234959, 25.2818, 2.12756) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 29.4253, 15.2112, 4.25512) [node name="Red" type="Node3D" parent="SpawnLocations"] + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_3ha0j") diff --git a/scenes/utils/menus/main/main_menu.gd b/scenes/utils/menus/main/main_menu.gd new file mode 100644 index 0000000..bb9b2d1 --- /dev/null +++ b/scenes/utils/menus/main/main_menu.gd @@ -0,0 +1,60 @@ +extends Node + +var player_manager: PlayerManager = PlayerManager.new() + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + var map_dir := DirAccess.open("res://scenes/maps/maps/") + + if map_dir: + map_dir.list_dir_begin() + var file_name = map_dir.get_next() + while file_name != "": + $UI/CreateServer/Maps.add_item(file_name) + file_name = map_dir.get_next() + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + pass + + +func _on_create_server_pressed() -> void: + $UI/CreateServer.visible = true + +func _on_join_server_pressed() -> void: + $UI/JoinServer.visible = true + + + +func _on_create_button_pressed() -> void: + var chosen_map_index = $UI/CreateServer/Maps.get_selected_items()[0] + var chosen_map = $UI/CreateServer/Maps.get_item_text(chosen_map_index) + var path_tmpl := "res://scenes/maps/maps/%s" + var path := path_tmpl % chosen_map + GameServerManager.current_map = path + var err := GameServerManager.create_server(player_manager) + if err != OK: + print("couldn't create a server") + $UI.hide() + change_level.call_deferred(load(path)) + +# Call this function deferred and only on the main authority (server). +func change_level(scene: PackedScene): + + # Remove old level if any. + var level = $LevelLoader/CurrentLevel + for c in level.get_children(): + level.remove_child(c) + c.queue_free() + # Add new level. + level.add_child(scene.instantiate()) + + +func _on_text_edit_text_changed() -> void: + player_manager.name = $UI/TextEdit.text + + +func _on_join_button_pressed() -> void: + $UI.hide() + GameServerManager.join_server(player_manager, $UI/JoinServer/IP.text, $UI/JoinServer/Port.text.to_int()) + diff --git a/scenes/utils/menus/main/main_menu.tscn b/scenes/utils/menus/main/main_menu.tscn new file mode 100644 index 0000000..acb55c7 --- /dev/null +++ b/scenes/utils/menus/main/main_menu.tscn @@ -0,0 +1,145 @@ +[gd_scene load_steps=2 format=3 uid="uid://s48rpcadnn47"] + +[ext_resource type="Script" path="res://scenes/utils/menus/main/main_menu.gd" id="1_yi7ba"] + +[node name="MainMenu" 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_yi7ba") + +[node name="LevelLoader" type="Node3D" parent="."] + +[node name="CurrentLevel" type="Node3D" parent="LevelLoader"] + +[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="LevelLoader"] +_spawnable_scenes = PackedStringArray("res://scenes/maps/maps/lowpoly_tdm_2.tscn") +spawn_path = NodePath("../CurrentLevel") +spawn_limit = 1 + +[node name="UI" type="Control" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="MainButtons" type="Control" parent="UI"] +layout_mode = 1 +anchors_preset = 10 +anchor_right = 1.0 +grow_horizontal = 2 + +[node name="CreateServer" type="Button" parent="UI/MainButtons"] +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -4.0 +offset_right = 4.0 +offset_bottom = 8.0 +grow_horizontal = 2 +text = "Create Server" + +[node name="JoinServer" type="Button" parent="UI/MainButtons"] +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = 90.0 +offset_top = 3.0 +offset_right = 203.0 +offset_bottom = 34.0 +grow_horizontal = 2 +text = "Join Server" + +[node name="CreateServer" type="Control" parent="UI"] +visible = false +layout_mode = 1 +anchors_preset = 11 +anchor_left = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -512.0 +grow_horizontal = 0 +grow_vertical = 2 + +[node name="Maps" type="ItemList" parent="UI/CreateServer"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -214.0 +offset_top = -905.0 +offset_right = 234.0 +offset_bottom = -386.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="CreateButton" type="Button" parent="UI/CreateServer"] +layout_mode = 0 +offset_left = 236.0 +offset_top = 643.0 +offset_right = 282.0 +offset_bottom = 674.0 +text = "Start" + +[node name="JoinServer" type="Control" parent="UI"] +visible = false +layout_mode = 1 +anchors_preset = 11 +anchor_left = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -567.0 +grow_horizontal = 0 +grow_vertical = 2 + +[node name="JoinButton" type="Button" parent="UI/JoinServer"] +layout_mode = 0 +offset_left = 205.0 +offset_top = 187.0 +offset_right = 251.0 +offset_bottom = 218.0 +text = "Start" + +[node name="IP" type="TextEdit" parent="UI/JoinServer"] +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -240.5 +offset_right = 240.5 +offset_bottom = 58.0 +grow_horizontal = 2 +text = "127.0.0.1" + +[node name="Port" type="TextEdit" parent="UI/JoinServer"] +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -230.0 +offset_top = 69.0 +offset_right = 228.0 +offset_bottom = 129.0 +grow_horizontal = 2 +text = "27015" + +[node name="TextEdit" type="TextEdit" parent="UI"] +layout_mode = 1 +offset_right = 481.0 +offset_bottom = 58.0 +text = "Player Name" + +[connection signal="pressed" from="UI/MainButtons/CreateServer" to="." method="_on_create_server_pressed"] +[connection signal="pressed" from="UI/MainButtons/JoinServer" to="." method="_on_join_server_pressed"] +[connection signal="pressed" from="UI/CreateServer/CreateButton" to="." method="_on_create_button_pressed"] +[connection signal="pressed" from="UI/JoinServer/JoinButton" to="." method="_on_join_button_pressed"] +[connection signal="text_changed" from="UI/TextEdit" to="." method="_on_text_edit_text_changed"] diff --git a/scripts/game_server_manager.gd b/scripts/game_server_manager.gd index 0a7a895..ddff5cd 100644 --- a/scripts/game_server_manager.gd +++ b/scripts/game_server_manager.gd @@ -1,17 +1,76 @@ extends Node var players = {} - +var current_map: String = "" var local_player_health = 0 - +var player_state_global: PlayerState = PlayerState.new() # Called when the node enters the scene tree for the first time. @rpc("reliable", "call_local") func get_player_health(id: int) -> int: return players.get(id)["health"] +func _on_connected_ok(): + var player_state := PlayerState.new() + register_player.rpc_id(1, multiplayer.get_unique_id(), player_state_global.name) + + +@rpc("any_peer", "reliable", "call_remote") +func register_player(id: int, name: String): + var player_state := PlayerState.new() + player_state.id = id + player_state.name = name + players[multiplayer.get_remote_sender_id()] = player_state + +func _on_player_connected(id): + pass + #if multiplayer.is_server(): + #GameServerManager.load_map.rpc_id(id, GameServerManager.current_map) + func _ready() -> void: + multiplayer.peer_connected.connect(_on_player_connected) + multiplayer.connected_to_server.connect(_on_connected_ok) + print("started") pass # Replace with function body. # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass + +func set_map(name: String): + current_map = name + +func create_server(player_data: PlayerManager) -> Error: + var peer = ENetMultiplayerPeer.new() + var err = peer.create_server(27015, 30) + if err: + return err + multiplayer.multiplayer_peer = peer + if DisplayServer.get_name() != "headless": + var player_state := PlayerState.new() + player_state.id = 1 + player_state.name = player_data.name + players[1] = player_state + return OK + +func join_server(player_data: PlayerManager, ip: String, port: int) -> Error: + var peer = ENetMultiplayerPeer.new() + var err = peer.create_client("127.0.0.1", 27015) + if err != OK: + return err + player_state_global.id = multiplayer.get_remote_sender_id() + player_state_global.name = player_data.name + multiplayer.multiplayer_peer = peer + register_player.rpc_id(1, player_state_global) + return OK + +@rpc("authority", "call_remote") +func load_map(map: String): + get_tree().change_scene_to_file(map) + + +func request_data_from_client(id: int): + send_data_to_server.rpc_id(id) + +@rpc("any_peer", "call_remote") +func send_data_to_server(): + pass diff --git a/scripts/player_manager.gd b/scripts/player_manager.gd new file mode 100644 index 0000000..0175cfa --- /dev/null +++ b/scripts/player_manager.gd @@ -0,0 +1,12 @@ +class_name PlayerManager extends Object + +var name: String + +# 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