diff --git a/AMSG_Examples/GameLogic/SpawnPoint/player_spawn_location.tscn b/AMSG_Examples/GameLogic/SpawnPoint/player_spawn_location.tscn new file mode 100644 index 0000000..2266535 --- /dev/null +++ b/AMSG_Examples/GameLogic/SpawnPoint/player_spawn_location.tscn @@ -0,0 +1,8 @@ +[gd_scene format=3 uid="uid://daj0dc45avukm"] + +[node name="PlayerSpawnLocation" type="Marker3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.91311, 7.03314, 0) + +[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="."] +_spawnable_scenes = PackedStringArray("res://AMSG_Examples/Player/Player.tscn") +spawn_path = NodePath("..") diff --git a/AMSG_Examples/Maps/LevelManager.gd b/AMSG_Examples/Maps/LevelManager.gd new file mode 100644 index 0000000..670f328 --- /dev/null +++ b/AMSG_Examples/Maps/LevelManager.gd @@ -0,0 +1,162 @@ +extends Node +class_name LevelManager +## This is responsible for spawning the player, managing the level itself +## and also includes simple UI and network connection for quick testing. + +@export_group("Test") +## It will show a network connection UI and allow you to spawn a test player character. +## Should be disabled if you have a main manu that will handle player connection, level and player spawning. +@export var enable_testing : bool = true +## The test player character that is going to be spawned +@export var player_character = preload("res://AMSG_Examples/Player/Player.tscn") +@export var testing_ui = preload("res://AMSG_Examples/UI/test_ui.tscn") +@export_group("Network") +## Default port to connect in testing +@export var port := 8313 +## Default IP Address to connect in testing +@export var ip_address_to_connect := "localhost" +@export_group("Spawn") +@export var spawn_locations : Array[Node3D] + +var singleplayer := false +var is_the_server_a_player := true #if it is peer to peer the server will also have a playable character +# Called when the node enters the scene tree for the first time. + +var spawned_test_ui : Control +func _enter_tree(): + # Start the server if Godot passed the "--server" argument, + # and start the client if Godot passed the "--client" argument. + if "--listen_server" in OS.get_cmdline_args(): + _on_server_pressed() + elif "--client" in OS.get_cmdline_args(): + _on_client_pressed() + elif "--server" in OS.get_cmdline_args(): + _on_d_server_pressed() + + if enable_testing: + spawned_test_ui = testing_ui.instantiate() + add_child(spawned_test_ui) + spawned_test_ui.listen_server_button.connect("pressed", _on_server_pressed) + spawned_test_ui.d_server_button.connect("pressed", _on_d_server_pressed) + spawned_test_ui.client_button.connect("pressed", _on_client_pressed) + spawned_test_ui.single_player_button.connect("pressed", _on_singleplayer_pressed) + spawned_test_ui.main_menu_button.connect("pressed", _on_main_menu_pressed) + spawned_test_ui.ip_textbox.connect("text_changed", _on_ip_address_text_changed) + +func _on_server_pressed(): + is_the_server_a_player = true + start_network(true) + get_window().title = "Server" + +func _on_d_server_pressed(): + is_the_server_a_player = false + start_network(true) + get_window().title = "Dedicated Server" + +func _on_client_pressed(): + start_network(false) + get_window().title = "Client" + + +func _on_singleplayer_pressed(): + single_player() + get_window().title = "Singleplayer/Offline" + + +func _on_main_menu_pressed(): + spawned_test_ui.listen_server_button.visible = true + spawned_test_ui.d_server_button.visible = true + spawned_test_ui.client_button.visible = true + spawned_test_ui.single_player_button.visible = true + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + if singleplayer: + for Spawn in spawn_locations: + for c in Spawn.get_children(): + c.queue_free() + else: + if multiplayer.is_server(): + for p in multiplayer.get_peers(): + destroy_player(p) + if is_the_server_a_player: + destroy_player(1) + multiplayer.set_multiplayer_peer(null) + + +func _input(event): + if Input.is_action_just_pressed("exit"): + _on_main_menu_pressed() + + +func _on_ip_address_text_changed(): + if spawned_test_ui.ip_textbox.text == "": + ip_address_to_connect = "localhost" + else: + ip_address_to_connect = spawned_test_ui.ip_textbox.text + + + + +######## Basic Network Handeling for testing ######## + + + +func single_player(): + singleplayer = true + spawned_test_ui.listen_server_button.visible = false + spawned_test_ui.d_server_button.visible = false + spawned_test_ui.client_button.visible = false + spawned_test_ui.single_player_button.visible = false + var p = player_character.instantiate() + spawn_locations.pick_random().add_child(p) + + +func start_network(server:bool) -> void: + singleplayer = false + spawned_test_ui.listen_server_button.visible = false + spawned_test_ui.d_server_button.visible = false + spawned_test_ui.client_button.visible = false + spawned_test_ui.single_player_button.visible = false + var peer = ENetMultiplayerPeer.new() + #on server disconnected + multiplayer.server_disconnected.connect(self.server_disconnected) + #on connection failed + multiplayer.connection_failed.connect(self.connection_failed) + if server: + + #listen to peer connections, and create new player for them + multiplayer.peer_connected.connect(self.player_joined) + #listen to peer disconnections, and destroy their players + multiplayer.peer_disconnected.connect(self.player_disconnected) + + peer.create_server(port) + multiplayer.set_multiplayer_peer(peer) + if is_the_server_a_player: + create_player(1) + print("server listening on %s" %IP.get_local_addresses()[0]) + else: + peer.create_client(ip_address_to_connect,port) + multiplayer.set_multiplayer_peer(peer) + + +func player_joined(id:int): + create_player(id) +func player_disconnected(id:int): + destroy_player(id) +func server_disconnected(): + _on_main_menu_pressed() +func connection_failed(): + print("connection failed") + + +func create_player(id: int) -> void: + var p = player_character.instantiate() + p.set_name(str(id)) + spawn_locations.pick_random().add_child(p) +# p.top_level = true + +func destroy_player(id: int) -> void: + find_child(str(id),true,false).queue_free() + + + + diff --git a/AMSG_Examples/Maps/MovementTestMap.tscn b/AMSG_Examples/Maps/MovementTestMap.tscn index c4d4ffe..b35f859 100644 --- a/AMSG_Examples/Maps/MovementTestMap.tscn +++ b/AMSG_Examples/Maps/MovementTestMap.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=12 format=3 uid="uid://mpaxkxn0fdto"] +[gd_scene load_steps=13 format=3 uid="uid://mpaxkxn0fdto"] [ext_resource type="Environment" uid="uid://cfsln575lgopi" path="res://AMSG_Examples/Maps/default_env.tres" id="1_7h7du"] -[ext_resource type="Script" path="res://AMSG_Examples/Maps/main.gd" id="1_rvsng"] +[ext_resource type="Script" path="res://AMSG_Examples/Maps/LevelManager.gd" id="1_rvsng"] +[ext_resource type="PackedScene" uid="uid://daj0dc45avukm" path="res://AMSG_Examples/GameLogic/SpawnPoint/player_spawn_location.tscn" id="2_0g8sc"] [ext_resource type="Material" uid="uid://bf6te7t23qtp3" path="res://AMSG_Examples/Maps/GridMat.tres" id="3_27oba"] [ext_resource type="Script" path="res://addons/AMSG/Interactable/Light/InteractableLight.gd" id="4_kyyln"] [ext_resource type="PackedScene" uid="uid://f1hgkwi56ss6" path="res://AMSG_Examples/3DObjects/Apple/Apple.tscn" id="6_aiuj0"] @@ -21,106 +22,11 @@ points = PackedVector3Array(1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1 [sub_resource type="SphereMesh" id="SphereMesh_frhet"] -[node name="Node" type="Node"] +[node name="Node" type="Node" node_paths=PackedStringArray("spawn_locations")] script = ExtResource("1_rvsng") +spawn_locations = [NodePath("PlayerSpawnLocation")] -[node name="ListenServer" type="Button" parent="."] -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -144.0 -offset_top = -23.0 -offset_right = -4.0 -offset_bottom = 24.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 4 -size_flags_vertical = 4 -text = "Listen Server -" - -[node name="DServer" type="Button" parent="."] -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -144.0 -offset_top = 29.0 -offset_right = -4.0 -offset_bottom = 76.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 4 -size_flags_vertical = 4 -text = "Dedicated Server -" - -[node name="Client" type="Button" parent="."] -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = 8.0 -offset_top = -23.0 -offset_right = 151.0 -offset_bottom = 24.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 4 -size_flags_vertical = 4 -text = "Client -" - -[node name="IP_address" type="TextEdit" parent="Client"] -layout_mode = 0 -offset_top = 48.0 -offset_right = 144.0 -offset_bottom = 100.0 -placeholder_text = "localhost" -metadata/_edit_layout_mode = 0 -metadata/_edit_use_custom_anchors = false - -[node name="Singleplayer" type="Button" parent="."] -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -68.0 -offset_top = -85.0 -offset_right = 75.0 -offset_bottom = -38.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 4 -size_flags_vertical = 4 -text = "Singleplayer -" - -[node name="MainMenu" type="Button" parent="."] -anchors_preset = 3 -anchor_left = 1.0 -anchor_top = 1.0 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = -143.0 -offset_top = -47.0 -grow_horizontal = 0 -grow_vertical = 0 -size_flags_horizontal = 4 -size_flags_vertical = 4 -text = "Main Menu" - -[node name="PlayerSpawnLocation" type="Node3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.91311, 7.03314, 0) - -[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="."] -_spawnable_scenes = PackedStringArray("res://AMSG_Examples/Player/Player.tscn") -spawn_path = NodePath("../PlayerSpawnLocation") +[node name="PlayerSpawnLocation" parent="." instance=ExtResource("2_0g8sc")] [node name="light" type="StaticBody3D" parent="." groups=["detectable_object"]] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.84419, 1.95787, 16.7421) @@ -378,10 +284,3 @@ mesh = SubResource("SphereMesh_frhet") transform = Transform3D(-1, 0, 8.74228e-08, 0, 1, 0, -8.74228e-08, 0, -1, 0.873827, 3.49466, 16.8514) pixel_size = 0.008 text = "Look at the red box and press F to switch the light" - -[connection signal="pressed" from="ListenServer" to="." method="_on_server_pressed"] -[connection signal="pressed" from="DServer" to="." method="_on_d_server_pressed"] -[connection signal="pressed" from="Client" to="." method="_on_client_pressed"] -[connection signal="text_changed" from="Client/IP_address" to="." method="_on_ip_address_text_changed"] -[connection signal="pressed" from="Singleplayer" to="." method="_on_singleplayer_pressed"] -[connection signal="pressed" from="MainMenu" to="." method="_on_main_menu_pressed"] diff --git a/AMSG_Examples/Maps/main.gd b/AMSG_Examples/Maps/main.gd deleted file mode 100755 index 395a0b2..0000000 --- a/AMSG_Examples/Maps/main.gd +++ /dev/null @@ -1,124 +0,0 @@ -extends Node -@export var port := 8313 -@export var ip_address_to_connect := "localhost" -var singleplayer := false -@export var PlayerCharacter = preload("res://AMSG_Examples/Player/Player.tscn") -var is_the_server_a_player := true #if it is peer to peer the server will also have a playable character -# Called when the node enters the scene tree for the first time. -func _enter_tree(): - # Start the server if Godot passed the "--server" argument, - # and start the client if Godot passed the "--client" argument. - if "--listen_server" in OS.get_cmdline_args(): - _on_server_pressed() - elif "--client" in OS.get_cmdline_args(): - _on_client_pressed() - elif "--server" in OS.get_cmdline_args(): - _on_d_server_pressed() -func single_player(): - singleplayer = true - $ListenServer.visible = false - $DServer.visible = false - $Client.visible = false - $Singleplayer.visible = false - var p = PlayerCharacter.instantiate() - $PlayerSpawnLocation.add_child(p) - -func start_network(server:bool) -> void: - singleplayer = false - $ListenServer.visible = false - $DServer.visible = false - $Client.visible = false - $Singleplayer.visible = false - var peer = ENetMultiplayerPeer.new() - #on server disconnected - multiplayer.server_disconnected.connect(self.server_disconnected) - #on connection failed - multiplayer.connection_failed.connect(self.connection_failed) - if server: - - #listen to peer connections, and create new player for them - multiplayer.peer_connected.connect(self.player_joined) - #listen to peer disconnections, and destroy their players - multiplayer.peer_disconnected.connect(self.player_disconnected) - - peer.create_server(port) - multiplayer.set_multiplayer_peer(peer) - if is_the_server_a_player: - create_player(1) - print("server listening on %s" %IP.get_local_addresses()[0]) - else: - peer.create_client(ip_address_to_connect,port) - multiplayer.set_multiplayer_peer(peer) - - -func player_joined(id:int): - create_player(id) -func player_disconnected(id:int): - destroy_player(id) -func server_disconnected(): - _on_main_menu_pressed() -func connection_failed(): - print("connection failed") - - - - -func create_player(id: int) -> void: - var p = PlayerCharacter.instantiate() - p.set_name(str(id)) - $PlayerSpawnLocation.add_child(p) -# p.top_level = true - -func destroy_player(id: int) -> void: - $PlayerSpawnLocation.get_node(str(id)).queue_free() - - - -func _on_server_pressed(): - is_the_server_a_player = true - start_network(true) - -func _on_d_server_pressed(): - is_the_server_a_player = false - start_network(true) - -func _on_client_pressed(): - start_network(false) - - -func _on_singleplayer_pressed(): - single_player() - - - -func _on_main_menu_pressed(): - $ListenServer.visible = true - $DServer.visible = true - $Client.visible = true - $Singleplayer.visible = true - Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) - if singleplayer: - for i in $PlayerSpawnLocation.get_child_count(): - $PlayerSpawnLocation.get_child(i).queue_free() - else: - if multiplayer.is_server(): - for p in multiplayer.get_peers(): - destroy_player(p) - if is_the_server_a_player: - destroy_player(1) - multiplayer.set_multiplayer_peer(null) - - -func _input(event): - if Input.is_action_just_pressed("exit"): - _on_main_menu_pressed() - - -func _on_ip_address_text_changed(): - if $Client/IP_address.text == "": - ip_address_to_connect = "localhost" - else: - ip_address_to_connect = $Client/IP_address.text - - - diff --git a/AMSG_Examples/UI/test_ui.tscn b/AMSG_Examples/UI/test_ui.tscn new file mode 100644 index 0000000..83953fa --- /dev/null +++ b/AMSG_Examples/UI/test_ui.tscn @@ -0,0 +1,103 @@ +[gd_scene load_steps=2 format=3 uid="uid://cpte38hjq65na"] + +[sub_resource type="GDScript" id="GDScript_5sjy5"] +script/source = "extends Control + + +@export var single_player_button : Button +@export var listen_server_button : Button +@export var d_server_button : Button +@export var client_button : Button +@export var main_menu_button : Button +@export var ip_textbox : TextEdit +" + +[node name="TestUI" type="Control" node_paths=PackedStringArray("single_player_button", "listen_server_button", "d_server_button", "client_button", "main_menu_button", "ip_textbox")] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = SubResource("GDScript_5sjy5") +single_player_button = NodePath("CenterContainer/VBoxContainer/HBoxContainer2/SingleplayerButton") +listen_server_button = NodePath("CenterContainer/VBoxContainer/HBoxContainer/ListenServerButton") +d_server_button = NodePath("CenterContainer/VBoxContainer/HBoxContainer/DServerButton") +client_button = NodePath("CenterContainer/VBoxContainer/HBoxContainer2/ClientButton") +main_menu_button = NodePath("MainMenuButton") +ip_textbox = NodePath("CenterContainer/VBoxContainer/HBoxContainer2/ClientButton/IP_addressTextBox") + +[node name="CenterContainer" type="CenterContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"] +custom_minimum_size = Vector2(500, 100) +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="CenterContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="ListenServerButton" type="Button" parent="CenterContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Listen Server +" + +[node name="DServerButton" type="Button" parent="CenterContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Dedicated Server +" + +[node name="HBoxContainer2" type="HBoxContainer" parent="CenterContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="ClientButton" type="Button" parent="CenterContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Client +" + +[node name="IP_addressTextBox" type="TextEdit" parent="CenterContainer/VBoxContainer/HBoxContainer2/ClientButton"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = 50.0 +offset_bottom = 50.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +placeholder_text = "localhost" +metadata/_edit_layout_mode = 0 +metadata/_edit_use_custom_anchors = false + +[node name="SingleplayerButton" type="Button" parent="CenterContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Singleplayer +" + +[node name="MainMenuButton" type="Button" parent="."] +layout_mode = 1 +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -143.0 +offset_top = -47.0 +grow_horizontal = 0 +grow_vertical = 0 +size_flags_horizontal = 4 +size_flags_vertical = 4 +text = "Main Menu"