Auto-update offsets in C#
Use the built-in HttpClient and System.Text.Json APIs to retrieve and parse the current dataset without additional packages.
Request
Use JSON for runtime loading. Change the dataset to fflags when you need the flag registry instead of property offsets.
GET
https://api.decamp.dev/v1/latest?game=roblox&dataset=offsets&format=json- game
- roblox
- dataset
- offsets / fflags
- format
- json / hpp
Before you start
01
.NET 6 or newer.02
Network access to
api.decamp.dev.03
HttpClient and System.Text.Json are included with .NET.Create a shared HttpClient helper
using System.Globalization;
using System.Net.Http;
using System.Text.Json;
static readonly HttpClient Http = new()
{
BaseAddress = new Uri("https://api.decamp.dev")
};
static async Task<JsonDocument> GetOffsetsAsync()
{
using var response = await Http.GetAsync(
"/v1/latest?game=roblox&dataset=offsets&format=json");
response.EnsureSuccessStatusCode();
await using var stream = await response.Content.ReadAsStreamAsync();
return await JsonDocument.ParseAsync(stream);
}Find an offset by name
Read the class and field directly from the nested Offsets object and keep lookup failures on a normal Try path.
static bool TryFindOffset(
JsonElement data,
string className,
string propertyName,
out ulong offset)
{
offset = 0;
if (!data.TryGetProperty("Offsets", out var offsets))
return false;
if (!offsets.TryGetProperty(className, out var classOffsets))
return false;
if (!classOffsets.TryGetProperty(propertyName, out var entry))
return false;
var value = entry.GetString();
if (value is null || !value.StartsWith("0x"))
return false;
return ulong.TryParse(
value.AsSpan(2),
NumberStyles.HexNumber,
CultureInfo.InvariantCulture,
out offset);
}
Putting it together
Load the dataset, query the verified class and property pair, and retain the result for later use.
using var document = await GetOffsetsAsync();
var data = document.RootElement;
if (!TryFindOffset(
data,
"ClimbController",
"BalanceSpeed",
out var balanceSpeed))
{
Console.Error.WriteLine("[-] offset is unavailable");
return;
}
var generated = data.GetProperty("Dumped At").GetString();
var resolved = data.GetProperty("Total Offsets").GetInt32();
Console.WriteLine($"[+] generated: {generated ?? "unknown"}");
Console.WriteLine($"[+] resolved: {resolved}");
Console.WriteLine($"[+] ClimbController::BalanceSpeed: 0x{balanceSpeed:X}");Responses
200The selected file was returned.304No update. The cached file is still current.400The dataset or format is invalid.404The game or route does not exist.405The endpoint only accepts GET, HEAD, and OPTIONS.409The selected game is known but not available yet.500The service encountered an unexpected error.503The generated file is temporarily unavailable.