diff --git a/game-example/Main.cs b/game-example/Main.cs index eafef73..316ccef 100644 --- a/game-example/Main.cs +++ b/game-example/Main.cs @@ -43,10 +43,11 @@ public partial class Main : Control { SongKey = "mirinTestSong", ChartKey = "mirinTestSong-expert", Judgments = new JudgmentTotals() { - {Judgment.critPerfect, new JudgmentTotalSet() {Total = 36}}, - {Judgment.perfect, new JudgmentTotalSet() {Total = 14, Early = 7, Late = 7}}, + {Judgment.critPerfect, new JudgmentTotalSet() {Total = 33}}, + {Judgment.perfect, new JudgmentTotalSet() {Total = 15, Early = 5, Late = 10}}, {Judgment.great, new JudgmentTotalSet() {Total = 10, Early = 6, Late = 3}}, - {Judgment.good, new JudgmentTotalSet() {Total = 2, Late = 2}} + {Judgment.good, new JudgmentTotalSet() {Total = 2, Late = 2}}, + {Judgment.miss, new JudgmentTotalSet() {Total = 2}} }, ScoreComponents = new Dictionary() { {"lamp", new EnumComponent(Lamp.fc)}, diff --git a/game-example/ScoreDisplay.cs b/game-example/ScoreDisplay.cs new file mode 100644 index 0000000..c202d4e --- /dev/null +++ b/game-example/ScoreDisplay.cs @@ -0,0 +1,62 @@ +using Godot; +using System; + +public partial class ScoreDisplay : PanelContainer { + private string player; + private float accuracy; + private int points; + private Lamp lamp; + + [Export] + public Label PlayerLabel; + [Export] + public Label AccuracyLabel; + [Export] + public Label PointsLabel; + [Export] + public Label LampLabel; + + [Export] + public string Player { + get => player; + set { + player = value; + PlayerLabel.Text = value; + } + } + + [Export] + public float Accuracy { + get => accuracy; + set { + accuracy = value; + AccuracyLabel.Text = $"{value}%"; + } + } + + [Export] + public int Points { + get => points; + set { + points = value; + PointsLabel.Text = value.ToString(); + } + } + + [Export] + public Lamp Lamp { + get => lamp; + set { + lamp = value; + LampLabel.Text = value.ToString(); + } + } + + // Called when the node enters the scene tree for the first time. + public override void _Ready() { + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(double delta) { + } +} diff --git a/game-example/ScoreDisplay.cs.uid b/game-example/ScoreDisplay.cs.uid new file mode 100644 index 0000000..9414a63 --- /dev/null +++ b/game-example/ScoreDisplay.cs.uid @@ -0,0 +1 @@ +uid://2sy34yvapo4d diff --git a/game-example/ScoreDisplay.tscn b/game-example/ScoreDisplay.tscn new file mode 100644 index 0000000..dc33187 --- /dev/null +++ b/game-example/ScoreDisplay.tscn @@ -0,0 +1,67 @@ +[gd_scene format=3 uid="uid://dl8bhm8nwkgxv"] + +[ext_resource type="Script" uid="uid://2sy34yvapo4d" path="res://ScoreDisplay.cs" id="1_ul6xh"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5lbon"] +content_margin_left = 5.0 +content_margin_top = 5.0 +content_margin_right = 5.0 +content_margin_bottom = 5.0 +bg_color = Color(0.18039216, 0.18039216, 0.18039216, 1) +border_width_left = 5 +border_width_top = 5 +border_width_right = 5 +border_width_bottom = 5 +border_color = Color(0.15180002, 0.69, 0.4478101, 1) +border_blend = true +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[node name="ScoreDisplay" type="PanelContainer" unique_id=540730563 node_paths=PackedStringArray("PlayerLabel", "AccuracyLabel", "PointsLabel", "LampLabel")] +custom_minimum_size = Vector2(120, 120) +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -41.5 +offset_top = -25.0 +offset_right = 41.5 +offset_bottom = 25.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +theme_override_styles/panel = SubResource("StyleBoxFlat_5lbon") +script = ExtResource("1_ul6xh") +PlayerLabel = NodePath("VBoxContainer/Player") +AccuracyLabel = NodePath("VBoxContainer/Accuracy") +PointsLabel = NodePath("VBoxContainer/Points") +LampLabel = NodePath("VBoxContainer/Lamp") + +[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=501291788] +layout_mode = 2 + +[node name="Player" type="Label" parent="VBoxContainer" unique_id=233483873] +layout_mode = 2 +text = "lemmaeof.gay" + +[node name="HSeparator" type="HSeparator" parent="VBoxContainer" unique_id=452659903] +layout_mode = 2 + +[node name="Accuracy" type="Label" parent="VBoxContainer" unique_id=911172824] +layout_mode = 2 +text = "101.0000%" +horizontal_alignment = 1 + +[node name="Points" type="Label" parent="VBoxContainer" unique_id=2135961365] +layout_mode = 2 +text = "200000" +horizontal_alignment = 1 + +[node name="Lamp" type="Label" parent="VBoxContainer" unique_id=1318085330] +layout_mode = 2 +text = "ap" +horizontal_alignment = 1 diff --git a/game-example/main.tscn b/game-example/main.tscn index 7b5d100..cd1ebf1 100644 --- a/game-example/main.tscn +++ b/game-example/main.tscn @@ -2,6 +2,7 @@ [ext_resource type="Script" uid="uid://py2tglj0jfff" path="res://Main.cs" id="1_ig7tw"] [ext_resource type="Script" uid="uid://ctgotmluglc5k" path="res://fishyflip/FishyFlipHandler.cs" id="2_0xm2m"] +[ext_resource type="Script" uid="uid://dgvd1bhf184ok" path="res://microcosm/MicrocosmLeaderboardView.cs" id="3_h2yge"] [node name="Node2D" type="Control" unique_id=1655432914 node_paths=PackedStringArray("NameField", "Handler", "ResultLabel")] layout_mode = 3 @@ -13,9 +14,9 @@ grow_vertical = 2 size_flags_horizontal = 3 size_flags_vertical = 3 script = ExtResource("1_ig7tw") -NameField = NodePath("VBoxContainer/Name Field") +NameField = NodePath("HBoxContainer/Login/Name Field") Handler = NodePath("Handler") -ResultLabel = NodePath("VBoxContainer/Result Label") +ResultLabel = NodePath("HBoxContainer/Login/Result Label") [node name="Handler" type="Control" parent="." unique_id=523132026] anchors_preset = 0 @@ -24,37 +25,68 @@ offset_bottom = 40.0 script = ExtResource("2_0xm2m") metadata/_custom_type_script = "uid://ctgotmluglc5k" -[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=381839677] +[node name="HBoxContainer" type="HBoxContainer" parent="." unique_id=982115913] +custom_minimum_size = Vector2(0, 648) layout_mode = 1 -anchors_preset = 8 +anchors_preset = -1 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 +offset_left = -141.5 +offset_top = -64.0 +offset_right = 141.5 +offset_bottom = 64.0 grow_horizontal = 2 grow_vertical = 2 -[node name="Name Field" type="LineEdit" parent="VBoxContainer" unique_id=230847250] +[node name="ScrollContainer" type="ScrollContainer" parent="HBoxContainer" unique_id=2104684361] +clip_contents = false +custom_minimum_size = Vector2(120, 648) +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 4 +horizontal_scroll_mode = 0 + +[node name="Scores" type="VBoxContainer" parent="HBoxContainer/ScrollContainer" unique_id=1158174777 node_paths=PackedStringArray("ConstellationRequest", "SlingshotRequest")] +layout_mode = 2 +size_flags_vertical = 6 +script = ExtResource("3_h2yge") +ConstellationRequest = NodePath("Constellation Request") +SlingshotRequest = NodePath("Slingshot Request") + +[node name="Constellation Request" type="HTTPRequest" parent="HBoxContainer/ScrollContainer/Scores" unique_id=1139114366] + +[node name="Slingshot Request" type="HTTPRequest" parent="HBoxContainer/ScrollContainer/Scores" unique_id=1243096252] + +[node name="Status" type="Label" parent="HBoxContainer/ScrollContainer/Scores" unique_id=2090426868] +custom_minimum_size = Vector2(120, 0) +layout_mode = 2 +text = "Loading..." +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="Login" type="VBoxContainer" parent="HBoxContainer" unique_id=381839677] +layout_mode = 2 +size_flags_vertical = 4 + +[node name="Name Field" type="LineEdit" parent="HBoxContainer/Login" unique_id=230847250] layout_mode = 2 placeholder_text = "you.tsunagite.dev" -[node name="Login Button" type="Button" parent="VBoxContainer" unique_id=644165583] +[node name="Login Button" type="Button" parent="HBoxContainer/Login" unique_id=644165583] layout_mode = 2 text = "Log in with ATProto" -[node name="Result Label" type="Label" parent="VBoxContainer" unique_id=768867823] +[node name="Result Label" type="Label" parent="HBoxContainer/Login" unique_id=768867823] layout_mode = 2 horizontal_alignment = 1 -[node name="Button" type="Button" parent="VBoxContainer" unique_id=1057476799] +[node name="Button" type="Button" parent="HBoxContainer/Login" unique_id=1057476799] layout_mode = 2 text = "Do the thing" [connection signal="AuthComplete" from="Handler" to="." method="_OnAuthComplete"] [connection signal="HandleLoaded" from="Handler" to="." method="_OnHandleLoaded"] -[connection signal="pressed" from="VBoxContainer/Login Button" to="." method="_OnLoginPressed"] -[connection signal="pressed" from="VBoxContainer/Button" to="." method="_OnDoThingPressed"] +[connection signal="pressed" from="HBoxContainer/Login/Login Button" to="." method="_OnLoginPressed"] +[connection signal="pressed" from="HBoxContainer/Login/Button" to="." method="_OnDoThingPressed"] diff --git a/game-example/microcosm/MicrocosmLeaderboardView.cs b/game-example/microcosm/MicrocosmLeaderboardView.cs new file mode 100644 index 0000000..cb7444e --- /dev/null +++ b/game-example/microcosm/MicrocosmLeaderboardView.cs @@ -0,0 +1,92 @@ +using Godot; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.Json; + +//A leaderboard view assembled using Microcosm's Constellation and Slingshot services without a dedicated Tsunagite server middleware. +//This uses a lot of requests overall, which middleware can make less of an issue. +//FIXME: for some reason, Slingshot is taking thirty seconds to respond to *every request!* what's going on?! +public partial class MicrocosmLeaderboardView : VBoxContainer { + private const string chart = "at://lemmaeof.gay/dev.tsunagite.chart/mirinTestSong-expert"; + private static readonly string constellationQuery = $"https://constellation.microcosm.blue/xrpc/blue.microcosm.links.getBacklinks?subject={chart.URIEncode()}&source=dev.tsunagite.score%3Achart&limit=16"; + private static readonly PackedScene SCORE_DISPLAY = GD.Load("res://ScoreDisplay.tscn"); + + [Export] + public HttpRequest ConstellationRequest; + [Export] + public HttpRequest SlingshotRequest; + + // Called when the node enters the scene tree for the first time. + public override void _Ready() { + BuildLeaderboard(); + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(double delta) { + } + + private async void BuildLeaderboard() { + GetNode