102 lines
3.3 KiB
C#
102 lines
3.3 KiB
C#
using System.Text;
|
|
|
|
namespace Ashwild.Network
|
|
{
|
|
/// <summary>
|
|
/// Converts between a host's SteamID64 and a short, shareable session code.
|
|
/// A SteamID64 is a 17-digit number; an individual account only differs from the others
|
|
/// by its 32-bit account id (SteamID64 = IndividualBase + accountId), so we encode just
|
|
/// that account id in base36 to get a ~6-7 character code mixing digits and letters.
|
|
/// The conversion is fully reversible, so the joiner can rebuild the exact SteamID64.
|
|
/// </summary>
|
|
public static class SessionCode
|
|
{
|
|
#region Constants
|
|
|
|
/// <summary>
|
|
/// Base offset of every individual (public-universe) SteamID64 — 0x0110000100000000.
|
|
/// Subtracting it leaves only the 32-bit account id worth encoding.
|
|
/// </summary>
|
|
private const ulong IndividualBase = 76561197960265728UL;
|
|
|
|
/// <summary>
|
|
/// Base36 alphabet (digits + uppercase letters) used to render the short code.
|
|
/// </summary>
|
|
private const string Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
|
|
#endregion
|
|
|
|
#region Public API
|
|
|
|
/// <summary>
|
|
/// Builds the short shareable code from a full SteamID64.
|
|
/// </summary>
|
|
public static string FromSteamId(ulong steamId64)
|
|
{
|
|
ulong accountId = steamId64 >= IndividualBase ? steamId64 - IndividualBase : steamId64;
|
|
return ToBase36(accountId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parses a short code back into a full SteamID64. Accepts either the new base36 code
|
|
/// or a raw legacy SteamID64 string. Returns false when the code is empty or malformed.
|
|
/// </summary>
|
|
public static bool TryToSteamId(string code, out ulong steamId64)
|
|
{
|
|
steamId64 = 0;
|
|
if (string.IsNullOrWhiteSpace(code)) return false;
|
|
|
|
code = code.Trim().ToUpperInvariant();
|
|
|
|
// Backward-compat: a raw 17-digit SteamID64 pasted as-is.
|
|
if (ulong.TryParse(code, out ulong raw) && raw >= IndividualBase)
|
|
{
|
|
steamId64 = raw;
|
|
return true;
|
|
}
|
|
|
|
if (!TryFromBase36(code, out ulong accountId)) return false;
|
|
|
|
steamId64 = accountId + IndividualBase;
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Internal Helpers
|
|
|
|
/// <summary>
|
|
/// Renders an unsigned value as a base36 string (most-significant digit first).
|
|
/// </summary>
|
|
private static string ToBase36(ulong value)
|
|
{
|
|
if (value == 0) return "0";
|
|
|
|
StringBuilder sb = new StringBuilder(13);
|
|
while (value > 0)
|
|
{
|
|
sb.Insert(0, Alphabet[(int)(value % 36)]);
|
|
value /= 36;
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parses a base36 string into an unsigned value; false on any non-alphabet character.
|
|
/// </summary>
|
|
private static bool TryFromBase36(string code, out ulong value)
|
|
{
|
|
value = 0;
|
|
foreach (char c in code)
|
|
{
|
|
int digit = Alphabet.IndexOf(c);
|
|
if (digit < 0) return false;
|
|
value = value * 36 + (ulong)digit;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|