Browse Source

Refactor `APlayerID` to generate raw `SteamData`

To avoid needless creation of `APlayerID` classes we need to provide a
separate static method `GetSteamDataFromSteamID64()` that will generate
raw `SteamData` that we can then compare to existing instances of
`APlayerID`.
pull/8/head
Anton Tarasenko 4 years ago
parent
commit
b004114a65
  1. 85
      sources/Players/APlayerID.uc
  2. 2
      sources/Players/Tests/TEST_Player.uc

85
sources/Players/APlayerID.uc

@ -37,8 +37,11 @@ struct SteamData
// 32 lowest bits of SteadID64. // 32 lowest bits of SteadID64.
// Corresponds to a combination of "Y" and "Z" in "STEAM_X:Y:Z". // Corresponds to a combination of "Y" and "Z" in "STEAM_X:Y:Z".
var public int steamID32; var public int steamID32;
// Other 4 fields fully define a SteamID and `steamID64` can be generated // Other 4 fields fully define a SteamID and `steamID64` can be
// from them, but it is easier to simply cache it in a separate variable. // generated from them, but it is easier to simply cache it in
// a separate variable.
// `SteamData` is considered valid iff `steamID64` is equal to
// Steam64 ID that can be generated from other variables.
var string steamID64; var string steamID64;
}; };
var protected SteamData initializedData; var protected SteamData initializedData;
@ -50,7 +53,7 @@ var protected bool initialized;
// (425327 <-> [4, 2, 5, 3, 2, 7]) // (425327 <-> [4, 2, 5, 3, 2, 7])
// return given number mod 2 and // return given number mod 2 and
// divide that number by two (record result in that same array) // divide that number by two (record result in that same array)
private final function int DivideDigitArrayByTwo(out array<int> digits) private static final function int DivideDigitArrayByTwo(out array<int> digits)
{ {
local int i; local int i;
local int wasOdd; local int wasOdd;
@ -76,7 +79,7 @@ private final function int DivideDigitArrayByTwo(out array<int> digits)
// Given a number in form of array (`digits`) of it's digits // Given a number in form of array (`digits`) of it's digits
// (425327 <-> [4, 2, 5, 3, 2, 7]) // (425327 <-> [4, 2, 5, 3, 2, 7])
// extracts `bitsToRead` of lower bits from it and returns them as an `int`. // extracts `bitsToRead` of lower bits from it and returns them as an `int`.
private final function int ReadBitsFromDigitArray( private static final function int ReadBitsFromDigitArray(
out array<int> digits, out array<int> digits,
int bitsToRead) int bitsToRead)
{ {
@ -121,41 +124,62 @@ private final function string GetSteamAccountTypeCharacter()
} }
/** /**
* Initializes caller `APlayerID` from a given `string` ID. * Helper function that generates `SteamData` structure from
* a given Steam64 ID.
* *
* Each `APLayerID` can only be initialized once and becomes immutable * In case invalid ID is given this method will not raise any warning and
* afterwards. * returned value should be considered undefined.
*
* @param steamID64 `string` with unique ID, provided by the game
* (Steam64 ID used in profile permalink,
* like http://steamcommunity.com/profiles/76561198025127722)
* *
* @return `true` if initialization was successful and `false` otherwise * @param steamID64 Steam64 ID's decimal representation in a plain string.
* (can only happen if caller `APlayerID` was already initialized). * @return `SteamData` generated from a given Steam64 ID `steamID64`.
*/ */
public final function bool Initialize(string steamID64) public static final function SteamData GetSteamDataFromSteamID64(
string steamID64)
{ {
local int i; local int i;
local SteamData newSteamData;
local array<Text.Character> characters; local array<Text.Character> characters;
local array<int> digits; local array<int> digits;
if (initialized) return false;
characters = _().text.StringToRaw(steamID64); characters = _().text.StringToRaw(steamID64);
for (i = 0; i < characters.length; i += 1) { for (i = 0; i < characters.length; i += 1) {
digits[digits.length] = _().text.CharacterToInt(characters[i]); digits[digits.length] = _().text.CharacterToInt(characters[i]);
} }
initializedData.steamID64 = steamID64; newSteamData.steamID64 = steamID64;
// Refer to https://developer.valvesoftware.com/wiki/SteamID // Refer to https://developer.valvesoftware.com/wiki/SteamID
// The lowest bit represents Y. // The lowest bit represents Y.
// The next 31 bits represents the account number. // The next 31 bits represents the account number.
// ^ these two can be combined into a "SteamID32". // ^ these two can be combined into a "SteamID32".
initializedData.steamID32 = ReadBitsFromDigitArray(digits, 32); newSteamData.steamID32 = ReadBitsFromDigitArray(digits, 32);
// The next 20 bits represents the instance of the account. // The next 20 bits represents the instance of the account.
initializedData.instance = ReadBitsFromDigitArray(digits, 20); newSteamData.instance = ReadBitsFromDigitArray(digits, 20);
// The next 4 bits represents the type of account. // The next 4 bits represents the type of account.
initializedData.accountType = ReadBitsFromDigitArray(digits, 4); newSteamData.accountType = ReadBitsFromDigitArray(digits, 4);
// The next 8 bits represents the "Universe" the steam account belongs to. // The next 8 bits represents the "Universe" the steam account belongs to.
initializedData.universe = ReadBitsFromDigitArray(digits, 8); newSteamData.universe = ReadBitsFromDigitArray(digits, 8);
return newSteamData;
}
/**
* Initializes caller `APlayerID` from a given `string` ID.
*
* Each `APLayerID` can only be initialized once and becomes immutable
* afterwards.
*
* @param steamID64 `string` with unique ID, provided by the game
* (Steam64 ID used in profile permalink,
* like http://steamcommunity.com/profiles/76561198025127722)
*
* @return `true` if initialization was successful and `false` otherwise
* (can only happen if caller `APlayerID` was already initialized).
*/
public final function bool Initialize(string steamID64)
{
if (initialized) {
return false;
}
initializedData = GetSteamDataFromSteamID64(steamID64);
initialized = true; initialized = true;
return true; return true;
} }
@ -200,6 +224,27 @@ public final function bool IsEqual(APlayerID otherID)
return (initializedData.steamID32 == otherID.initializedData.steamID32); return (initializedData.steamID32 == otherID.initializedData.steamID32);
} }
/**
* Checks if caller `APlayerID`s is the same as what's described by
* given `SteamData`.
*
* NOTE: only part of the `otherSteamData` might be used for comparison.
* It is up to user to ensure that given `otherSteamData` is valid.
*
* @param otherSteamData `SteamData` to compare caller `APlayerID` to.
* @return `true` if caller `APlayerID` is identical to ID described by
* `otherSteamData` and `false` otherwise.
* If caller `APlayerID` is uninitialized, the result will be `false`.
*/
public final function bool IsEqualToSteamData(SteamData otherSteamData)
{
if (!IsInitialized()) {
return false;
}
return (initializedData.steamID32 == otherSteamData.steamID32);
}
/** /**
* Returns unique string representation of the caller `APlayerData`. * Returns unique string representation of the caller `APlayerData`.
* *

2
sources/Players/Tests/TEST_Player.uc

@ -50,8 +50,8 @@ protected static function Test_PlayerID()
testID3 = APlayerID(_().memory.Allocate(class'APlayerID')); testID3 = APlayerID(_().memory.Allocate(class'APlayerID'));
testID2.Initialize("76561198025127722"); testID2.Initialize("76561198025127722");
testID3.Initialize("76561198044316328"); testID3.Initialize("76561198044316328");
TEST_ExpectTrue(testID.IsEqual(testID));
TEST_ExpectTrue(testID.IsEqual(testID2)); TEST_ExpectTrue(testID.IsEqual(testID2));
TEST_ExpectTrue(testID.IsEqualToSteamData(testID2.GetSteamData()));
TEST_ExpectFalse(testID3.IsEqual(testID)); TEST_ExpectFalse(testID3.IsEqual(testID));
Issue("Steam data returned by `APlayerID` is incorrect."); Issue("Steam data returned by `APlayerID` is incorrect.");

Loading…
Cancel
Save