From 51b011e724b0effb55cfadb192e263b1f7bc060c Mon Sep 17 00:00:00 2001 From: Jibbajabbafic Date: Sat, 20 Jan 2024 23:47:04 +0000 Subject: [PATCH 1/7] feat: update Godot to 3.5.3 --- CHANGELOG.md | 3 +++ Dockerfile | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01e2dfe1..8182294d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ Types of changes: ## [Unreleased] +### Changed +- Update Godot to 3.5.3 + ### Fixed - Fix joining official servers for HTML5 builds - Only show compatible servers in HTML5 server browser (server must use HTTPS) diff --git a/Dockerfile b/Dockerfile index 4da4ad92..f320444a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM alpine:3.17.2 as base # Godot shared environment Variables -ENV GODOT_VERSION "3.5.2" +ENV GODOT_VERSION "3.5.3" ENV GODOT_EXPORT_PRESET "linux" # Install tools for downloading From d3403ffc7f9a70143b79453b676bd3ae1d960f5b Mon Sep 17 00:00:00 2001 From: Jibbajabbafic Date: Fri, 2 Feb 2024 00:39:08 +0000 Subject: [PATCH 2/7] fix(player): ensure players always trigger finish --- common/world/finish_line/finish_line.gd | 12 +++--------- common/world/player/player.gd | 10 ++++++++++ common/world/world.gd | 1 + 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/common/world/finish_line/finish_line.gd b/common/world/finish_line/finish_line.gd index db256261..556be26d 100644 --- a/common/world/finish_line/finish_line.gd +++ b/common/world/finish_line/finish_line.gd @@ -1,12 +1,6 @@ extends Node2D -var players_already_finished := [] - -func _on_FinishLineArea_body_entered(body: Node) -> void: - if players_already_finished.has(body.name): - Logger.print(self, "Player %s already finished!" % body.name) - return - if body.has_method("finish"): - body.finish() - players_already_finished.append(body.name) +func _on_FinishLineArea_body_entered(_body: Node) -> void: + # This is handled on the player now as the colliders could be unreliable at high speeds with lag + pass diff --git a/common/world/player/player.gd b/common/world/player/player.gd index 82944d28..7ce2d2ac 100644 --- a/common/world/player/player.gd +++ b/common/world/player/player.gd @@ -23,6 +23,8 @@ var coins := 0 var items := [] var checkpoint_position := Vector2() var is_bot := false +var finish_line_position := Vector2() +var is_finished := false # Movement vars var velocity: Vector2 = Vector2() @@ -35,6 +37,9 @@ func _physics_process(_delta: float) -> void: update_movement() if is_position_out_of_bounds(self.position): death("Out of bounds") + if self.position.x >= finish_line_position.x: + # Ensures players always trigger the finish + finish() func update_movement() -> void: @@ -75,6 +80,7 @@ func _on_Detect_body_entered(_body: Node) -> void: func start() -> void: enable_movement = true + is_finished = false func do_flap() -> void: @@ -161,6 +167,10 @@ func use_item() -> void: func finish() -> void: + if is_finished: + # Only call finish once per player + return + is_finished = true add_score() emit_signal("finish", self) diff --git a/common/world/world.gd b/common/world/world.gd index cb9f1239..85a51aaa 100644 --- a/common/world/world.gd +++ b/common/world/world.gd @@ -109,6 +109,7 @@ func spawn_player(player_id: int, spawn_position: Vector2, is_bot: bool) -> Node player.position = spawn_position player.enable_movement = false player.is_bot = is_bot + player.finish_line_position = level_generator.finish_line.position add_child(player) return player return null From 9e3819a36c0db12c63b40e95da7ee779318c9a5f Mon Sep 17 00:00:00 2001 From: Jibbajabbafic Date: Fri, 2 Feb 2024 01:01:45 +0000 Subject: [PATCH 3/7] fix(setup): stop host game options infinitely updating --- server/server_network.gd | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/server_network.gd b/server/server_network.gd index 84c678c7..60ba11ea 100644 --- a/server/server_network.gd +++ b/server/server_network.gd @@ -366,7 +366,10 @@ remote func receive_game_option_change(option: String, value: int) -> void: populate_bots(game_options.bots, value) game_options[option] = value Logger.print(self, "Player %s set %s to %s" % [player_id, option, value]) - rpc("receive_game_option_change", option, value) + for connected_player_id in multiplayer.get_network_connected_peers(): + # Don't send update to the host again to stop infinite update loops from lag + if not is_host_id(connected_player_id): + rpc_id(connected_player_id, "receive_game_option_change", option, value) func is_option_valid(option: String, value: int) -> bool: From 94996796c28e617dc7db442c29999dc7c4dc77b2 Mon Sep 17 00:00:00 2001 From: Jibbajabbafic Date: Fri, 2 Feb 2024 01:06:52 +0000 Subject: [PATCH 4/7] chore: update changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8182294d..0e44015d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,10 @@ Types of changes: ### Fixed - Fix joining official servers for HTML5 builds -- Only show compatible servers in HTML5 server browser (server must use HTTPS) +- Only show compatible servers in HTML5 server browser + - HTML5 builds can only connect to HTTPS hosted servers +- Fix players sometimes not triggering finish +- Fix host game options getting stuck in a loop ## [0.11.0] - 2023-09-27 From db99f2e5961905d4162cfba13d7072024b3b6225 Mon Sep 17 00:00:00 2001 From: Jibbajabbafic Date: Sun, 11 Feb 2024 22:12:17 +0000 Subject: [PATCH 5/7] feat(ui): show progress % on leaderboard --- CHANGELOG.md | 1 + client/ui/leaderboard.gd | 6 +++--- client/ui/leaderboard_entry.tscn | 12 ++++++------ client/ui/ui.gd | 2 +- server/world/world.gd | 28 +++++++++++++--------------- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e44015d..2f9f4279 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Types of changes: ### Changed - Update Godot to 3.5.3 +- Show progress % instead of score on leaderboard ### Fixed - Fix joining official servers for HTML5 builds diff --git a/client/ui/leaderboard.gd b/client/ui/leaderboard.gd index 34cdd074..a0796559 100644 --- a/client/ui/leaderboard.gd +++ b/client/ui/leaderboard.gd @@ -4,7 +4,7 @@ export var LeaderboardEntry: PackedScene func add_player( - player_name: String, colour: int, place_text: String, score: int, time: float + player_name: String, colour: int, place_text: String, progress: float, time: float ) -> void: var entry = LeaderboardEntry.instance() var player_body = entry.get_node("PlayerHolder/Player") @@ -19,8 +19,8 @@ func add_player( entry.get_node("Skull").show() else: place.text = place_text - var score_label = entry.get_node("Score") - score_label.text = str(score) + var progress_label = entry.get_node("Progress") + progress_label.text = "%3d%%" % (progress * 100) var time_label = entry.get_node("Time") if place_text.empty(): time_label.hide() diff --git a/client/ui/leaderboard_entry.tscn b/client/ui/leaderboard_entry.tscn index a777d383..e53d0c95 100644 --- a/client/ui/leaderboard_entry.tscn +++ b/client/ui/leaderboard_entry.tscn @@ -54,21 +54,21 @@ custom_fonts/font = ExtResource( 4 ) text = "Player Name" clip_text = true -[node name="Score" type="Label" parent="."] +[node name="Progress" type="Label" parent="."] margin_left = 648.0 margin_top = 8.0 -margin_right = 733.0 +margin_right = 753.0 margin_bottom = 56.0 -rect_min_size = Vector2( 85, 0 ) +rect_min_size = Vector2( 105, 0 ) theme = ExtResource( 3 ) custom_fonts/font = ExtResource( 4 ) -text = "0" +text = "100%" align = 2 [node name="Time" type="Label" parent="."] -margin_left = 753.0 +margin_left = 773.0 margin_top = 8.0 -margin_right = 1012.0 +margin_right = 1032.0 margin_bottom = 56.0 rect_clip_content = true size_flags_horizontal = 0 diff --git a/client/ui/ui.gd b/client/ui/ui.gd index ab2ba14f..20f04fdb 100644 --- a/client/ui/ui.gd +++ b/client/ui/ui.gd @@ -104,7 +104,7 @@ func show_leaderboard(player_list: Array) -> void: for player in player_list: var place_text := int2ordinal(player.place) if player.has("place") else "" var time = player.get("time", 0.0) - $Leaderboard.add_player(player.name, player.colour, place_text, player.score, time) + $Leaderboard.add_player(player.name, player.colour, place_text, player.progress, time) if Network.Client.is_host(): $Leaderboard/Footer/RestartButton.show() diff --git a/server/world/world.gd b/server/world/world.gd index 5592369c..fc1d1617 100644 --- a/server/world/world.gd +++ b/server/world/world.gd @@ -150,13 +150,7 @@ func player_lose_life(player_id: int) -> void: var death_time = time var player_info = player_list[player_id] Logger.print(self, "Player %s lost all their lives!" % [player_id]) - var death_entry = { - "player_id": player_id, - "time": death_time, - "name": player_info.name, - "colour": player_info.colour, - "score": player_info.score, - } + var death_entry = create_leaderboard_entry(player_id, death_time, player_info) # Push to front so first player to die shows up last players_died.push_front(death_entry) Network.Server.send_despawn_player(player_id) @@ -179,14 +173,8 @@ func _on_Player_finish(player: CommonPlayer) -> void: ) var player_id := int(player.name) var player_info = player_list[player_id] - var finish_entry = { - "player_id": player_id, - "place": place, - "time": finish_time, - "name": player_info.name, - "colour": player_info.colour, - "score": player_info.score, - } + var finish_entry = create_leaderboard_entry(player_id, finish_time, player_info) + finish_entry["place"] = place players_finished.push_back(finish_entry) Network.Server.send_player_finished_race(player_id, place, finish_time) ._on_Player_finish(player) @@ -199,3 +187,13 @@ func end_race() -> void: leaderboard.append_array(players_died) Network.Server.send_leaderboard(leaderboard) Logger.print(self, "Server Leaderboard: %s" % [leaderboard]) + + +func create_leaderboard_entry(player_id: int, finish_time: float, player_info: Dictionary) -> Dictionary: + return { + "player_id": player_id, + "time": finish_time, + "name": player_info.name, + "colour": player_info.colour, + "progress": float(player_info.score) / game_options.goal, + } From 4ee9ca6ecc48e21643ce9bf3f68617ad2e27f5f0 Mon Sep 17 00:00:00 2001 From: Jibbajabbafic Date: Sun, 11 Feb 2024 22:24:23 +0000 Subject: [PATCH 6/7] feat(world): save obstacle rng state for debug --- common/world/obstacles/obstacle.gd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/world/obstacles/obstacle.gd b/common/world/obstacles/obstacle.gd index 2085feaf..870d909a 100644 --- a/common/world/obstacles/obstacle.gd +++ b/common/world/obstacles/obstacle.gd @@ -5,6 +5,8 @@ class_name Obstacle export(bool) var random_height := false var generated := false +# Store the RNG state that generated this obstacle for debug +var generated_rng_state := 0 var length: int var height: int # The distance from the middle to the boundary at the top and bottom @@ -24,6 +26,7 @@ func _ready() -> void: func generate(game_rng: RandomNumberGenerator) -> void: + generated_rng_state = game_rng.get_state() do_generate(game_rng) length = calculate_length() # Generate the nav poly for the obstacles From 3fcc8c40848a1da318f5cb64e134e3a4d27297ae Mon Sep 17 00:00:00 2001 From: Jibbajabbafic Date: Sun, 11 Feb 2024 23:39:12 +0000 Subject: [PATCH 7/7] feat(ui): show progress % in game --- CHANGELOG.md | 2 +- client/ui/race_progress.gd | 10 ++++++++++ client/ui/ui.gd | 2 +- client/ui/ui.tscn | 15 +++++++++++++++ client/world/world.gd | 3 ++- common/world/player/player.gd | 5 +++++ server/world/world.gd | 14 +++++++++++++- 7 files changed, 47 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f9f4279..28ddbc4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ Types of changes: ### Changed - Update Godot to 3.5.3 -- Show progress % instead of score on leaderboard +- Show progress percentage instead of scores ### Fixed - Fix joining official servers for HTML5 builds diff --git a/client/ui/race_progress.gd b/client/ui/race_progress.gd index 21a831dc..604f394b 100644 --- a/client/ui/race_progress.gd +++ b/client/ui/race_progress.gd @@ -2,6 +2,8 @@ extends Control var PlayerMarker := preload("res://client/ui/player_marker.tscn") var players := {} +# Progress as a float indexed by player ID +var players_progress := {} var active_player_id := 0 export(NodePath) var MarkerAreaPath @@ -16,6 +18,7 @@ func add_player(player_id: int, player_colour: Color) -> void: # Default markers to below the line marker.rect_rotation = 180 players[player_id] = marker + players_progress[player_id] = 0.0 MarkerArea.add_child(marker) @@ -28,6 +31,7 @@ func remove_player(player_id: int) -> void: func set_active_player(new_player_id: int) -> void: active_player_id = new_player_id + update_progress_text() for player_id in players: if player_id == active_player_id: players[player_id].rect_rotation = 0 @@ -37,6 +41,12 @@ func set_active_player(new_player_id: int) -> void: func set_progress(player_id: int, player_progress: float) -> void: if players.has(player_id): + players_progress[player_id] = player_progress + update_progress_text() # Minus the marker size so it doesn't go past the end var max_pos = MarkerArea.rect_size.x - players[player_id].rect_size.x players[player_id].rect_position.x = min(MarkerArea.rect_size.x * player_progress, max_pos) + + +func update_progress_text() -> void: + $ActiveProgress.text = "%d%%" % (players_progress[active_player_id] * 100) diff --git a/client/ui/ui.gd b/client/ui/ui.gd index 20f04fdb..b0fe029a 100644 --- a/client/ui/ui.gd +++ b/client/ui/ui.gd @@ -102,7 +102,7 @@ func show_leaderboard(player_list: Array) -> void: $Death.hide() $Leaderboard.clear_players() for player in player_list: - var place_text := int2ordinal(player.place) if player.has("place") else "" + var place_text := int2ordinal(player.place) if player.place > 0 else "" var time = player.get("time", 0.0) $Leaderboard.add_player(player.name, player.colour, place_text, player.progress, time) diff --git a/client/ui/ui.tscn b/client/ui/ui.tscn index d71da71d..2e94635f 100644 --- a/client/ui/ui.tscn +++ b/client/ui/ui.tscn @@ -950,6 +950,7 @@ anchor_right = 1.0 anchor_bottom = 1.0 [node name="Score" type="Label" parent="Ingame/Player"] +visible = false anchor_left = 0.5 anchor_right = 0.5 margin_left = -100.0 @@ -1260,6 +1261,20 @@ margin_left = -5.0 margin_top = -32.0 margin_bottom = -32.0 +[node name="ActiveProgress" type="Label" parent="Ingame/RaceProgress"] +anchor_left = 0.5 +anchor_right = 0.5 +margin_left = -100.0 +margin_top = -47.0 +margin_right = 100.0 +margin_bottom = 1.0 +rect_min_size = Vector2( 200, 0 ) +theme = SubResource( 2 ) +custom_colors/font_color_shadow = Color( 0, 0, 0, 1 ) +custom_fonts/font = ExtResource( 2 ) +text = "0%" +align = 1 + [node name="InputControls" parent="Ingame" instance=ExtResource( 21 )] [node name="MessageBox" parent="." instance=ExtResource( 29 )] diff --git a/client/world/world.gd b/client/world/world.gd index ca038833..31e626b5 100644 --- a/client/world/world.gd +++ b/client/world/world.gd @@ -44,7 +44,7 @@ func update_player_progress() -> void: and is_instance_valid(player_entry.body) ): var player_progress: float = 0.0 - player_progress = player_entry.body.position.x / finish_line_x_pos + player_progress = player_entry.body.get_progress() $UI.RaceProgress.set_progress(player_id, player_progress) @@ -146,6 +146,7 @@ func start_game(game_seed: int, new_game_options: Dictionary, new_player_list: D assert(result == OK) $UI/Loading.set_hint_text("Generating level") $UI/Loading.start() + Network.Client.game_options = new_game_options .start_game(game_seed, new_game_options, new_player_list) if not level_generator.level_ready: # Level generator could be finished before returning to this function diff --git a/common/world/player/player.gd b/common/world/player/player.gd index 7ce2d2ac..0c7c3094 100644 --- a/common/world/player/player.gd +++ b/common/world/player/player.gd @@ -178,3 +178,8 @@ func finish() -> void: func knockback() -> void: Logger.print(self, "Knocking player %s back to %s" % [name, checkpoint_position]) set_global_position(checkpoint_position) + + +func get_progress() -> float: + # Account for body radius + return (self.position.x + 16) / finish_line_position.x diff --git a/server/world/world.gd b/server/world/world.gd index fc1d1617..1c5559a2 100644 --- a/server/world/world.gd +++ b/server/world/world.gd @@ -151,6 +151,7 @@ func player_lose_life(player_id: int) -> void: var player_info = player_list[player_id] Logger.print(self, "Player %s lost all their lives!" % [player_id]) var death_entry = create_leaderboard_entry(player_id, death_time, player_info) + death_entry["progress"] = player_info.body.get_progress() # Push to front so first player to die shows up last players_died.push_front(death_entry) Network.Server.send_despawn_player(player_id) @@ -175,6 +176,8 @@ func _on_Player_finish(player: CommonPlayer) -> void: var player_info = player_list[player_id] var finish_entry = create_leaderboard_entry(player_id, finish_time, player_info) finish_entry["place"] = place + # Always ensure finished players are at 100% + finish_entry["progress"] = 1.0 players_finished.push_back(finish_entry) Network.Server.send_player_finished_race(player_id, place, finish_time) ._on_Player_finish(player) @@ -185,15 +188,24 @@ func end_race() -> void: time_running = false var leaderboard := players_finished.duplicate() leaderboard.append_array(players_died) + leaderboard.sort_custom(self, "leaderboard_sort") Network.Server.send_leaderboard(leaderboard) Logger.print(self, "Server Leaderboard: %s" % [leaderboard]) +func leaderboard_sort(a, b) -> bool: + if a.place > 0 and b.place > 0: + return a.place < b.place + else: + return a.progress > b.progress + + func create_leaderboard_entry(player_id: int, finish_time: float, player_info: Dictionary) -> Dictionary: return { "player_id": player_id, "time": finish_time, "name": player_info.name, "colour": player_info.colour, - "progress": float(player_info.score) / game_options.goal, + "place": -1, + "progress": 0.0 }