From b004114a6570e594cb6f7071330f458d97f9bee2 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sun, 9 Aug 2020 23:47:14 +0700 Subject: [PATCH] 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`. --- sources/Players/APlayerID.uc | 87 +++++++++++++++++++++------- sources/Players/Tests/TEST_Player.uc | 2 +- 2 files changed, 67 insertions(+), 22 deletions(-) diff --git a/sources/Players/APlayerID.uc b/sources/Players/APlayerID.uc index 26ed045..a510fd2 100644 --- a/sources/Players/APlayerID.uc +++ b/sources/Players/APlayerID.uc @@ -37,8 +37,11 @@ struct SteamData // 32 lowest bits of SteadID64. // Corresponds to a combination of "Y" and "Z" in "STEAM_X:Y:Z". var public int steamID32; - // Other 4 fields fully define a SteamID and `steamID64` can be generated - // from them, but it is easier to simply cache it in a separate variable. + // Other 4 fields fully define a SteamID and `steamID64` can be + // 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 protected SteamData initializedData; @@ -50,7 +53,7 @@ var protected bool initialized; // (425327 <-> [4, 2, 5, 3, 2, 7]) // return given number mod 2 and // divide that number by two (record result in that same array) -private final function int DivideDigitArrayByTwo(out array digits) +private static final function int DivideDigitArrayByTwo(out array digits) { local int i; local int wasOdd; @@ -76,7 +79,7 @@ private final function int DivideDigitArrayByTwo(out array digits) // Given a number in form of array (`digits`) of it's digits // (425327 <-> [4, 2, 5, 3, 2, 7]) // 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 digits, int bitsToRead) { @@ -121,42 +124,63 @@ 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 - * afterwards. - * - * @param steamID64 `string` with unique ID, provided by the game - * (Steam64 ID used in profile permalink, - * like http://steamcommunity.com/profiles/76561198025127722) + * In case invalid ID is given this method will not raise any warning and + * returned value should be considered undefined. * - * @return `true` if initialization was successful and `false` otherwise - * (can only happen if caller `APlayerID` was already initialized). + * @param steamID64 Steam64 ID's decimal representation in a plain string. + * @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 SteamData newSteamData; local array characters; local array digits; - if (initialized) return false; characters = _().text.StringToRaw(steamID64); for (i = 0; i < characters.length; i += 1) { digits[digits.length] = _().text.CharacterToInt(characters[i]); } - initializedData.steamID64 = steamID64; + newSteamData.steamID64 = steamID64; // Refer to https://developer.valvesoftware.com/wiki/SteamID // The lowest bit represents Y. // The next 31 bits represents the account number. // ^ 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. - initializedData.instance = ReadBitsFromDigitArray(digits, 20); + newSteamData.instance = ReadBitsFromDigitArray(digits, 20); // 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. - initializedData.universe = ReadBitsFromDigitArray(digits, 8); - initialized = true; + 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; return true; } @@ -200,6 +224,27 @@ public final function bool IsEqual(APlayerID otherID) 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`. * diff --git a/sources/Players/Tests/TEST_Player.uc b/sources/Players/Tests/TEST_Player.uc index 28bbcd0..b85cb56 100644 --- a/sources/Players/Tests/TEST_Player.uc +++ b/sources/Players/Tests/TEST_Player.uc @@ -50,8 +50,8 @@ protected static function Test_PlayerID() testID3 = APlayerID(_().memory.Allocate(class'APlayerID')); testID2.Initialize("76561198025127722"); testID3.Initialize("76561198044316328"); - TEST_ExpectTrue(testID.IsEqual(testID)); TEST_ExpectTrue(testID.IsEqual(testID2)); + TEST_ExpectTrue(testID.IsEqualToSteamData(testID2.GetSteamData())); TEST_ExpectFalse(testID3.IsEqual(testID)); Issue("Steam data returned by `APlayerID` is incorrect.");