/** * Object that is supposed to store a persistent data about the * certain player. That is data that will be remembered even after player * reconnects or server changes map/restarts. * Copyright 2020-2023 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. * * Acedia is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License, or * (at your option) any later version. * * Acedia is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Acedia. If not, see . */ class User extends AcediaObject; // Unique identifier for which this `User` stores it's data var private UserID id; // A numeric "key" assigned to this user for a session that can serve as // an easy reference in console commands var private int key; var private HashTable sessionData; var private int persistentDataLifeVersion; var private PersistentDataManager persistentData; protected function Finalizer() { if (id != none) { id.FreeSelf(); } id = none; } private final function UpdatePersistentDataManager() { local Users_Feature feature; if ( persistentData != none && persistentData.GetLifeVersion() != persistentDataLifeVersion) { persistentData = none; } if (persistentData == none) { feature = Users_Feature(class'Users_Feature'.static.GetEnabledInstance()); if (feature != none) { persistentData = feature.BorrowPersistentDataManager(); } if (persistentData != none) { persistentDataLifeVersion = persistentData.GetLifeVersion(); } _.memory.Free(feature); } } /** * Initializes caller `User` with id and it's session key. * * Initialization should (and can) only be done once. * Before a `Initialize()` call, any other method calls on such `User` * must be considerate to have undefined behavior. * DO NOT CALL THIS METHOD MANUALLY. */ public final function Initialize(UserID initID, int initKey) { id = initID; key = initKey; if (initID != none) { initID.NewRef(); } } /** * Return id for which caller `User` stores data. * * @return `UserID` that caller `User` was initialized with. */ public final function UserID GetID() { if (id != none) { id.NewRef(); } return id; } /** * Return session key of the caller `User`. * * @return Session key of the caller `User`. */ public final function int GetKey() { return key; } /** * Returns a reference to user's session data for a given group. * * Guaranteed to not be `none`. */ public final function HashTable GetSessionData(Text groupName) { local HashTable groupData; if (sessionData == none) { sessionData = _.collections.EmptyHashTable(); } groupData = sessionData.GetHashTable(groupName); if (groupData == none) { groupData = _.collections.EmptyHashTable(); sessionData.SetItem(groupName, groupData); } return groupData; } /** * Returns persistent data for the caller user. Data is specified by the its * name along with the name of the data group it is stored in. * * @param groupName Name of the group to get data from. Cannot be `none`. * @param dataName Name of the data to return. If `none` value is provided, * all the data in specified group will be returned. * @return Requested data, `none` in case of failure (i.e. data is missing). */ public final function AcediaObject GetPersistentData( BaseText groupName, BaseText dataName) { local AcediaObject result; local UserID myID; UpdatePersistentDataManager(); if (persistentData == none) { return none; } myID = GetID(); result = persistentData.GetPersistentData(myID, groupname, dataName); _.memory.Free(myID); return result; } /** * Changes persistent data for the caller user. Data to change is specified by * the its name along with the name of the data group it is stored in. * * @param groupName Name of the group to get data from. Cannot be `none`. * @param dataName Name of the data to return. Cannot be `none`. * @param data New data to record. * @return `true` in case operation was successful and `false` otherwise. */ public final function bool SetPersistentData( BaseText groupName, BaseText dataName, AcediaObject data) { local bool result; local UserID myID; UpdatePersistentDataManager(); if (persistentData == none) { return false; } myID = GetID(); result = persistentData .WritePersistentData(myID, groupname, dataName, data); _.memory.Free(myID); return result; } public function bool IsEqual(Object other) { local User otherUser; if (id == none) return false; otherUser = User(other); if (otherUser == none) return false; if (otherUser.id == none) return false; return id.IsEqual(otherUser.id); } protected function int CalculateHashCode() { // If `id` is `none`, then caller `User` shouldn't be used at all return id.GetHashCode(); } defaultproperties { }