From 2d70381d5fa9d54c9172c0da81150802942c8c77 Mon Sep 17 00:00:00 2001 From: Lurkars Date: Mon, 15 Jul 2019 22:15:29 +0200 Subject: [PATCH] lobby networking for direct hosting and debugging --- scenes/menu/lobby.tscn | 60 ++++++++++++++++++++--- scenes/menu/main.tscn | 64 +++++++++++++++++++----- scenes/player/HumanPlayer.tscn | 36 +++++++++----- scripts/game/game.gd | 87 ++++++++++++++++++++++++++++----- scripts/menu/lobby.gd | 50 +++++++++++++++---- scripts/menu/main.gd | 27 +++++++--- scripts/menu/server.gd | 9 ++-- scripts/player/HumanControls.gd | 2 +- 8 files changed, 268 insertions(+), 67 deletions(-) diff --git a/scenes/menu/lobby.tscn b/scenes/menu/lobby.tscn index 26562ac..a979b5d 100644 --- a/scenes/menu/lobby.tscn +++ b/scenes/menu/lobby.tscn @@ -1,10 +1,17 @@ -[gd_scene load_steps=6 format=2] +[gd_scene load_steps=10 format=2] [ext_resource path="res://resources/ui/theme.tres" type="Theme" id=1] [ext_resource path="res://scripts/menu/lobby.gd" type="Script" id=2] -[ext_resource path="res://resources/ui/font.tres" type="DynamicFont" id=3] -[ext_resource path="res://assets/icons/return.png" type="Texture" id=4] -[ext_resource path="res://scripts/menu/player_settings.gd" type="Script" id=5] +[ext_resource path="res://assets/icons/checkmark.png" type="Texture" id=3] +[ext_resource path="res://assets/icons/question.png" type="Texture" id=4] +[ext_resource path="res://resources/ui/font.tres" type="DynamicFont" id=5] +[ext_resource path="res://assets/icons/return.png" type="Texture" id=6] +[ext_resource path="res://scripts/menu/player_settings.gd" type="Script" id=7] +[ext_resource path="res://assets/fonts/Kenney Future Narrow.ttf" type="DynamicFontData" id=8] + +[sub_resource type="DynamicFont" id=1] +size = 100 +font_data = ExtResource( 8 ) [node name="lobby" type="Control"] anchor_right = 1.0 @@ -34,6 +41,18 @@ margin_top = 19.0 margin_right = 500.0 margin_bottom = 414.0 +[node name="ready_icon" type="Button" parent="menu/players"] +visible = false +margin_right = 12.0 +margin_bottom = 33.0 +icon = ExtResource( 3 ) + +[node name="not_ready_icon" type="Button" parent="menu/players"] +visible = false +margin_right = 12.0 +margin_bottom = 33.0 +icon = ExtResource( 4 ) + [node name="ready" type="CheckButton" parent="menu"] margin_left = 723.0 margin_top = 412.0 @@ -47,9 +66,9 @@ margin_left = 10.0 margin_top = 413.0 margin_right = 142.0 margin_bottom = 469.0 -custom_fonts/font = ExtResource( 3 ) +custom_fonts/font = ExtResource( 5 ) text = "Back" -icon = ExtResource( 4 ) +icon = ExtResource( 6 ) flat = true [node name="settings" type="Control" parent="menu"] @@ -57,7 +76,7 @@ margin_left = 513.0 margin_top = 23.0 margin_right = 878.0 margin_bottom = 240.0 -script = ExtResource( 5 ) +script = ExtResource( 7 ) [node name="name_label" type="Label" parent="menu/settings"] anchor_top = 0.5 @@ -88,7 +107,32 @@ anchor_right = 1.0 anchor_bottom = 0.5 margin_top = 46.5 margin_bottom = 79.5 -[connection signal="pressed" from="menu/ready" to="." method="_on_ready_pressed"] + +[node name="disconnected_dialog" type="AcceptDialog" parent="."] +margin_right = 138.0 +margin_bottom = 84.0 +dialog_text = "Server disconnected!" + +[node name="countdown" type="Label" parent="."] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -94.0 +margin_top = -56.5 +margin_right = 94.0 +margin_bottom = 56.5 +custom_fonts/font = SubResource( 1 ) +text = "3" +align = 1 +valign = 1 + +[node name="countdown_timer" type="Timer" parent="."] +wait_time = 3.0 +one_shot = true +[connection signal="toggled" from="menu/ready" to="." method="_on_ready_toggled"] [connection signal="pressed" from="menu/back" to="." method="_on_back_pressed"] [connection signal="text_changed" from="menu/settings/name" to="." method="_on_name_text_changed"] [connection signal="color_changed" from="menu/settings/color" to="." method="_on_color_color_changed"] +[connection signal="confirmed" from="disconnected_dialog" to="." method="_on_disconnected_dialog_confirmed"] +[connection signal="popup_hide" from="disconnected_dialog" to="." method="_on_disconnected_dialog_popup_hide"] diff --git a/scenes/menu/main.tscn b/scenes/menu/main.tscn index d9b8303..4821aec 100644 --- a/scenes/menu/main.tscn +++ b/scenes/menu/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=7 format=2] +[gd_scene load_steps=10 format=2] [ext_resource path="res://resources/ui/theme.tres" type="Theme" id=1] [ext_resource path="res://scripts/menu/main.gd" type="Script" id=2] @@ -6,6 +6,11 @@ [ext_resource path="res://assets/icons/singleplayer.png" type="Texture" id=4] [ext_resource path="res://assets/icons/wrench.png" type="Texture" id=5] [ext_resource path="res://assets/icons/power.png" type="Texture" id=6] +[ext_resource path="res://assets/icons/cpu.png" type="Texture" id=7] +[ext_resource path="res://assets/icons/exitRight.png" type="Texture" id=8] + +[sub_resource type="StyleBoxFlat" id=1] +bg_color = Color( 0.85098, 0.670588, 0.188235, 1 ) [node name="main_menu" type="Control"] anchor_right = 1.0 @@ -21,9 +26,9 @@ anchor_top = 0.5 anchor_right = 0.5 anchor_bottom = 0.5 margin_left = -155.0 -margin_top = -155.0 +margin_top = -201.5 margin_right = 155.0 -margin_bottom = 155.0 +margin_bottom = 201.5 grow_horizontal = 2 grow_vertical = 2 @@ -32,9 +37,9 @@ anchor_top = 0.5 anchor_right = 1.0 anchor_bottom = 0.5 margin_left = -0.857422 -margin_top = -153.725 +margin_top = -194.725 margin_right = -0.857422 -margin_bottom = -97.7245 +margin_bottom = -138.725 text = "Multiplayer" icon = ExtResource( 3 ) flat = true @@ -43,8 +48,8 @@ flat = true anchor_top = 0.5 anchor_right = 1.0 anchor_bottom = 0.5 -margin_top = -91.154 -margin_bottom = -35.154 +margin_top = -132.154 +margin_bottom = -76.154 text = "Practice" icon = ExtResource( 4 ) flat = true @@ -54,9 +59,9 @@ anchor_top = 0.5 anchor_right = 1.0 anchor_bottom = 0.5 margin_left = -0.572113 -margin_top = -25.128 +margin_top = -66.128 margin_right = -0.572113 -margin_bottom = 30.872 +margin_bottom = -10.128 text = "Settings" icon = ExtResource( 5 ) flat = true @@ -66,13 +71,50 @@ anchor_top = 0.5 anchor_right = 1.0 anchor_bottom = 0.5 margin_left = -0.572113 -margin_top = 98.872 +margin_top = 132.872 margin_right = -0.572113 -margin_bottom = 154.872 +margin_bottom = 188.872 text = "Quit" icon = ExtResource( 6 ) flat = true + +[node name="debug" type="Panel" parent="menu"] +margin_top = 193.0 +margin_right = 309.0 +margin_bottom = 327.0 +custom_styles/panel = SubResource( 1 ) + +[node name="debug_label" type="Label" parent="menu/debug"] +anchor_right = 1.0 +margin_top = 3.0 +margin_bottom = 60.0 +text = "debug +localhost:8128" +align = 1 +valign = 1 + +[node name="quick_host" type="Button" parent="menu/debug"] +anchor_top = 0.5 +anchor_bottom = 0.5 +margin_left = 16.3244 +margin_top = 1.68341 +margin_right = 145.324 +margin_bottom = 57.6834 +text = "Host" +icon = ExtResource( 7 ) + +[node name="quick_join" type="Button" parent="menu/debug"] +anchor_top = 0.5 +anchor_bottom = 0.5 +margin_left = 161.885 +margin_top = 2.32294 +margin_right = 290.885 +margin_bottom = 58.3229 +text = "Join" +icon = ExtResource( 8 ) [connection signal="pressed" from="menu/online" to="." method="_on_online_pressed"] [connection signal="pressed" from="menu/practice" to="." method="_on_practice_pressed"] [connection signal="pressed" from="menu/settings" to="." method="_on_settings_pressed"] [connection signal="pressed" from="menu/quit" to="." method="_on_quit_pressed"] +[connection signal="pressed" from="menu/debug/quick_host" to="." method="_on_quick_host_pressed"] +[connection signal="pressed" from="menu/debug/quick_join" to="." method="_on_quick_join_pressed"] diff --git a/scenes/player/HumanPlayer.tscn b/scenes/player/HumanPlayer.tscn index 25f8e2e..98477a4 100644 --- a/scenes/player/HumanPlayer.tscn +++ b/scenes/player/HumanPlayer.tscn @@ -1,21 +1,29 @@ -[gd_scene load_steps=7 format=2] +[gd_scene load_steps=10 format=2] [ext_resource path="res://scripts/player/HumanControls.gd" type="Script" id=1] -[ext_resource path="res://scenes/menu/ingame.tscn" type="PackedScene" id=2] -[ext_resource path="res://scripts/player/HumanInventory.gd" type="Script" id=3] -[ext_resource path="res://scenes/road/roadStraightLong.tscn" type="PackedScene" id=4] -[ext_resource path="res://scripts/player/InventoryPreview.gd" type="Script" id=5] +[ext_resource path="res://assets/fonts/Kenney Future Narrow.ttf" type="DynamicFontData" id=2] +[ext_resource path="res://scenes/menu/ingame.tscn" type="PackedScene" id=3] +[ext_resource path="res://scripts/player/HumanInventory.gd" type="Script" id=4] +[ext_resource path="res://scenes/road/roadStraightLong.tscn" type="PackedScene" id=5] +[ext_resource path="res://scripts/player/InventoryPreview.gd" type="Script" id=6] [sub_resource type="ViewportTexture" id=1] viewport_path = NodePath("inventory/viewport") +[sub_resource type="DynamicFont" id=2] +size = 11 +font_data = ExtResource( 2 ) + +[sub_resource type="DynamicFont" id=3] +size = 100 +font_data = ExtResource( 2 ) + [node name="HumanPlayer" type="Spatial"] script = ExtResource( 1 ) [node name="hud" type="CanvasLayer" parent="."] [node name="inventory" type="Control" parent="hud"] -visible = false anchor_right = 1.0 anchor_bottom = 1.0 @@ -42,11 +50,12 @@ margin_right = 75.0 margin_bottom = 58.0 grow_horizontal = 2 grow_vertical = 2 +custom_fonts/font = SubResource( 2 ) custom_colors/font_color = Color( 0, 0, 0, 1 ) align = 1 valign = 1 -[node name="ingame_menu" parent="hud" instance=ExtResource( 2 )] +[node name="ingame_menu" parent="hud" instance=ExtResource( 3 )] visible = false [node name="speed" type="Label" parent="hud"] @@ -68,16 +77,19 @@ anchor_top = 0.5 anchor_right = 0.5 anchor_bottom = 0.5 margin_left = -20.0 -margin_top = -7.0 +margin_top = -56.5 margin_right = 20.0 -margin_bottom = 7.0 +margin_bottom = 56.5 +grow_horizontal = 2 +grow_vertical = 2 +custom_fonts/font = SubResource( 3 ) align = 1 valign = 1 uppercase = true [node name="inventory" type="Spatial" parent="."] editor/display_folded = true -script = ExtResource( 3 ) +script = ExtResource( 4 ) [node name="viewport" type="Viewport" parent="inventory"] size = Vector2( 150, 150 ) @@ -95,8 +107,8 @@ far = 20.0 [node name="view" type="Spatial" parent="inventory"] transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -50, -1000, 0 ) -[node name="roadStraightLong" parent="inventory/view" instance=ExtResource( 4 )] +[node name="roadStraightLong" parent="inventory/view" instance=ExtResource( 5 )] transform = Transform( -4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, 0, 0 ) [node name="preview" type="Spatial" parent="inventory"] -script = ExtResource( 5 ) +script = ExtResource( 6 ) diff --git a/scripts/game/game.gd b/scripts/game/game.gd index cc656d3..ef30f4a 100644 --- a/scripts/game/game.gd +++ b/scripts/game/game.gd @@ -9,13 +9,18 @@ var bot_player_scene = preload("res://scenes/player/BotPlayer.tscn") var players = {} +var game_running:bool = false + +var game_ready_timer:Timer + signal players_changed(players) signal connection_failed() signal connection_succeeded() -signal game_ready() -signal game_start() +signal server_disconnected() +signal game_ready(ready) +signal game_started() signal game_ended() -signal game_error(msg) +signal game_error(type, data) func _ready(): var arguments = {} @@ -29,11 +34,16 @@ func host_game(port:int): get_tree().set_network_peer(host) get_tree().connect("network_peer_connected", self, "_player_connected") get_tree().connect("network_peer_disconnected", self,"_player_disconnected") - get_tree().connect("server_disconnected", self, "_server_disconnected") + game_ready_timer = Timer.new() + get_tree().get_root().add_child(game_ready_timer) + game_ready_timer.set_one_shot(true) + game_ready_timer.set_wait_time(3) + game_ready_timer.connect("timeout",self,"start_game") func join_game(ip, port:int): get_tree().connect("connected_to_server", self, "_connected_ok") get_tree().connect("connection_failed", self, "_connected_fail") + get_tree().connect("server_disconnected", self, "_server_disconnected") var host = NetworkedMultiplayerENet.new() host.create_client(ip, port) get_tree().set_network_peer(host) @@ -45,17 +55,51 @@ func _connected_ok(): func _connected_fail(): get_tree().set_network_peer(null) emit_signal("connection_failed") + +func _server_disconnected(): + get_tree().set_network_peer(null) + emit_signal("server_disconnected") -remote func set_player(id, new_name:String = " ", new_color:Color = Color.black, ready:bool = false): +func _player_disconnected(id): + if (get_tree().is_network_server()): + if game_running: # Game is in progress + emit_signal("game_error", "DISCONNECTED", [id]) + # TODO! + else: + remove_player(id) + +remote func set_player(id, new_name:String = " ", new_color:Color = Color.black, new_ready:bool = false): + players[id] = {"name" : new_name, "color" : new_color, "ready" : new_ready, "prepared" : false} + emit_signal("players_changed", players) + + if get_tree().is_network_server(): + var all_ready = true + for p_id in players: + rpc_id(id, "set_player", p_id, players[p_id].name, players[p_id].color, new_ready) + rpc_id(p_id, "set_player", id, new_name, new_color, new_ready) + all_ready = all_ready && players[p_id].ready + if all_ready: + game_ready_timer.start() + print("all_ready!") + else: + game_ready_timer.stop() + emit_signal("game_ready", all_ready) + +func update_player(new_name:String = " ", new_color:Color = Color.black, new_ready:bool = false): + if get_tree().is_network_server(): + set_player(get_tree().get_network_unique_id(), new_name, new_color, new_ready) + else: + game.rpc("set_player",get_tree().get_network_unique_id(), new_name, new_color, new_ready) + +remote func remove_player(id): + players.erase(id) if (get_tree().is_network_server()): for p_id in players: - rpc_id(id, "set_player", p_id, players[p_id].name, players[p_id].color, ready) - rpc_id(p_id, "set_player", id, new_name, new_color, ready) + rpc_id(p_id, "remove_player", id) - players[id] = {"name" : new_name, "color" : new_color, "ready" : ready} emit_signal("players_changed", players) - -func prepare_game(bots:bool): + +remotesync func prepare_game(bots:bool): get_tree().set_pause(true) @@ -99,9 +143,25 @@ func prepare_game(bots:bool): bot.set_network_master(get_tree().get_network_unique_id()) _player_scene.set_start(bot_index) -remote func post_start_game(): - get_tree().set_pause(false) + rpc_id(1, "player_prepared", get_tree().get_network_unique_id()) + +func start_game(): + rpc("prepare_game", false) + +remotesync func player_prepared(id): + if (get_tree().is_network_server()): + players[id].prepared = true + var all_prepared = true + for p_id in players: + all_prepared = all_prepared && players[p_id].prepared + if all_prepared: + rpc("post_start_game") +remotesync func post_start_game(): + get_tree().set_pause(false) + game_running = true + emit_signal("game_started") + func local_game(name:String, color:Color, bots:bool): var localhost = NetworkedMultiplayerENet.new() localhost.create_server(0, 0) @@ -116,4 +176,5 @@ func quit_game(): players.clear() get_tree().set_network_peer(null) - get_tree().get_root().get_node("main_menu").show() \ No newline at end of file + get_tree().get_root().get_node("main_menu").show() + game_running = false \ No newline at end of file diff --git a/scripts/menu/lobby.gd b/scripts/menu/lobby.gd index 0e40b18..10f8b75 100644 --- a/scripts/menu/lobby.gd +++ b/scripts/menu/lobby.gd @@ -1,27 +1,44 @@ extends Control +onready var countdown_timer = get_node("countdown_timer") onready var settings = get_node("menu/settings") +onready var player_list = get_node("menu/players") func _ready(): game.connect("players_changed", self, "_players_changed") game.connect("game_ready", self, "_game_ready") game.connect("game_started", self, "_game_started") + game.connect("server_disconnected", self, "_server_disconnected") + +func _physics_process(delta): + if not countdown_timer.is_stopped(): + get_node("countdown").text = str(int(countdown_timer.get_time_left()) + 1) func _players_changed(players): - get_node("menu/players").clear() + player_list.clear() for p_id in players: var player = players[p_id] if p_id == get_tree().get_network_unique_id(): - get_node("menu/players").add_item(player.name + " (You)") + player_list.add_item(player.name + " (You)") + else: + player_list.add_item(player.name) + player_list.set_item_custom_bg_color(player_list.get_item_count()-1, player.color) + if player.ready: + player_list.set_item_icon(player_list.get_item_count()-1, player_list.get_node("ready_icon").get_button_icon()) else: - get_node("menu/players").add_item(player.name) - get_node("menu/players").set_item_custom_bg_color(get_node("menu/players").get_item_count()-1, player.color) + player_list.set_item_icon(player_list.get_item_count()-1, player_list.get_node("not_ready_icon").get_button_icon()) -func _game_ready(): - pass +func _game_ready(all_ready): + if all_ready: + get_node("countdown").show() + countdown_timer.start() + else: + countdown_timer.stop() + get_node("countdown").hide() func _game_started(): - pass + hide() + queue_free() func _on_name_text_changed(new_text): _on_player_changed() @@ -29,15 +46,28 @@ func _on_name_text_changed(new_text): func _on_color_color_changed(color): _on_player_changed() -func _on_ready_pressed(): +func _on_ready_toggled(button_pressed): _on_player_changed() + settings.get_node("name").set_editable(not button_pressed) + settings.get_node("color").set_disabled(button_pressed) func _on_player_changed(): var name = settings.get_node("name").text var color = settings.get_node("color").color var ready = get_node("menu/ready").pressed - game.set_player(get_tree().get_network_unique_id(), name, color, ready) + game.update_player(name,color,ready) func _on_back_pressed(): + game.quit_game() queue_free() - get_tree().get_root().get_node("server").show() + if get_tree().get_root().has_node("server"): + get_tree().get_root().get_node("server").show() + elif get_tree().get_root().has_node("main_menu"): + get_tree().get_root().get_node("main_menu").show() + +func _server_disconnected(): + get_node("disconnected_dialog").set_exclusive(true) + get_node("disconnected_dialog").popup_centered() + +func _on_disconnected_dialog_popup_hide(): + _on_back_pressed() diff --git a/scripts/menu/main.gd b/scripts/menu/main.gd index 3b11415..c9aea34 100644 --- a/scripts/menu/main.gd +++ b/scripts/menu/main.gd @@ -1,24 +1,37 @@ extends Control - var server_menu_scene = preload("res://scenes/menu/server.tscn") var local_menu_scene = preload("res://scenes/menu/local_game.tscn") - +var lobby_menu_scene = preload("res://scenes/menu/lobby.tscn") func _on_online_pressed(): var server_menu = server_menu_scene.instance() get_tree().get_root().add_child(server_menu) - - get_tree().get_root().get_node("main_menu").hide() + hide() func _on_practice_pressed(): var local_menu = local_menu_scene.instance() get_tree().get_root().add_child(local_menu) - - get_tree().get_root().get_node("main_menu").hide() + hide() func _on_settings_pressed(): - pass # Replace with function body. + pass func _on_quit_pressed(): get_tree().quit() + +func _on_quick_host_pressed(): + game.host_game(8128) + var lobby_menu = lobby_menu_scene.instance() + get_tree().get_root().add_child(lobby_menu) + game.set_player(get_tree().get_network_unique_id()) + hide() + +func _on_quick_join_pressed(): + game.connect("connection_succeeded", self, "_quick_connection_succeeded") + game.join_game("127.0.0.1", 8128) + +func _quick_connection_succeeded(): + var lobby_menu = lobby_menu_scene.instance() + get_tree().get_root().add_child(lobby_menu) + hide() \ No newline at end of file diff --git a/scripts/menu/server.gd b/scripts/menu/server.gd index 8a8ec70..cb70352 100644 --- a/scripts/menu/server.gd +++ b/scripts/menu/server.gd @@ -11,16 +11,15 @@ func _on_back_pressed(): queue_free() get_tree().get_root().get_node("main_menu").show() - func _on_direct_host_pressed(): var direct_host_menu = direct_host_menu_scene.instance() get_tree().get_root().add_child(direct_host_menu) - - get_tree().get_root().get_node("server").hide() + get_tree().get_root().get_node("main_menu").hide() + hide() func _on_direct_join_pressed(): var direct_join_menu = direct_join_menu_scene.instance() get_tree().get_root().add_child(direct_join_menu) - - get_tree().get_root().get_node("server").hide() + get_tree().get_root().get_node("main_menu").hide() + hide() diff --git a/scripts/player/HumanControls.gd b/scripts/player/HumanControls.gd index 01384cf..013ad19 100644 --- a/scripts/player/HumanControls.gd +++ b/scripts/player/HumanControls.gd @@ -8,7 +8,7 @@ func _physics_process(delta): if player.is_out: camera.set_speed(0.1) if player.timer.get_time_left() > 0: - get_node("hud/reset").set_text(str(int(player.timer.get_time_left()))) + get_node("hud/reset").set_text(str(int(player.timer.get_time_left()) + 1)) else: get_node("hud/reset").set_text("reset") if Input.is_action_pressed("ui_down"):