diff --git a/sources/Users/UserAPI.uc b/sources/Users/UserAPI.uc index 6f9eb63..330c2e5 100644 --- a/sources/Users/UserAPI.uc +++ b/sources/Users/UserAPI.uc @@ -22,6 +22,11 @@ class UserAPI extends AcediaObject var private config string userdataDBLink; +// Active `Users_Feature`, remember it along with life version to avoid +// taking up a reference +var private int usersFeatureLifeVersion; +var private Users_Feature usersFeature; + // Database where user's data (persistent data and user groups) is stored var private Database persistentDatabase; @@ -35,6 +40,23 @@ protected function Constructor() SetupUserDataDatabase(); } +// DO NOT CALL MANUALLY +public function _reloadFeature() +{ + if ( usersFeature != none + && usersFeature.GetLifeVersion() == usersFeatureLifeVersion) + { + usersFeature.FreeSelf(); + usersFeature = none; + } + usersFeature = + Users_Feature(class'Users_Feature'.static.GetEnabledInstance()); + if (usersFeature != none) { + usersFeatureLifeVersion = usersFeature.GetLifeVersion(); + } + _.memory.Free(usersFeature); +} + // Loads persistent user database, specified by the AcediaCore's config and // creates a basic skeleton for storing its data private function SetupUserDataDatabase() @@ -233,11 +255,12 @@ public final function User FetchByKey(int userKey) /** * Returns names of all available groups that users can belong to. * - * In case this feature is configured to load user groups from a database - * (either local or remote), the returned value is a locally cached one. - * This helps us avoid having to query database each time we want to check - * something about user groups, but it also means we might have an outdated - * information. + * Will only work if `Users_Feature` is active. + * In case active config of `Users_Feature` is configured to load user + * groups from a database (either local or remote), the returned value is + * a locally cached one. This helps us avoid having to query database each time + * we want to check something about user groups, but it also means we might + * have an outdated information. * * @return Array with names of all available groups. * All array elements are guaranteed to be not-`none`, unique and in @@ -245,22 +268,296 @@ public final function User FetchByKey(int userKey) */ public final function array GetAvailableGroups() { - local Users_Feature usersFeature; - local array result; + local array emptyResult; - usersFeature = Users_Feature(class'Users_Feature'.static - .GetEnabledInstance()); - if (usersFeature == none) { - return result; + if (usersFeature != none) { + return usersFeature.GetAvailableGroups(); } - result = usersFeature.GetAvailableGroups(); - usersFeature.FreeSelf(); - return result; + return emptyResult; +} + +/** + * Adds a new user group. + * + * Will only work if `Users_Feature` is active. + * In case active config of `Users_Feature` is configured to load user + * groups from a database (either local or remote), the returned value is + * a locally cached one. This helps us avoid having to query database each time + * we want to check something about user groups, but it also means we might + * have an outdated information. + * Changes will always persist for the duration of the match, but writing + * them into the (non-config) source might fail, leading to changes being reset + * after the level switch. For non-database (config) sources changes will + * always be saved. + * + * @param groupName Name of the group to add. Case-insensitive. + * @return `true` if group was added and `false` otherwise (including if it + * already existed). + */ +public final function bool AddGroup(BaseText groupName) +{ + if (usersFeature != none) { + return usersFeature.AddGroup(groupName); + } + return false; +} + +/** + * Removes existing user group. + * + * Will only work if `Users_Feature` is active. + * In case active config of `Users_Feature` is configured to load user + * groups from a database (either local or remote), the returned value is + * a locally cached one. This helps us avoid having to query database each time + * we want to check something about user groups, but it also means we might + * have an outdated information. + * Changes will always persist for the duration of the match, but writing + * them into the (non-config) source might fail, leading to changes being reset + * after the level switch. For non-database (config) sources changes will + * always be saved. + * + * @param groupName Name of the group to remove. Case-insensitive. + * @return `true` if group was removed and `false` otherwise (including if it + * didn't exist in the first place). + */ +public final function bool RemoveGroup(BaseText groupName) +{ + if (usersFeature != none) { + return usersFeature.RemoveGroup(groupName); + } + return false; +} + +/** + * Checks whether group with specified name exists. + * + * Will only work if `Users_Feature` is active. + * In case active config of `Users_Feature` is configured to load user + * groups from a database (either local or remote), the returned value is + * a locally cached one. This helps us avoid having to query database each time + * we want to check something about user groups, but it also means we might + * have an outdated information. + * + * @param groupName Name of the group to check existence of. + * Case-insensitive. + * @return `true` if group exists and `false` otherwise. + */ +public final function bool IsGroupExisting(BaseText groupName) +{ + if (usersFeature != none) { + return usersFeature.IsGroupExisting(groupName); + } + return false; +} + +/** + * Adds user with the given SteamID into the specified group. + * + * Will only work if `Users_Feature` is active. + * In case active config of `Users_Feature` is configured to load user + * groups from a database (either local or remote), changes are guaranteed to + * be made to the locally cached copy that will persist for the duration of + * the game. Method will also attempt to change the database value, but that is + * not guaranteed to succeed, meaning that changes might not be saved for + * later matches. + * + * @param steamID SteamID of the user to add to the group. + * @param groupName Name of the group to add user to. Case-insensitive. + * @return `true` if user was added to the group (including if her was already + * added to it) and `false` in any other case. + */ +public final function bool AddSteamIDToGroup( + BaseText steamID, + BaseText groupName) +{ + if (usersFeature != none) { + return usersFeature.AddSteamIDToGroup(steamID, groupName); + } + return false; +} + +/** + * Adds user with the given SteamID into the specified group. + * + * Will only work if `Users_Feature` is active. + * In case active config of `Users_Feature` is configured to load user + * groups from a database (either local or remote), changes are guaranteed to + * be made to the locally cached copy that will persist for the duration of + * the game. Method will also attempt to change the database value, but that is + * not guaranteed to succeed, meaning that changes might not be saved for + * later matches. + * + * @param steamID SteamID of the user to add to the group. + * @param groupName Name of the group to add user to. Case-insensitive. + * @return `true` if user was added to the group (including if her was already + * added to it) and `false` in any other case. + */ +public final /*unreal*/ function bool AddSteamIDToGroup_S( + string steamID, + string groupName) +{ + if (usersFeature != none) { + return usersFeature.AddSteamIDToGroup_S(steamID, groupName); + } + return false; +} + +/** + * Adds user (given by the `UserID`) into the specified group. + * + * Will only work if `Users_Feature` is active. + * In case active config of `Users_Feature` is configured to load user + * groups from a database (either local or remote), changes are guaranteed to + * be made to the locally cached copy that will persist for the duration of + * the game. Method will also attempt to change the database value, but that is + * not guaranteed to succeed, meaning that changes might not be saved for + * later matches. + * + * @param id `UserID` of the user to add to the group. + * @param groupName Name of the group to add user to. Case-insensitive. + * @return `true` if user was added to the group (including if her was already + * added to it) and `false` in any other case. + */ +public final function bool AddUserIDToGroup( + UserID id, + BaseText groupName) +{ + if (usersFeature != none) { + return usersFeature.AddUserIDToGroup(id, groupName); + } + return false; +} + +/** + * Adds given user into the specified group. + * + * Will only work if `Users_Feature` is active. + * In case active config of `Users_Feature` is configured to load user + * groups from a database (either local or remote), changes are guaranteed to + * be made to the locally cached copy that will persist for the duration of + * the game. Method will also attempt to change the database value, but that is + * not guaranteed to succeed, meaning that changes might not be saved for + * later matches. + * + * @param user User to add to the group. + * @param groupName Name of the group to add user to. Case-insensitive. + * @return `true` if user was added to the group (including if her was already + * added to it) and `false` in any other case. + */ +public final function bool AddUserToGroup(User user, BaseText groupName) +{ + if (usersFeature != none) { + return usersFeature.AddUserToGroup(user, groupName); + } + return false; +} + +/** + * Removes user with the given SteamID from the specified group. + * + * Will only work if `Users_Feature` is active. + * In case active config of `Users_Feature` is configured to load user + * groups from a database (either local or remote), changes are guaranteed to + * be made to the locally cached copy that will persist for the duration of + * the game. Method will also attempt to change the database value, but that is + * not guaranteed to succeed, meaning that changes might not be saved for + * later matches. + * + * @param steamID SteamID of the user to remove to the group. + * @param groupName Name of the group to remove user to. Case-insensitive. + * @return `true` if user was removed to the group (including if her was + * already removed to it) and `false` in any other case. + */ +public final function bool RemoveSteamIDFromGroup( + BaseText steamID, + BaseText groupName) +{ + if (usersFeature != none) { + return usersFeature.RemoveSteamIDFromGroup(steamID, groupName); + } + return false; +} + +/** + * Removes user with the given SteamID from the specified group. + * + * Will only work if `Users_Feature` is active. + * In case active config of `Users_Feature` is configured to load user + * groups from a database (either local or remote), changes are guaranteed to + * be made to the locally cached copy that will persist for the duration of + * the game. Method will also attempt to change the database value, but that is + * not guaranteed to succeed, meaning that changes might not be saved for + * later matches. + * + * @param steamID SteamID of the user to remove to the group. + * @param groupName Name of the group to remove user to. Case-insensitive. + * @return `true` if user was removed to the group (including if her was + * already removed to it) and `false` in any other case. + */ +public final /*unreal*/ function bool RemoveSteamIDFromGroup_S( + string steamID, + string groupName) +{ + if (usersFeature != none) { + return usersFeature.RemoveSteamIDFromGroup_S(steamID, groupName); + } + return false; +} + +/** + * Removes user (given by the `UserID`) from the specified group. + * + * Will only work if `Users_Feature` is active. + * In case active config of `Users_Feature` is configured to load user + * groups from a database (either local or remote), changes are guaranteed to + * be made to the locally cached copy that will persist for the duration of + * the game. Method will also attempt to change the database value, but that is + * not guaranteed to succeed, meaning that changes might not be saved for + * later matches. + * + * @param id `UserID` of the user to remove to the group. + * @param groupName Name of the group to remove user to. Case-insensitive. + * @return `true` if user was removed to the group (including if her was + * already removed to it) and `false` in any other case. + */ +public final function bool RemoveUserIDFromGroup( + UserID id, + BaseText groupName) +{ + if (usersFeature != none) { + return usersFeature.RemoveUserIDFromGroup(id, groupName); + } + return false; +} + +/** + * Removes user from the specified group. + * + * Will only work if `Users_Feature` is active. + * In case active config of `Users_Feature` is configured to load user + * groups from a database (either local or remote), changes are guaranteed to + * be made to the locally cached copy that will persist for the duration of + * the game. Method will also attempt to change the database value, but that is + * not guaranteed to succeed, meaning that changes might not be saved for + * later matches. + * + * @param user User to remove to the group. + * @param groupName Name of the group to remove user to. Case-insensitive. + * @return `true` if user was removed to the group (including if her was + * already removed to it) and `false` in any other case. + */ +public final function bool RemoveUserFromGroup(User user, BaseText groupName) +{ + if (usersFeature != none) { + return usersFeature.RemoveUserFromGroup(user, groupName); + } + return false; } /** * Returns names of all groups available for the user given by the SteamID. * + * Will only work if `Users_Feature` is active. * In case active config of `Users_Feature` is set up to load user groups * from a database (either local or remote), the returned value is a locally * cached one. This helps us avoid having to query database each time we want @@ -280,22 +577,18 @@ public final function array GetAvailableGroups() public final function array GetGroupsForSteamID( BaseText steamID) { - local Users_Feature usersFeature; - local array result; + local array emptyResult; - usersFeature = Users_Feature(class'Users_Feature'.static - .GetEnabledInstance()); - if (usersFeature == none) { - return result; + if (usersFeature != none) { + return usersFeature.GetGroupsForSteamID(steamID); } - result = usersFeature.GetGroupsForSteamID(steamID); - usersFeature.FreeSelf(); - return result; + return emptyResult; } /** * Returns names of all groups available for the user given by the SteamID. * + * Will only work if `Users_Feature` is active. * In case active config of `Users_Feature` is set up to load user groups * from a database (either local or remote), the returned value is a locally * cached one. This helps us avoid having to query database each time we want @@ -314,23 +607,19 @@ public final function array GetGroupsForSteamID( public final /*unreal*/ function array GetGroupsForSteamID_S( string steamID) { - local Users_Feature usersFeature; - local array result; + local array emptyResult; - usersFeature = Users_Feature(class'Users_Feature'.static - .GetEnabledInstance()); - if (usersFeature == none) { - return result; + if (usersFeature != none) { + return usersFeature.GetGroupsForSteamID_S(steamID); } - result = usersFeature.GetGroupsForSteamID_S(steamID); - usersFeature.FreeSelf(); - return result; + return emptyResult; } /** * Returns names of all groups available for the user given by the `UserID`. * + * Will only work if `Users_Feature` is active. * In case active config of `Users_Feature` is set up to load user groups * from a database (either local or remote), the returned value is a locally * cached one. This helps us avoid having to query database each time we want @@ -347,22 +636,18 @@ public final /*unreal*/ function array GetGroupsForSteamID_S( */ public final function array GetGroupsForUserID(UserID id) { - local Users_Feature usersFeature; - local array result; + local array emptyResult; - usersFeature = Users_Feature(class'Users_Feature'.static - .GetEnabledInstance()); - if (usersFeature == none) { - return result; + if (usersFeature != none) { + return usersFeature.GetGroupsForUserID(id); } - result = usersFeature.GetGroupsForUserID(id); - usersFeature.FreeSelf(); - return result; + return emptyResult; } /** * Returns names of all groups available for the user. * + * Will only work if `Users_Feature` is active. * In case active config of `Users_Feature` is set up to load user groups * from a database (either local or remote), the returned value is a locally * cached one. This helps us avoid having to query database each time we want @@ -380,22 +665,18 @@ public final function array GetGroupsForUserID(UserID id) */ public final function array GetGroupsForUser(User user) { - local Users_Feature usersFeature; - local array result; + local array emptyResult; - usersFeature = Users_Feature(class'Users_Feature'.static - .GetEnabledInstance()); - if (usersFeature == none) { - return result; + if (usersFeature != none) { + return usersFeature.GetGroupsForUser(user); } - result = usersFeature.GetGroupsForUser(user); - usersFeature.FreeSelf(); - return result; + return emptyResult; } /** * Returns `UserID`s of all users that belong into the group named `groupName`. * + * Will only work if `Users_Feature` is active. * In case active config of `Users_Feature` is set up to load user groups * from a database (either local or remote), the returned value is a locally * cached one. This helps us avoid having to query database each time we want @@ -410,23 +691,19 @@ public final function array GetGroupsForUser(User user) */ public final function array GetGroupMembers(BaseText groupName) { - local Users_Feature usersFeature; - local array result; + local array emptyResult; - usersFeature = Users_Feature(class'Users_Feature'.static - .GetEnabledInstance()); - if (usersFeature == none) { - return result; + if (usersFeature != none) { + return usersFeature.GetGroupMembers(groupName); } - result = usersFeature.GetGroupMembers(groupName); - usersFeature.FreeSelf(); - return result; + return emptyResult; } /** * Checks whether user given by the `UserID` belongs to the group named * `groupName`. * + * Will only work if `Users_Feature` is active. * In case active config of `Users_Feature` is set up to load user groups * from a database (either local or remote), the returned value is a locally * cached one. This helps us avoid having to query database each time we want @@ -441,22 +718,16 @@ public final function array GetGroupMembers(BaseText groupName) */ public final function bool IsUserIDInGroup(UserID id, Text groupName) { - local Users_Feature usersFeature; - local bool result; - - usersFeature = Users_Feature(class'Users_Feature'.static - .GetEnabledInstance()); - if (usersFeature == none) { - return result; + if (usersFeature != none) { + return usersFeature.IsUserIDInGroup(id, groupName); } - result = usersFeature.IsUserIDInGroup(id, groupName); - usersFeature.FreeSelf(); - return result; + return false; } /** * Checks whether user belongs to the given group. * + * Will only work if `Users_Feature` is active. * In case active config of `Users_Feature` is set up to load user groups * from a database (either local or remote), the returned value is a locally * cached one. This helps us avoid having to query database each time we want @@ -472,23 +743,17 @@ public final function bool IsUserIDInGroup(UserID id, Text groupName) */ public final function bool IsUserInGroup(User user, Text groupName) { - local Users_Feature usersFeature; - local bool result; - - usersFeature = Users_Feature(class'Users_Feature'.static - .GetEnabledInstance()); - if (usersFeature == none) { - return result; + if (usersFeature != none) { + return usersFeature.IsUserInGroup(user, groupName); } - result = usersFeature.IsUserInGroup(user, groupName); - usersFeature.FreeSelf(); - return result; + return false; } /** * Checks whether user groups' data was already loaded from the source * (either config file or local/remote database). * + * Will only work if `Users_Feature` is active. * Data loaded once is cached and this method returning `true` does not * guarantee that is isn't outdated. Additional, asynchronous queries must be * made to check for that. @@ -497,17 +762,10 @@ public final function bool IsUserInGroup(User user, Text groupName) */ public final function bool IsUserGroupDataLoaded() { - local Users_Feature usersFeature; - local bool result; - - usersFeature = Users_Feature(class'Users_Feature'.static - .GetEnabledInstance()); - if (usersFeature == none) { - return result; + if (usersFeature != none) { + return usersFeature.IsUserGroupDataLoaded(); } - result = usersFeature.IsUserGroupDataLoaded(); - usersFeature.FreeSelf(); - return result; + return false; } defaultproperties diff --git a/sources/Users/Users_Feature.uc b/sources/Users/Users_Feature.uc index d05ec3d..46b9ddb 100644 --- a/sources/Users/Users_Feature.uc +++ b/sources/Users/Users_Feature.uc @@ -32,6 +32,16 @@ var private array loadedUserGroups; // a set data structure (has user id as keys and always `none` as a value). var private HashTable loadedGroupToUsersMap; +protected function OnEnabled() +{ + _.users._reloadFeature(); +} + +protected function OnDisabled() +{ + _.users._reloadFeature(); +} + protected function SwapConfig(FeatureConfig config) { local Users newConfig; @@ -180,8 +190,124 @@ public final function array GetAvailableGroups() return result; } +/** + * Adds a new user group. + * + * In case this feature is configured to load user groups from a database + * (either local or remote), the returned value is a locally cached one. + * This helps us avoid having to query database each time we want to check + * something about user groups, but it also means we might have an outdated + * information. + * Changes will always persist for the duration of the match, but writing + * them into the (non-config) source might fail, leading to changes being reset + * after the level switch. For non-database (config) sources changes will + * always be saved. + * + * @param groupName Name of the group to add. Case-insensitive. + * @return `true` if group was added and `false` otherwise (including if it + * already existed). + */ +public final function bool AddGroup(BaseText groupName) +{ + local bool groupExists; + local Text lowerCaseGroupName; + local HashTable newUserSet; + + if (groupName == none) { + return false; + } + lowerCaseGroupName = groupName.LowerCopy(); + groupExists = loadedGroupToUsersMap.HasKey(lowerCaseGroupName); + if (!groupExists) + { + lowerCaseGroupName.FreeSelf(); + return false; + } + loadedUserGroups[loadedUserGroups.length] = lowerCaseGroupName; + // Try loading local `UserGroup`? + newUserSet = _.collections.EmptyHashTable(); + loadedGroupToUsersMap.SetItem(lowerCaseGroupName, newUserSet); + newUserSet.FreeSelf(); + return true; +} + +/** + * Removes existing user group. + * + * In case this feature is configured to load user groups from a database + * (either local or remote), the returned value is a locally cached one. + * This helps us avoid having to query database each time we want to check + * something about user groups, but it also means we might have an outdated + * information. + * Changes will always persist for the duration of the match, but writing + * them into the (non-config) source might fail, leading to changes being reset + * after the level switch. For non-database (config) sources changes will + * always be saved. + * + * @param groupName Name of the group to remove. Case-insensitive. + * @return `true` if group was removed and `false` otherwise (including if it + * didn't exist in the first place). + */ +public final function bool RemoveGroup(BaseText groupName) +{ + local int i; + local bool groupExists; + local Text lowerCaseGroupName; + + if (groupName == none) { + return false; + } + lowerCaseGroupName = groupName.LowerCopy(); + groupExists = loadedGroupToUsersMap.HasKey(lowerCaseGroupName); + if (!groupExists) + { + lowerCaseGroupName.FreeSelf(); + return false; + } + for (i = 0; i < loadedUserGroups.length; i += 1) + { + if (lowercaseGroupName.Compare(loadedUserGroups[i])) + { + loadedUserGroups.Remove(i, 1); + break; + } + } + // Try loading local `UserGroup`? + loadedGroupToUsersMap.RemoveItem(lowerCaseGroupName); + lowerCaseGroupName.FreeSelf(); + return true; +} + +/** + * Checks whether group with specified name exists. + * + * In case this feature is configured to load user groups from a database + * (either local or remote), the returned value is a locally cached one. + * This helps us avoid having to query database each time we want to check + * something about user groups, but it also means we might have an outdated + * information. + * + * @param groupName Name of the group to check existence of. + * Case-insensitive. + * @return `true` if group exists and `false` otherwise. + */ +public final function bool IsGroupExisting(BaseText groupName) +{ + local bool result; + local Text lowerCaseGroupName; + + if (groupName == none) { + return false; + } + lowerCaseGroupName = groupName.LowerCopy(); + result = loadedGroupToUsersMap.HasKey(lowerCaseGroupName); + lowerCaseGroupName.FreeSelf(); + return result; +} + /** * Adds user with the given SteamID into the specified group. + * * In case this feature is configured to load user groups from a database * (either local or remote), changes are guaranteed to be made to the locally * cached copy that will persist for the duration of the game. Method will also @@ -189,7 +315,7 @@ public final function array GetAvailableGroups() * meaning that changes might not be saved for later matches. * * @param steamID SteamID of the user to add to the group. - * @param groupName Name of the group to add user to. + * @param groupName Name of the group to add user to. Case-insensitive. * @return `true` if user was added to the group (including if her was already * added to it) and `false` in any other case. */ @@ -206,6 +332,7 @@ public final function bool AddSteamIDToGroup( lowercaseGroupName = groupName.LowerCopy(); groupUsers = loadedGroupToUsersMap.GetHashTable(lowercaseGroupName); lowercaseGroupName.FreeSelf(); + // No specified group? Nothing to add! if (groupUsers == none) { return false; } @@ -216,6 +343,7 @@ public final function bool AddSteamIDToGroup( /** * Adds user with the given SteamID into the specified group. + * * In case this feature is configured to load user groups from a database * (either local or remote), changes are guaranteed to be made to the locally * cached copy that will persist for the duration of the game. Method will also @@ -223,7 +351,7 @@ public final function bool AddSteamIDToGroup( * meaning that changes might not be saved for later matches. * * @param steamID SteamID of the user to add to the group. - * @param groupName Name of the group to add user to. + * @param groupName Name of the group to add user to. Case-insensitive. * @return `true` if user was added to the group (including if her was already * added to it) and `false` in any other case. */ @@ -244,6 +372,7 @@ public final /*unreal*/ function bool AddSteamIDToGroup_S( /** * Adds user (given by the `UserID`) into the specified group. + * * In case this feature is configured to load user groups from a database * (either local or remote), changes are guaranteed to be made to the locally * cached copy that will persist for the duration of the game. Method will also @@ -251,7 +380,7 @@ public final /*unreal*/ function bool AddSteamIDToGroup_S( * meaning that changes might not be saved for later matches. * * @param id `UserID` of the user to add to the group. - * @param groupName Name of the group to add user to. + * @param groupName Name of the group to add user to. Case-insensitive. * @return `true` if user was added to the group (including if her was already * added to it) and `false` in any other case. */ @@ -274,6 +403,7 @@ public final function bool AddUserIDToGroup( /** * Adds given user into the specified group. + * * In case this feature is configured to load user groups from a database * (either local or remote), changes are guaranteed to be made to the locally * cached copy that will persist for the duration of the game. Method will also @@ -281,7 +411,7 @@ public final function bool AddUserIDToGroup( * meaning that changes might not be saved for later matches. * * @param user User to add to the group. - * @param groupName Name of the group to add user to. + * @param groupName Name of the group to add user to. Case-insensitive. * @return `true` if user was added to the group (including if her was already * added to it) and `false` in any other case. */ @@ -301,6 +431,7 @@ public final function bool AddUserToGroup(User user, BaseText groupName) /** * Removes user with the given SteamID from the specified group. + * * In case this feature is configured to load user groups from a database * (either local or remote), changes are guaranteed to be made to the locally * cached copy that will persist for the duration of the game. Method will also @@ -308,7 +439,7 @@ public final function bool AddUserToGroup(User user, BaseText groupName) * meaning that changes might not be saved for later matches. * * @param steamID SteamID of the user to remove to the group. - * @param groupName Name of the group to remove user to. + * @param groupName Name of the group to remove user to. Case-insensitive. * @return `true` if user was removed to the group (including if her was * already removed to it) and `false` in any other case. */ @@ -337,6 +468,7 @@ public final function bool RemoveSteamIDFromGroup( /** * Removes user with the given SteamID from the specified group. + * * In case this feature is configured to load user groups from a database * (either local or remote), changes are guaranteed to be made to the locally * cached copy that will persist for the duration of the game. Method will also @@ -344,7 +476,7 @@ public final function bool RemoveSteamIDFromGroup( * meaning that changes might not be saved for later matches. * * @param steamID SteamID of the user to remove to the group. - * @param groupName Name of the group to remove user to. + * @param groupName Name of the group to remove user to. Case-insensitive. * @return `true` if user was removed to the group (including if her was * already removed to it) and `false` in any other case. */ @@ -365,6 +497,7 @@ public final /*unreal*/ function bool RemoveSteamIDFromGroup_S( /** * Removes user (given by the `UserID`) from the specified group. + * * In case this feature is configured to load user groups from a database * (either local or remote), changes are guaranteed to be made to the locally * cached copy that will persist for the duration of the game. Method will also @@ -372,7 +505,7 @@ public final /*unreal*/ function bool RemoveSteamIDFromGroup_S( * meaning that changes might not be saved for later matches. * * @param id `UserID` of the user to remove to the group. - * @param groupName Name of the group to remove user to. + * @param groupName Name of the group to remove user to. Case-insensitive. * @return `true` if user was removed to the group (including if her was * already removed to it) and `false` in any other case. */ @@ -395,6 +528,7 @@ public final function bool RemoveUserIDFromGroup( /** * Removes user from the specified group. + * * In case this feature is configured to load user groups from a database * (either local or remote), changes are guaranteed to be made to the locally * cached copy that will persist for the duration of the game. Method will also @@ -402,7 +536,7 @@ public final function bool RemoveUserIDFromGroup( * meaning that changes might not be saved for later matches. * * @param user User to remove to the group. - * @param groupName Name of the group to remove user to. + * @param groupName Name of the group to remove user to. Case-insensitive. * @return `true` if user was removed to the group (including if her was * already removed to it) and `false` in any other case. */