fix: so many bugs, feat: cancel tournaments

This commit is contained in:
2025-12-08 22:48:58 -05:00
Unverified
parent 5d821f732b
commit ad713965e5
7 changed files with 274 additions and 140 deletions

View File

@@ -28,6 +28,7 @@ window/size/viewport_width=1280
window/size/viewport_height=720 window/size/viewport_height=720
window/stretch/mode="canvas_items" window/stretch/mode="canvas_items"
window/stretch/aspect="expand" window/stretch/aspect="expand"
window/vsync/vsync_mode=2
[dotnet] [dotnet]

View File

@@ -10,32 +10,17 @@ public partial class AdminControls : HBoxContainer
public override void _Ready() public override void _Ready()
{ {
Connection.Instance.OnBecomeAdmin += OnBecomeAdmin; Connection.Instance.OnBecomeAdmin += UpdateUI;
Connection.Instance.OnTournamentEnd += _ => StartTournament.Show(); Connection.Instance.OnTournamentEnd += UpdateUI;
Connection.Instance.OnStartTournamentAck += () => StartTournament.Hide(); Connection.Instance.OnStartTournamentAck += UpdateUI;
Connection.Instance.OnCancelTournamentAck += UpdateUI;
Connection.Instance.OnGetDataAcks += UpdateUI;
StartTournament.Pressed += () => Connection.Instance.StartTournament(); StartTournament.Pressed += () => Connection.Instance.StartTournament();
CancelTournament.Pressed += () => Connection.Instance.CancelTournament(); CancelTournament.Pressed += () => Connection.Instance.CancelTournament();
if (!Connection.Instance.IsAdmin)
{
StartTournament.Hide();
CancelTournament.Hide();
Label.Hide();
Timeout.Hide();
}
else if (Connection.Instance.ActiveTournament)
{
StartTournament.Hide();
}
Timeout.Value = Connection.Instance.CurrentWaitTimeout;
var time = Connection.Instance.CurrentWaitTimeout.ToString();
if (time.Length > 3)
{
time = time.Substring(0, 3);
}
Label.Text = "Wait To Move: " + time + "s "; UpdateUI();
Timeout.ValueChanged += value => Timeout.ValueChanged += value =>
{ {
Connection.Instance.SetTournamentWait((float)value); Connection.Instance.SetTournamentWait((float)value);
@@ -52,7 +37,54 @@ public partial class AdminControls : HBoxContainer
public override void _ExitTree() public override void _ExitTree()
{ {
Connection.Instance.OnBecomeAdmin -= OnBecomeAdmin; Connection.Instance.OnBecomeAdmin -= UpdateUI;
Connection.Instance.OnTournamentEnd -= UpdateUI;
Connection.Instance.OnStartTournamentAck -= UpdateUI;
Connection.Instance.OnCancelTournamentAck -= UpdateUI;
Connection.Instance.OnGetDataAcks -= UpdateUI;
}
private void UpdateUI()
{
if (!Connection.Instance.IsAdmin)
{
BecomeAdmin.Show();
StartTournament.Hide();
CancelTournament.Hide();
Label.Hide();
Timeout.Hide();
}
else
{
BecomeAdmin.Hide();
Label.Show();
Timeout.Show();
}
if (Connection.Instance.IsAdmin && Connection.Instance.DemoMode)
{
StartTournament.Hide();
CancelTournament.Hide();
}
else if (Connection.Instance.IsAdmin && Connection.Instance.ActiveTournament)
{
StartTournament.Hide();
CancelTournament.Show();
}
else if (Connection.Instance.IsAdmin)
{
StartTournament.Show();
CancelTournament.Hide();
}
Timeout.Value = Connection.Instance.CurrentWaitTimeout;
var time = Connection.Instance.CurrentWaitTimeout.ToString();
if (time.Length > 3)
{
time = time.Substring(0, 3);
}
Label.Text = "Wait To Move: " + time + "s ";
} }
private void ShowAuthPopup() private void ShowAuthPopup()
@@ -66,7 +98,7 @@ public partial class AdminControls : HBoxContainer
authWindow.Size = new Vector2I(256, 128); authWindow.Size = new Vector2I(256, 128);
authWindow.CloseRequested += () => authWindow.CloseRequested += () =>
{ {
GetTree().Root.RemoveChild(authWindow); GetTree().Root.CallDeferred(Node.MethodName.RemoveChild, authWindow);
}; };
var vbox = new VBoxContainer(); var vbox = new VBoxContainer();
@@ -81,12 +113,30 @@ public partial class AdminControls : HBoxContainer
passwordBox.PlaceholderText = "Password"; passwordBox.PlaceholderText = "Password";
passwordBox.SetCustomMinimumSize(new Vector2(32, 32)); passwordBox.SetCustomMinimumSize(new Vector2(32, 32));
passwordBox.GuiInput += e =>
{
if (passwordBox.HasFocus() && e is InputEventKey inputEventKey && inputEventKey.IsPressed())
{
if (inputEventKey.KeyLabel == Key.Enter)
{
Connection.Instance.AdminAuth(passwordBox.Text);
GetTree().Root.CallDeferred(Node.MethodName.RemoveChild, authWindow);
GetViewport().SetInputAsHandled();
}
if (inputEventKey.KeyLabel == Key.Space)
{
GetViewport().SetInputAsHandled();
}
}
};
var button = new Button(); var button = new Button();
button.Text = "Login"; button.Text = "Login";
button.Pressed += () => button.Pressed += () =>
{ {
Connection.Instance.AdminAuth(passwordBox.Text); Connection.Instance.AdminAuth(passwordBox.Text);
GetTree().Root.RemoveChild(authWindow); GetTree().Root.CallDeferred(Node.MethodName.RemoveChild, authWindow);
}; };
vbox.AddChild(passwordBox); vbox.AddChild(passwordBox);
@@ -96,19 +146,4 @@ public partial class AdminControls : HBoxContainer
GetTree().Root.AddChild(authWindow); GetTree().Root.AddChild(authWindow);
} }
private void OnBecomeAdmin()
{
BecomeAdmin.Hide();
if (!Connection.Instance.ActiveTournament)
{
StartTournament.Show();
}
else
{
CancelTournament.Show();
}
Label.Show();
Timeout.Show();
}
} }

View File

@@ -1,5 +1,4 @@
using Godot; using Godot;
using System.Collections.Generic;
using System.Linq; using System.Linq;
public partial class BoardScreen : Node2D public partial class BoardScreen : Node2D
@@ -65,11 +64,10 @@ public partial class BoardScreen : Node2D
player2Card.GetNode<Label>("Status").Hide(); player2Card.GetNode<Label>("Status").Hide();
} }
Connection.Instance.OnObserveWin += winner => { _lastMove = true; _winner = winner; }; Connection.Instance.OnObserveWin += OnObserveWin;
Connection.Instance.OnObserveDraw += () => _lastMove = true; Connection.Instance.OnObserveDraw += OnObserveDraw;
Connection.Instance.OnObserveTerminated += () => PopupMessage("Match Terminated"); Connection.Instance.OnObserveTerminated += OnObserveTerminated;
Connection.Instance.OnObserveMove += ObserveMove; Connection.Instance.OnObserveMove += ObserveMove;
Connection.Instance.OnTournamentEnd += ShowTournamentScoreboard;
} }
public override void _Process(double delta) public override void _Process(double delta)
@@ -114,20 +112,46 @@ public partial class BoardScreen : Node2D
public override void _ExitTree() public override void _ExitTree()
{ {
Connection.Instance.OnObserveWin -= OnObserveWin;
Connection.Instance.OnObserveDraw -= OnObserveDraw;
Connection.Instance.OnObserveTerminated -= OnObserveTerminated;
Connection.Instance.OnObserveMove -= ObserveMove; Connection.Instance.OnObserveMove -= ObserveMove;
Connection.Instance.OnTournamentEnd -= ShowTournamentScoreboard;
} }
private void OnObserveWin(string winner)
{
_lastMove = true;
_winner = winner;
player1Card.GetNode<Label>("Status").Hide();
player2Card.GetNode<Label>("Status").Hide();
}
private void OnObserveDraw()
{
_lastMove = true;
player1Card.GetNode<Label>("Status").Hide();
player2Card.GetNode<Label>("Status").Hide();
}
private void OnObserveTerminated()
{
PopupMessage("Match Terminated");
player1Card.GetNode<Label>("Status").Hide();
player2Card.GetNode<Label>("Status").Hide();
}
private void ObserveMove(string username, int column) private void ObserveMove(string username, int column)
{ {
if (username == matchData.player1) if (username == matchData.player1)
{ {
if (!_lastMove)
player2Card.GetNode<Label>("Status").Show();
player1Card.GetNode<Label>("Status").Hide(); player1Card.GetNode<Label>("Status").Hide();
player2Card.GetNode<Label>("Status").Show();
} }
else else
{ {
player1Card.GetNode<Label>("Status").Show(); if (!_lastMove)
player1Card.GetNode<Label>("Status").Show();
player2Card.GetNode<Label>("Status").Hide(); player2Card.GetNode<Label>("Status").Hide();
} }
Connection.Instance.PreviousMoves.Add((username, column)); Connection.Instance.PreviousMoves.Add((username, column));
@@ -160,39 +184,6 @@ public partial class BoardScreen : Node2D
TransitionToBracket(); TransitionToBracket();
} }
private void ShowTournamentScoreboard(List<(string, int)> playerScoreboard)
{
var scoreboardWindow = new Window();
scoreboardWindow.AlwaysOnTop = true;
scoreboardWindow.MaximizeDisabled = true;
scoreboardWindow.Unresizable = true;
scoreboardWindow.InitialPosition = Window.WindowInitialPosition.CenterMainWindowScreen;
scoreboardWindow.Size = new Vector2I(256, 512);
scoreboardWindow.CloseRequested += () =>
{
GetTree().Root.RemoveChild(scoreboardWindow);
};
var tree = new Tree();
tree.HideRoot = true;
tree.Columns = 2;
tree.ColumnTitlesVisible = true;
tree.SetColumnTitle(0, "Player");
tree.SetColumnTitle(1, "Score");
var root = tree.CreateItem();
foreach ((string, int) entry in playerScoreboard)
{
var item = tree.CreateItem(root);
item.SetText(0, entry.Item1);
item.SetText(1, entry.Item2.ToString());
}
scoreboardWindow.AddChild(tree);
GetTree().Root.AddChild(scoreboardWindow);
}
private void TransitionToBracket() private void TransitionToBracket()
{ {
GetTree().ChangeSceneToFile(BRACKET_SCENE_PATH); GetTree().ChangeSceneToFile(BRACKET_SCENE_PATH);

View File

@@ -31,7 +31,6 @@ public partial class BracketScene : Control
Connection.Instance.OnUpdatedPlayers += UpdatePlayers; Connection.Instance.OnUpdatedPlayers += UpdatePlayers;
Connection.Instance.OnUpdatedMatches += UpdateMatches; Connection.Instance.OnUpdatedMatches += UpdateMatches;
Connection.Instance.OnWatchGameAck += TransitionToBoard; Connection.Instance.OnWatchGameAck += TransitionToBoard;
Connection.Instance.OnTournamentEnd += ShowTournamentScoreboard;
} }
public override void _ExitTree() public override void _ExitTree()
@@ -39,13 +38,13 @@ public partial class BracketScene : Control
Connection.Instance.OnUpdatedPlayers -= UpdatePlayers; Connection.Instance.OnUpdatedPlayers -= UpdatePlayers;
Connection.Instance.OnUpdatedMatches -= UpdateMatches; Connection.Instance.OnUpdatedMatches -= UpdateMatches;
Connection.Instance.OnWatchGameAck -= TransitionToBoard; Connection.Instance.OnWatchGameAck -= TransitionToBoard;
Connection.Instance.OnTournamentEnd -= ShowTournamentScoreboard;
} }
private void UpdatePlayers(List<PlayerData> playerList) private void UpdatePlayers(List<PlayerData> playerList)
{ {
Players.Clear(); Players.Clear();
_playerList = playerList; _playerList = playerList;
_playerList.Sort((a, b) => a.username.CompareTo(b.username));
var root = Players.CreateItem(); var root = Players.CreateItem();
for (int i = 0; i < _playerList.Count; i++) for (int i = 0; i < _playerList.Count; i++)
{ {
@@ -55,7 +54,7 @@ public partial class BracketScene : Control
item.SetText(2, playerList[i].isPlaying ? "Yes" : "No"); item.SetText(2, playerList[i].isPlaying ? "Yes" : "No");
if (Connection.Instance.IsAdmin) if (Connection.Instance.IsAdmin)
{ {
item.AddButton(0, TerminateKickButton, i, false, "Kick"); // TODO item.AddButton(0, TerminateKickButton, i, false, "Kick");
} }
} }
} }
@@ -71,22 +70,30 @@ public partial class BracketScene : Control
item.SetText(0, matchList[i].matchId.ToString()); item.SetText(0, matchList[i].matchId.ToString());
item.SetText(1, matchList[i].player1); item.SetText(1, matchList[i].player1);
item.SetText(2, matchList[i].player2); item.SetText(2, matchList[i].player2);
item.AddButton(0, WatchButton, item.GetButtonCount(0), false, "Watch"); item.AddButton(0, WatchButton, i, false, "Watch");
if (Connection.Instance.IsAdmin) if (Connection.Instance.IsAdmin)
{ {
item.AddButton(0, TerminateKickButton, item.GetButtonCount(0), false, "Terminate"); item.AddButton(0, TerminateKickButton, 128 + i, false, "Terminate");
} }
} }
} }
private void WatchGame(TreeItem item, long column, long id, long mouseButtonIndex) private void WatchGame(TreeItem item, long column, long id, long mouseButtonIndex)
{ {
if (mouseButtonIndex == 1 && column == 0) if (mouseButtonIndex == 1 && column == 0 && id < 128)
{ {
Connection.Instance.SendWatchGame(_matchList[(int) id].matchId); Connection.Instance.SendWatchGame(_matchList[(int) id].matchId);
} }
} }
private void TerminateGame(TreeItem item, long column, long id, long mouseButtonIndex)
{
if (mouseButtonIndex == 1 && column == 0 && id - 128 >= 0 && _matchList[(int) id - 128] != null)
{
Connection.Instance.TerminateGame(_matchList[(int) id - 128].matchId);
}
}
private void KickPlayer(TreeItem item, long column, long id, long mouseButtonIndex) private void KickPlayer(TreeItem item, long column, long id, long mouseButtonIndex)
{ {
if (mouseButtonIndex == 1 && column == 0) if (mouseButtonIndex == 1 && column == 0)
@@ -95,51 +102,8 @@ public partial class BracketScene : Control
} }
} }
private void TerminateGame(TreeItem item, long column, long id, long mouseButtonIndex)
{
if (mouseButtonIndex == 1 && column == 0 && id - 1 > 0 && _matchList[(int) id - 1] != null)
{
Connection.Instance.TerminateGame(_matchList[(int) id - 1].matchId);
}
}
private void TransitionToBoard() private void TransitionToBoard()
{ {
GetTree().ChangeSceneToFile(BOARD_SCENE_PATH); GetTree().ChangeSceneToFile(BOARD_SCENE_PATH);
} }
private void ShowTournamentScoreboard(List<(string, int)> playerScoreboard)
{
var scoreboardWindow = new Window();
scoreboardWindow.Theme = GD.Load<Theme>("res://assets/theme.tres");
scoreboardWindow.AlwaysOnTop = true;
scoreboardWindow.MaximizeDisabled = true;
scoreboardWindow.Unresizable = true;
scoreboardWindow.InitialPosition = Window.WindowInitialPosition.CenterMainWindowScreen;
scoreboardWindow.Size = new Vector2I(256, 512);
scoreboardWindow.CloseRequested += () =>
{
GetTree().Root.RemoveChild(scoreboardWindow);
};
var tree = new Tree();
tree.HideRoot = true;
tree.Columns = 2;
tree.ColumnTitlesVisible = true;
tree.Theme = GD.Load<Theme>("res://assets/theme.tres");
tree.SetColumnTitle(0, "Player");
tree.SetColumnTitle(1, "Score");
var root = tree.CreateItem();
foreach ((string, int) entry in playerScoreboard)
{
var item = tree.CreateItem(root);
item.SetText(0, entry.Item1);
item.SetText(1, entry.Item2.ToString());
}
scoreboardWindow.AddChild(tree);
GetTree().Root.AddChild(scoreboardWindow);
}
} }

View File

@@ -8,12 +8,55 @@ public partial class ConnectButtonUI : Button
public override void _Ready() public override void _Ready()
{ {
Connection.Instance.OnWsConnectionSuccess += () => GetTree().ChangeSceneToFile(BRACKET_SCENE_PATH); Connection.Instance.OnWsConnectionSuccess += OnConnectionSuccess;
Connection.Instance.OnWsConnectionFailed += () => ErrorLabel.Text = "Couldn't connect to server! " + Connection.Instance.LastError; Connection.Instance.OnWsConnectionFailed += OnConnectionFailed;
if (Connection.Instance.LastUsedConnectionAddress.Length > 0)
{
AddressField.Text = Connection.Instance.LastUsedConnectionAddress;
}
if (Connection.Instance.LastError.Length > 0)
{
ErrorLabel.Text = Connection.Instance.LastError;
}
AddressField.GuiInput += e =>
{
if (AddressField.HasFocus() && e is InputEventKey inputEventKey && inputEventKey.IsPressed())
{
if (inputEventKey.KeyLabel == Key.Enter)
{
Connection.Instance.Connect(AddressField.Text);
GetViewport().SetInputAsHandled();
}
if (inputEventKey.KeyLabel == Key.Space)
{
GetViewport().SetInputAsHandled();
}
}
};
}
public override void _ExitTree()
{
Connection.Instance.OnWsConnectionSuccess -= OnConnectionSuccess;
Connection.Instance.OnWsConnectionFailed -= OnConnectionFailed;
} }
public override void _Pressed() public override void _Pressed()
{ {
Connection.Instance.Connect(AddressField.Text); Connection.Instance.Connect(AddressField.Text);
} }
private void OnConnectionSuccess()
{
GetTree().ChangeSceneToFile(BRACKET_SCENE_PATH);
}
private void OnConnectionFailed()
{
ErrorLabel.Text = "Couldn't connect to server! " + Connection.Instance.LastError;
}
} }

View File

@@ -30,8 +30,10 @@ public partial class Connection : Node
public event Action<List<MatchData>> OnUpdatedMatches; public event Action<List<MatchData>> OnUpdatedMatches;
public event Action<List<PlayerData>> OnUpdatedPlayers; public event Action<List<PlayerData>> OnUpdatedPlayers;
public event Action OnStartTournamentAck; public event Action OnStartTournamentAck;
public event Action<List<(string, int)>> OnTournamentEnd; public event Action OnTournamentEnd;
public event Action OnCancelTournamentAck;
public event Action OnBecomeAdmin; public event Action OnBecomeAdmin;
public event Action OnGetDataAcks;
public event Action OnWsConnectionSuccess; public event Action OnWsConnectionSuccess;
public event Action OnWsConnectionFailed; public event Action OnWsConnectionFailed;
@@ -43,18 +45,19 @@ public partial class Connection : Node
public bool IsAdmin { get; private set; } public bool IsAdmin { get; private set; }
public bool IsPlayer { get; private set; } public bool IsPlayer { get; private set; }
public bool ActiveTournament { get; private set; } public bool ActiveTournament { get; private set; }
public bool DemoMode { get; private set; }
public List<(string, int)> PreviousMoves { get; private set; } = []; public List<(string, int)> PreviousMoves { get; private set; } = [];
public double CurrentWaitTimeout { get; private set; } = 5.0; public double CurrentWaitTimeout { get; private set; } = 5.0;
public MatchData CurrentObservingMatch { get; private set; } public MatchData CurrentObservingMatch { get; private set; }
public string LastUsedConnectionAddress { get; private set; } = "";
public string LastError { get; private set; } = "";
private bool IsSocketOpen => _webSocket.GetReadyState() == WebSocketPeer.State.Open; private bool IsSocketOpen => _webSocket.GetReadyState() == WebSocketPeer.State.Open;
private bool _connecting = false; private bool _connecting = false;
private bool _connected = false; private bool _connected = false;
private List<(string, int)> _lastScoreboard = [];
public String LastError = ""; private bool _shouldShowTournamentResults = false;
public override void _Ready() public override void _Ready()
{ {
@@ -67,6 +70,7 @@ public partial class Connection : Node
public void Connect(string address) public void Connect(string address)
{ {
_connecting = true; _connecting = true;
LastUsedConnectionAddress = address;
if (_connected) if (_connected)
{ {
return; return;
@@ -94,6 +98,7 @@ public partial class Connection : Node
{ {
_connecting = false; _connecting = false;
_connected = true; _connected = true;
LastError = "";
OnWsConnectionSuccess?.Invoke(); OnWsConnectionSuccess?.Invoke();
StartGameListRefreshLoop(); StartGameListRefreshLoop();
} }
@@ -103,6 +108,19 @@ public partial class Connection : Node
string message = _webSocket.GetPacket().GetStringFromUtf8(); string message = _webSocket.GetPacket().GetStringFromUtf8();
HandleServerMessage(message); HandleServerMessage(message);
} }
if (_shouldShowTournamentResults)
{
var children = GetTree().Root.GetChildren();
foreach (var child in children)
{
if (child.Name.ToString() == "BracketView")
{
_shouldShowTournamentResults = false;
ShowTournamentScoreboard(_lastScoreboard);
}
}
}
} }
else if (state == WebSocketPeer.State.Connecting) else if (state == WebSocketPeer.State.Connecting)
{ {
@@ -122,9 +140,14 @@ public partial class Connection : Node
else if (_connected) else if (_connected)
{ {
_connected = false; _connected = false;
IsAdmin = false;
CurrentWaitTimeout = 5.0;
ActiveTournament = false;
DemoMode = false;
StopGameListRefreshLoop(); StopGameListRefreshLoop();
var code = _webSocket.GetCloseCode(); var code = _webSocket.GetCloseCode();
var reason = _webSocket.GetCloseReason(); var reason = _webSocket.GetCloseReason();
LastError = "Unexpected Disconnect. Reason: " + reason + ", Code: " + code;
GD.PrintErr("WebSocket closed with code: " + code + ", reason " + reason + ". Clean: " + (code != -1)); GD.PrintErr("WebSocket closed with code: " + code + ", reason " + reason + ". Clean: " + (code != -1));
OnWsDisconnect?.Invoke(); OnWsDisconnect?.Invoke();
} }
@@ -222,6 +245,16 @@ public partial class Connection : Node
SendCommand("ADMIN", "AUTH:" + password); SendCommand("ADMIN", "AUTH:" + password);
} }
public void GetMoveWait()
{
SendCommand("GET", "MOVE_WAIT");
}
public void GetTournamentStatus()
{
SendCommand("GET", "TOURNAMENT_STATUS");
}
// Admin commands // Admin commands
public void KickPlayer(string playerId) public void KickPlayer(string playerId)
@@ -330,7 +363,8 @@ public partial class Connection : Node
if (body == "AUTH:ACK") if (body == "AUTH:ACK")
{ {
IsAdmin = true; IsAdmin = true;
SetTournamentWait(5.0f); GetMoveWait();
GetTournamentStatus();
OnBecomeAdmin?.Invoke(); OnBecomeAdmin?.Invoke();
} }
@@ -338,6 +372,26 @@ public partial class Connection : Node
case "TOURNAMENT": case "TOURNAMENT":
HandleTournamentMessage(body); HandleTournamentMessage(body);
break; break;
case "GET":
if (body.StartsWith("MOVE_WAIT"))
{
CurrentWaitTimeout = double.Parse(body.Split(":")[1]);
}
else if (body.StartsWith("TOURNAMENT_STATUS"))
{
string status = body.Split(":")[1];
if (status != "DEMO")
{
ActiveTournament = bool.Parse(status);
}
else
{
ActiveTournament = false;
DemoMode = true;
}
}
OnGetDataAcks?.Invoke();
break;
case "ERROR": case "ERROR":
GD.PrintErr(message); GD.PrintErr(message);
OnError?.Invoke(message); OnError?.Invoke(message);
@@ -372,7 +426,9 @@ public partial class Connection : Node
playerScoreboard.Add((data[0], int.Parse(data[1]))); playerScoreboard.Add((data[0], int.Parse(data[1])));
} }
OnTournamentEnd?.Invoke(playerScoreboard); _lastScoreboard = playerScoreboard;
_shouldShowTournamentResults = true;
OnTournamentEnd?.Invoke();
break; break;
} }
case "START": case "START":
@@ -381,6 +437,12 @@ public partial class Connection : Node
ActiveTournament = true; ActiveTournament = true;
break; break;
} }
case "CANCEL":
{
ActiveTournament = false;
OnCancelTournamentAck?.Invoke();
break;
}
} }
} }
@@ -517,4 +579,42 @@ public partial class Connection : Node
} }
} }
} }
public void ShowTournamentScoreboard(List<(string, int)> playerScoreboard)
{
var scoreboardWindow = new Window();
scoreboardWindow.Theme = GD.Load<Theme>("res://assets/theme.tres");
scoreboardWindow.AlwaysOnTop = true;
scoreboardWindow.MaximizeDisabled = true;
scoreboardWindow.Unresizable = true;
scoreboardWindow.InitialPosition = Window.WindowInitialPosition.CenterMainWindowScreen;
scoreboardWindow.Size = new Vector2I(256, 512);
scoreboardWindow.CloseRequested += () =>
{
GetTree().Root.RemoveChild(scoreboardWindow);
};
var tree = new Tree();
tree.HideRoot = true;
tree.Columns = 2;
tree.ColumnTitlesVisible = true;
tree.Theme = GD.Load<Theme>("res://assets/theme.tres");
tree.GrowHorizontal = Control.GrowDirection.Both;
tree.GrowVertical = Control.GrowDirection.Both;
tree.SetColumnTitle(0, "Player");
tree.SetColumnTitle(1, "Score");
var root = tree.CreateItem();
foreach ((string, int) entry in playerScoreboard)
{
var item = tree.CreateItem(root);
item.SetText(0, entry.Item1);
item.SetText(1, entry.Item2.ToString());
}
scoreboardWindow.AddChild(tree);
tree.SetAnchorsPreset(Control.LayoutPreset.FullRect);
GetTree().Root.AddChild(scoreboardWindow);
}
} }

View File

@@ -10,5 +10,5 @@ func _ready() -> void:
# Called every frame. 'delta' is the elapsed time since the previous frame. # Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void: func _process(_delta: float) -> void:
pass pass