feat: admin UI, player scoreboard, back button logic

This commit is contained in:
2025-12-04 10:47:40 -05:00
Unverified
parent a16a44ba7a
commit 24ca218ee2
8 changed files with 236 additions and 17 deletions

123
scripts/AdminControls.cs Normal file
View File

@@ -0,0 +1,123 @@
using Godot;
using System;
using System.Collections.Generic;
public partial class AdminControls : HBoxContainer
{
[Export] public Button BecomeAdmin;
[Export] public Button StartTournament;
public override void _Ready()
{
Connection.Instance.OnBecomeAdmin += OnBecomeAdmin;
Connection.Instance.OnTournamentEnd += OnEndTournament;
StartTournament.Pressed += StartTournamentCommand;
if (!Connection.Instance.IsAdmin || Connection.Instance.ActiveTournament)
{
StartTournament.Hide();
}
BecomeAdmin.Pressed += ShowAuthPopup;
}
public override void _ExitTree()
{
Connection.Instance.OnBecomeAdmin -= OnBecomeAdmin;
Connection.Instance.OnTournamentEnd -= OnEndTournament;
}
private void StartTournamentCommand()
{
Connection.Instance.StartTournament();
}
private void OnEndTournament(List<(string, int)> playerScoreboard)
{
StartTournament.Show();
ShowTournamentScoreboard(playerScoreboard);
}
private void ShowAuthPopup()
{
var authWindow = new Window();
authWindow.AlwaysOnTop = true;
authWindow.MaximizeDisabled = true;
authWindow.Unresizable = true;
authWindow.InitialPosition = Window.WindowInitialPosition.CenterMainWindowScreen;
authWindow.Size = new Vector2I(256, 128);
authWindow.CloseRequested += () =>
{
GetTree().Root.RemoveChild(authWindow);
};
var vbox = new VBoxContainer();
vbox.LayoutMode = 1;
vbox.AnchorBottom = 1.0f;
vbox.AnchorRight = 1.0f;
vbox.GrowHorizontal = GrowDirection.Both;
vbox.GrowVertical = GrowDirection.Both;
vbox.Alignment = AlignmentMode.Center;
var passwordBox = new TextEdit();
passwordBox.PlaceholderText = "Password";
passwordBox.SetCustomMinimumSize(new Vector2(32, 32));
var button = new Button();
button.Text = "Login";
button.Pressed += () =>
{
Connection.Instance.AdminAuth(passwordBox.Text);
GetTree().Root.RemoveChild(authWindow);
};
vbox.AddChild(passwordBox);
vbox.AddChild(button);
authWindow.AddChild(vbox);
GetTree().Root.AddChild(authWindow);
}
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 OnBecomeAdmin()
{
BecomeAdmin.Hide();
if (!Connection.Instance.ActiveTournament)
{
StartTournament.Show();
}
}
}

View File

@@ -0,0 +1 @@
uid://1y72woiynf31

View File

@@ -1,9 +1,11 @@
using Godot;
using System;
using System.Collections.Generic;
public partial class BoardScreen : Node2D {
[Export] public PackedScene BracketScene;
[Export] public BaseButton BackButton;
private const string RED_CHIP_PATH = "res://scenes/red_chip.tscn";
private const string YELLOW_CHIP_PATH = "res://scenes/yellow_chip.tscn";
@@ -45,6 +47,12 @@ public partial class BoardScreen : Node2D {
Connection.Instance.OnObserveDraw += ObserveDraw;
Connection.Instance.OnObserveTerminated += ObserveTerminated;
Connection.Instance.OnObserveMove += ObserveMove;
Connection.Instance.OnTournamentEnd += ShowTournamentScoreboard;
BackButton.Pressed += () =>
{
TransitionToBracket();
};
}
public override void _ExitTree()
@@ -53,6 +61,7 @@ public partial class BoardScreen : Node2D {
Connection.Instance.OnObserveDraw -= ObserveDraw;
Connection.Instance.OnObserveTerminated -= ObserveTerminated;
Connection.Instance.OnObserveMove -= ObserveMove;
Connection.Instance.OnTournamentEnd -= ShowTournamentScoreboard;
}
private void ObserveMove(string username, int column)
@@ -69,22 +78,76 @@ public partial class BoardScreen : Node2D {
private void ObserveWin(string winner)
{
// TODO
var popup = new Popup();
popup.AlwaysOnTop = true;
popup.PopupCentered();
popup.Size = new Vector2I(128, 128);
var text = new Label();
text.Text = winner + " wins!";
popup.AddChild(text);
GetTree().Root.AddChild(popup);
TransitionToBracket();
}
private void ObserveDraw()
{
// TODO
var popup = new Popup();
popup.AlwaysOnTop = true;
popup.PopupCentered();
popup.Size = new Vector2I(128, 128);
var text = new Label();
text.Text = "Draw!";
popup.AddChild(text);
GetTree().Root.AddChild(popup);
TransitionToBracket();
}
private void ObserveTerminated()
{
// TODO
var popup = new Popup();
popup.AlwaysOnTop = true;
popup.PopupCentered();
popup.Size = new Vector2I(128, 128);
var text = new Label();
text.Text = "Match Terminated";
popup.AddChild(text);
GetTree().Root.AddChild(popup);
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()
{
GetTree().ChangeSceneToPacked(BracketScene);

View File

@@ -29,7 +29,6 @@ public partial class BracketScene : Control
Connection.Instance.OnUpdatedPlayers += UpdatePlayers;
Connection.Instance.OnUpdatedMatches += UpdateMatches;
Connection.Instance.OnBecomeAdmin += BecomeAdmin;
Connection.Instance.OnWatchGameAck += TransitionToBoard;
}
@@ -37,7 +36,6 @@ public partial class BracketScene : Control
{
Connection.Instance.OnUpdatedPlayers -= UpdatePlayers;
Connection.Instance.OnUpdatedMatches -= UpdateMatches;
Connection.Instance.OnBecomeAdmin -= BecomeAdmin;
Connection.Instance.OnWatchGameAck -= TransitionToBoard;
}
@@ -90,15 +88,8 @@ public partial class BracketScene : Control
}
}
private void BecomeAdmin()
{
// TODO
}
private void TransitionToBoard()
{
// TODO
GD.Print("Watch game worked!");
GetTree().ChangeSceneToPacked(BoardScene);
}
}

View File

@@ -30,6 +30,7 @@ public partial class Connection : Node
public event Action<string, int> OnObserveMove;
public event Action<List<MatchData>> OnUpdatedMatches;
public event Action<List<PlayerData>> OnUpdatedPlayers;
public event Action OnStartTournamentAck;
public event Action<List<(string, int)>> OnTournamentEnd;
public event Action OnBecomeAdmin;
@@ -39,6 +40,8 @@ public partial class Connection : Node
public bool IsAdmin { get; private set; }
public bool IsPlayer { get; private set; }
public bool ActiveTournament { get; private set; }
public MatchData CurrentObservingMatch { get; private set; }
@@ -334,6 +337,7 @@ public partial class Connection : Node
{
case "END":
{
ActiveTournament = false;
List<(string, int)> playerScoreboard = new List<(string, int)>();
string[] entries = segments[1].Split("|");
foreach (string entry in entries)
@@ -345,6 +349,12 @@ public partial class Connection : Node
OnTournamentEnd?.Invoke(playerScoreboard);
break;
}
case "START":
{
OnStartTournamentAck?.Invoke();
ActiveTournament = true;
break;
}
}
}