TD-18: Matchmaking UI
All checks were successful
Quality Check / Linting (push) Successful in 6s
Quality Check / Linting (pull_request) Successful in 7s

This commit is contained in:
Kevin Schmidt 2025-03-05 11:35:40 +01:00
parent b1c2dd4eb5
commit f6e650b671
15 changed files with 128 additions and 71 deletions

View file

@ -114,7 +114,7 @@ custom_features=""
export_filter="all_resources" export_filter="all_resources"
include_filter="" include_filter=""
exclude_filter="" exclude_filter=""
export_path="../../../../../Downloads/TowerDefence.dmg" export_path="../../../../../Downloads/TowerDefence.app"
encryption_include_filters="" encryption_include_filters=""
encryption_exclude_filters="" encryption_exclude_filters=""
encrypt_pck=false encrypt_pck=false

View file

@ -19,6 +19,8 @@ config/icon="res://textures/icon.svg"
ConnectionChannel="*res://scripts/channel/connection/connection_channel.gd" ConnectionChannel="*res://scripts/channel/connection/connection_channel.gd"
MatchmakingChannel="*res://scripts/channel/matchmaking/matchmaking_channel.gd" MatchmakingChannel="*res://scripts/channel/matchmaking/matchmaking_channel.gd"
MatchChannel="*res://scripts/channel/match/match_channel.gd"
CurrentMatch="*res://scripts/match/current_match.gd"
[display] [display]

49
scenes/game.tscn Normal file
View file

@ -0,0 +1,49 @@
[gd_scene load_steps=3 format=3 uid="uid://co1x3hlc2efr6"]
[ext_resource type="Script" path="res://scripts/match/ui/opponent_name.gd" id="1_saby1"]
[ext_resource type="Script" path="res://scripts/match/ui/current_game_time.gd" id="2_3jcub"]
[node name="Game" type="Node2D"]
[node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="HUD" type="Control" parent="CanvasLayer"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Opponent Name" type="RichTextLabel" parent="CanvasLayer/HUD"]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -0.5
offset_right = 0.5
offset_bottom = 45.0
grow_horizontal = 2
text = "Unknown"
fit_content = true
scroll_active = false
autowrap_mode = 0
script = ExtResource("1_saby1")
[node name="Time" type="RichTextLabel" parent="CanvasLayer/HUD"]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -20.0
offset_top = -20.0
offset_right = 20.0
offset_bottom = 20.0
grow_horizontal = 2
grow_vertical = 2
fit_content = true
scroll_active = false
autowrap_mode = 0
script = ExtResource("2_3jcub")

View file

@ -1,12 +1,12 @@
[gd_scene load_steps=12 format=3 uid="uid://bqfijb7bk2g7j"] [gd_scene load_steps=12 format=3 uid="uid://bqfijb7bk2g7j"]
[ext_resource type="Theme" uid="uid://bt4hxdwromnxs" path="res://ui/theme.tres" id="1_6qgep"] [ext_resource type="Theme" uid="uid://bt4hxdwromnxs" path="res://ui/theme.tres" id="1_6qgep"]
[ext_resource type="Script" path="res://scripts/ui/show_banner_on_error.gd" id="2_1tbi1"] [ext_resource type="Script" path="res://scripts/ui/login/show_banner_on_error.gd" id="2_1tbi1"]
[ext_resource type="Script" path="res://scripts/ui/swap_menu.gd" id="2_c477a"] [ext_resource type="Script" path="res://scripts/ui/swap_menu.gd" id="2_c477a"]
[ext_resource type="Script" path="res://scripts/ui/login.gd" id="3_33cgr"] [ext_resource type="Script" path="res://scripts/ui/login/login.gd" id="3_33cgr"]
[ext_resource type="Resource" uid="uid://cdixdbu3sqgjn" path="res://config/api_config.tres" id="4_5vuod"] [ext_resource type="Resource" uid="uid://cdixdbu3sqgjn" path="res://config/api_config.tres" id="4_5vuod"]
[ext_resource type="Script" path="res://scripts/ui/quit.gd" id="6_cixwl"] [ext_resource type="Script" path="res://scripts/ui/quit.gd" id="6_cixwl"]
[ext_resource type="Script" path="res://scripts/ui/search_match.gd" id="7_dmfpl"] [ext_resource type="Script" path="res://scripts/ui/lobby/search_match.gd" id="7_dmfpl"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_q2pxx"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_q2pxx"]
bg_color = Color(0.52, 0.52, 0.52, 1) bg_color = Color(0.52, 0.52, 0.52, 1)

View file

@ -0,0 +1,12 @@
class_name CurrentUnixTimeMessage
extends Message
const MESSAGE_ID: String = "CurrentUnixTime"
@export var time: int
# gdlint:ignore = class-variable-name
@export var matchId: String
func get_message_id() -> String:
return MESSAGE_ID

View file

@ -0,0 +1,20 @@
extends Channel
signal on_match_update(msg: CurrentUnixTimeMessage)
func get_channel_location() -> String:
return "match"
func _process(_delta: float) -> void:
self.socket.poll()
if self.socket.get_ready_state() != WebSocketPeer.STATE_OPEN:
return
while self.socket.get_available_packet_count():
var msg := CurrentUnixTimeMessage.deserialize(
self.socket.get_packet().get_string_from_utf8(), [CurrentUnixTimeMessage]
)
if msg.get_message_id() != CurrentUnixTimeMessage.MESSAGE_ID:
return
on_match_update.emit(msg)

View file

@ -33,7 +33,7 @@ func _process(_delta: float) -> void:
MatchFoundMessage.MESSAGE_ID: MatchFoundMessage.MESSAGE_ID:
on_match_found.emit(msg) on_match_found.emit(msg)
MatchAbortedMessage.MESSAGE_ID: MatchAbortedMessage.MESSAGE_ID:
on_match_found.emit(msg) on_match_aborted.emit()
MatchEstablishedMessage.MESSAGE_ID: MatchEstablishedMessage.MESSAGE_ID:
on_match_established.emit(msg) on_match_established.emit(msg)
_: _:

View file

@ -1,8 +0,0 @@
class_name CurrentUnixTimeMessage
extends Message
var time: int
func get_message_id() -> String:
return "CurrentUnixTime"

View file

@ -0,0 +1,13 @@
extends Node
enum State { NONE, RUNNING, WON, LOST }
var state: State = State.NONE
var opponent_name: String = ""
func start_game(msg: MatchEstablishedMessage) -> void:
self.opponent_name = msg.opponentName
self.state = State.RUNNING
MatchChannel.connect_socket(msg.token)
get_tree().change_scene_to_file("res://scenes/game.tscn")

View file

@ -0,0 +1,9 @@
extends RichTextLabel
func _ready() -> void:
MatchChannel.connect("on_match_update", on_match_update)
func on_match_update(msg: CurrentUnixTimeMessage) -> void:
self.text = str(msg.time)

View file

@ -0,0 +1,5 @@
extends RichTextLabel
func _ready() -> void:
self.text = CurrentMatch.opponent_name

View file

@ -10,7 +10,7 @@ extends Control
var searching: bool = false var searching: bool = false
var sent_accept_message: bool = false var sent_accept_message: bool = false
var match_id: String = "" var found_match: MatchFoundMessage
func _ready() -> void: func _ready() -> void:
@ -45,6 +45,13 @@ func _ready() -> void:
popup.visible = false popup.visible = false
func _process(_delta: float) -> void:
if found_match:
var now := int(Time.get_unix_time_from_system() * 1000)
time_bar.max_value = found_match.ttl
time_bar.value = found_match.ttl - (now - found_match.created)
# gdlint:ignore = max-public-methods # gdlint:ignore = max-public-methods
func export_valid() -> bool: func export_valid() -> bool:
if not popup: if not popup:
@ -93,19 +100,17 @@ func on_match_set_search_state(msg: MatchSetSearchStateMessage) -> void:
func on_match_found(msg: MatchFoundMessage) -> void: func on_match_found(msg: MatchFoundMessage) -> void:
set_match_accptance_ui(true) set_match_accptance_ui(true)
set_accaptence_buttons_enabled(true) set_accaptence_buttons_enabled(true)
match_id = msg.matchId found_match = msg
# TODO: Show and Reset Timer bar
func on_match_aborted() -> void: func on_match_aborted() -> void:
set_match_accptance_ui(false) set_match_accptance_ui(false)
set_searching_ui(false) set_searching_ui(false)
match_id = "" found_match = null
func on_match_established(msg: MatchEstablishedMessage) -> void: func on_match_established(msg: MatchEstablishedMessage) -> void:
print(msg.opponentName) CurrentMatch.start_game(msg)
#TODO: Implement
############################# #############################
@ -129,12 +134,12 @@ func on_abort_pressed() -> void:
func on_accept_pressed() -> void: func on_accept_pressed() -> void:
set_accaptence_buttons_enabled(false) set_accaptence_buttons_enabled(false)
MatchmakingChannel.send_match_accepted(true, match_id) MatchmakingChannel.send_match_accepted(true, found_match.matchId)
func on_decline_pressed() -> void: func on_decline_pressed() -> void:
set_accaptence_buttons_enabled(false) set_accaptence_buttons_enabled(false)
MatchmakingChannel.send_match_accepted(false, match_id) MatchmakingChannel.send_match_accepted(false, found_match.matchId)
############################# #############################

View file

@ -1,50 +0,0 @@
extends RichTextLabel
@export var login: Login
@export var api_config: ApiConfig
var api := ServerApi.new(api_config)
# docs.redotengine.org/en/stable/tutorials/networking/websocket.html
var time_channel = WebSocketPeer.new()
func _ready() -> void:
login.connect("login_successful", on_login)
(
ConnectionChannel
. connect(
"on_channel_token_received",
on_channel_token_received,
)
)
func on_login(session: PlayerLoginSession):
ConnectionChannel.connect_to_channel(session.token)
ConnectionChannel.request_channel_token(Message.Channels.TIME)
func on_channel_token_received(msg: ProvidedConnectionTokenMessage) -> void:
if time_channel.get_ready_state() != WebSocketPeer.STATE_CLOSED:
return
if msg.channel != Message.Channels.TIME:
return
time_channel.handshake_headers = PackedStringArray(
["Authorization: " + msg.token],
)
time_channel.connect_to_url("ws://localhost:8080/ws/time")
func _process(_delta: float) -> void:
time_channel.poll()
var state = time_channel.get_ready_state()
if state != WebSocketPeer.STATE_OPEN:
return
while time_channel.get_available_packet_count():
var msg: CurrentUnixTimeMessage = Messize(
time_channel.get_packet().get_string_from_utf8(), [CurrentUnixTimeMessage]
)
if msg == null:
continue
self.text = str(msg.time)