Skip to content

Add a web label#883

Open
11EJDE11 wants to merge 12 commits into
CnCNet:developfrom
11EJDE11:feat-web-label-2
Open

Add a web label#883
11EJDE11 wants to merge 12 commits into
CnCNet:developfrom
11EJDE11:feat-web-label-2

Conversation

@11EJDE11

Copy link
Copy Markdown
Member

This PR adds a label that can query JSON data from a datasource. We can use this for the online player count, for ladder ranking, or news. INI datasources are also supported.

Datasources are specified in ClientDefinitions.ini

[DataSources]
DataSourceID=URL,RefreshIntervalSeconds,TimeoutSeconds,Format ;example: TopPlayers=https://ladder.cncnet.org/api/v1/qm/ladder/rankings,300,10,json|ini

Labels then point to a datasource and can query the JSON.

[ExtraControls]
1=lblTopPlayer1:XNAClientJSONLabel

[lblTopPlayer1]
$Type=XNAClientJSONLabel
DataSourceID=TopPlayers
Template=1. {YR[0].player_name} - {YR[0].points:N0} pts
LoadingText=Loading...
FallbackText=---
FontIndex=1
RemapColor=230,230,230
Location=360,166

See INISytem.md for more info.

Excuse the crappy screenshot.
image

@github-actions

github-actions Bot commented Nov 17, 2025

Copy link
Copy Markdown

Nightly build for this pull request:

  • artifacts.zip
    This comment is automatic and is meant to allow guests to get latest automatic builds without registering. It is updated on every successful build.

@Metadorius Metadorius left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Gave you some feedback.

Generally though while this approach definitely has it's place, I am not sure if we should do an explicit separate data source manager? My thoughts were more about something like an implicit manager class; different labels could have content URL endpoints specified right in place, and the response will be shared between them by that class (say, if the requests came to the manager in span of half a minute, then give the same data to every subscriber; if something updates the URL -- then all of the consumers of that URL will receive that).

Not fully set on the above, what are your thoughts?

cc @SadPencil @MahBoiDeveloper @Starkku @Rampastring

Comment thread ClientGUI/XNAClientJSONLabel.cs Outdated
Comment on lines +158 to +179
private List<string> ParseJSONPath(string json, string path)
{
try
{
var root = Newtonsoft.Json.Linq.JToken.Parse(json);
var results = new List<string>();

var tokens = root.SelectTokens(path);

if (tokens != null)
foreach (var token in tokens)
if (token != null)
results.Add(token.ToString());

return results.Count > 0 ? results : null;
}
catch (Exception ex)
{
Logger.Log($"JSONPath error: {ex.Message}");
return null;
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should happen way earlier at manager stage, and the control should only receive a parsed json and do template substitution, otherwise we're duplicating work.

Also we already use System.Text.Json, I see that it has no support for JSON Path for some reason, maybe this extension to System.Text.Json would do better? https://www.nuget.org/packages/JsonPath.Net Just so we don't introduce two similar libraries.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSON is now parsed to JToken in the manager and the label only does template substitution, so the duplication is sorted. Regarding JsonPath.NET, I couldn't get this working in an acceptable manner.

Comment thread ClientGUI/XNAClientJSONLabel.cs Outdated
Comment thread ClientCore/JSONDataSourceManager.cs Outdated
Comment thread ClientCore/JSONDataSourceManager.cs Outdated
Comment thread ClientCore/JSONDataSourceManager.cs Outdated
Comment thread ClientCore/JSONDataSourceManager.cs Outdated
Comment thread ClientCore/JSONDataSourceManager.cs Outdated
private readonly string _url;
private readonly int _refreshIntervalSeconds;
private readonly int _timeoutSeconds;
private readonly string _format;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this _format should be either an enum and/or maybe even a tiny simple interface/class with one method that converts input value (stream?) and gives JSON for arbitrary data representation.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with an interface. So we can decouple some string parsing logic from the UI logic. My recent editing experience on LAN lobby shows that it might waste a huge amount of time to maintain codes if different kinds of logics are not decoupled

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in the latest commit - IDataSourceFormat.

{
private readonly string _id;
private readonly string _url;
private readonly int _refreshIntervalSeconds;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it run even in background or when controls using it is not active?

although I realise now that it will probably complicate the code a lot, so I don't think there's a big need in doing it exactly. but if there is a lot of players that don't go online -- maybe autorefresh isn't something we may want to do? it will strain our servers quite a bit, maybe we should update just when the control is shown for the first time? (or sth in this direction)

Comment thread ClientGUI/XNAClientJSONLabel.cs Outdated
Comment thread ClientGUI/XNAClientJSONLabel.cs Outdated
Update datasources format in ClientDefintions
Add localisation
Change to XNAClientWebLabel
…er already handles them.

Replace _format string with IDataSourceFormat interface.
IniDataSourceFormat now builds a JObject directly
@11EJDE11 11EJDE11 requested review from Metadorius and SadPencil April 6, 2026 03:02
@SadPencil SadPencil added this to the 2.13.1 milestone May 5, 2026
@SadPencil SadPencil modified the milestones: 2.13.1, long term Jun 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants