TmScores 1.0.0
dotnet add package TmScores --version 1.0.0
NuGet\Install-Package TmScores -Version 1.0.0
<PackageReference Include="TmScores" Version="1.0.0" />
<PackageVersion Include="TmScores" Version="1.0.0" />
<PackageReference Include="TmScores" />
paket add TmScores --version 1.0.0
#r "nuget: TmScores, 1.0.0"
#:package TmScores@1.0.0
#addin nuget:?package=TmScores&version=1.0.0
#tool nuget:?package=TmScores&version=1.0.0
TmScores
A .NET library for reading and writing Trackmania master server score files.
Score files are cached leaderboards and medal ranks used between TrackMania Forever and ManiaPlanet 3 versions of Trackmania (2008-2015).
Scores types
| Type | Description |
|---|---|
CampaignScores |
Per-zone or per-group campaign scores, including per-map challenge scores and medal leagues |
ChallengeScores |
Per-league scores for an individual map |
GeneralScores |
Overall skillpoints and high score leaderboards per league |
LadderScores |
Ladder rankings and player counts per league |
Usage
Install the NuGet package:
dotnet add package TmScores
Deserialize
All scores types expose a static Deserialize method that accepts a file path or stream. Files are expected to be gzip-compressed (the standard stored format).
Campaign scores:
using TmScores;
var scores = CampaignScores.Deserialize("UnitedRace104085.gz");
Challenge scores (single map):
var scores = ChallengeScores.Deserialize("BeySZdnfuSh4nHY5xztiXLmlrXe.gz");
General scores:
var scores = GeneralScores.Deserialize("General104085.gz");
Ladder scores:
var scores = LadderScores.Deserialize("Multi104085.gz");
Deserialize raw (uncompressed)
Use DeserializeRaw to read from an uncompressed stream:
var scores = CampaignScores.DeserializeRaw("UnitedRace104085");
Serialize
All scores types support round-trip serialization back to the compressed binary format:
using var ms = new MemoryStream();
scores.Serialize(ms);
Or to a file:
scores.Serialize("output.gz");
Use SerializeRaw to write uncompressed.
Build scores from scratch
All types support collection initializer syntax:
var scores = new CampaignScores
{
new CampaignLeague
{
Name = "World|Czech republic|Jihoceský kraj",
ChallengeScores =
[
new CampaignChallengeScores("4kQ_0mHdJtnSdsQty9ZX0W8SDb1")
{
new Scores
{
LeagueName = "World",
Skillpoints = [new RecordUnit<int>(22060, 1)],
HighScores = [new HighScore(1, 22060, "jack1998-1998", "$i$f00ғ$c00ฟ$900๏.$fffRollin $f00¬ $c00Law")]
}
}
],
MedalLeagues =
[
new CampaignMedalLeague("World")
{
new CampaignMedalPlayMode(PlayMode.Race, [new RecordUnit<int>(22060, 1)])
}
]
}
};
var scores = new LadderScores
{
new LadderLeague { Name = "World", PlayerCount = 9782572, Points = [(1, 100), (2, 90)] },
new LadderLeague { Name = "World|Czech republic", PlayerCount = 385442, Points = [(1, 80), (2, 70)] }
};
var scores = new ChallengeScores
{
new Scores
{
LeagueName = "World",
Skillpoints = [new RecordUnit<int>(1112, 1)],
HighScores = [new HighScore(1, 1112, "bigbang1112", "BigBang1112")]
}
};
Timestamp
When deserializing from a gzip stream, the modification timestamp embedded in the gzip header is exposed via the Timestamp property:
var scores = CampaignScores.Deserialize("UnitedRace104085.gz");
Console.WriteLine(scores.Timestamp); // DateTimeOffset, or null if unavailable
Data model
CampaignScores (ICollection<CampaignLeague>)
└── CampaignLeague
├── ChallengeScores[] (CampaignChallengeScores per map)
│ └── Scores[] (per league)
│ ├── Skillpoints (RecordUnit<int>[])
│ └── HighScores (HighScore[])
└── MedalLeagues[] (CampaignMedalLeague per league)
└── CampaignMedalPlayMode[] (per PlayMode)
└── RecordUnit<int>[]
GeneralScores (ICollection<Scores>)
└── Scores
├── Skillpoints (RecordUnit<int>[])
└── HighScores (HighScore[])
ChallengeScores (ICollection<Scores>)
└── Scores
├── Skillpoints (RecordUnit<int>[])
└── HighScores (HighScore[])
LadderScores (ICollection<LadderLeague>)
└── LadderLeague
├── PlayerCount (int)
└── Points ((int Rank, int Points)[])
Key types
| Type | Description |
|---|---|
RecordUnit<T> |
A score value (Score) paired with a player count (Count) |
HighScore |
A leaderboard entry: Rank, Score, Login, Nickname, optional FilePath and GhostUrl |
PlayMode |
Race, Puzzle, Platform, Stunts |
Showcase
Simple scores viewer and editor is available here.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on TmScores:
| Package | Downloads |
|---|---|
|
ManiaAPI.Xml
Wrapper for the XML API used in TMF and ManiaPlanet. Part of the ManiaAPI.NET library set. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 158 | 5/9/2026 |