rott/kf_sources/AcediaCore/Classes/ItemCard.uc
2026-07-14 20:27:09 +07:00

177 lines
6.7 KiB
Ucode

/**
* Author: dkanus
* Home repo: https://www.insultplayers.ru/git/AcediaFramework/AcediaCore
* License: GPL
* Copyright 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 <https://www.gnu.org/licenses/>.
*/
class ItemCard extends AcediaObject;
//! Utility class designed for storing either class of an object
//! (possibly also a specific instance) along with authorization information:
//! which user groups are allowed to use stored entity and with what level of
//! permissions (defined by the name of a config with permissions).
//!
//! [`ItemCard`] has to be initialized with either [`InitializeWithClass()`] or
//! [`InitializeWithInstance()`] before it can be used.
/// Class of object that this card describes.
var private class<AcediaObject> storedClass;
/// Instance of an object (can also *optionally* be stored in this card)
var private AcediaObject storedInstance;
/// This [`HashTable`] maps authorized groups to their respective config names.
///
/// Each key represents an authorized group, and its corresponding value
/// indicates the associated config name. If a key has a value of `none`,
/// the default config (named "default") should be used for that group.
var private HashTable groupToConfig;
var LoggerAPI.Definition errGroupAlreadyHasConfig;
protected function Finalizer() {
_.memory.Free2(storedInstance, groupToConfig);
storedInstance = none;
storedClass = none;
groupToConfig = none;
}
/// Initializes the caller [`ItemCard`] object with class to be stored.
///
/// Initialization can only be done once: once method returned `true`,
/// all future calls will fail.
///
/// Returns `false` if caller was already initialized or `none` is provided as
/// an argument. Otherwise succeeds and returns `true`.
public function bool InitializeWithClass(class<AcediaObject> toStore) {
if (storedClass != none) return false;
if (toStore == none) return false;
storedClass = toStore;
groupToConfig = _.collections.EmptyHashTable();
return true;
}
/// Initializes the caller [`ItemCard`] object with an object to be stored.
///
/// Initialization can only be done once: once method returned `true`,
/// all future calls will fail.
///
/// Returns `false` caller was already initialized or `none` is provided as
/// an argument. Otherwise succeeds and returns `true`.
public function bool InitializeWithInstance(AcediaObject toStore) {
if (storedClass != none) return false;
if (toStore == none) return false;
storedClass = toStore.class;
storedInstance = toStore;
storedInstance.NewRef();
groupToConfig = _.collections.EmptyHashTable();
return true;
}
/// Authorizes a new group to use the this card's item.
///
/// This function allows to specify the config name for a particular user group.
/// If this config name is skipped (specified as `none`), then "default" will be
/// used instead.
///
/// Function will return `true` if group was successfully authorized and
/// `false` otherwise (either group already authorized or caller [`ItemCard`]
/// isn't initialized).
///
/// # Errors
///
/// If specified group was already authorized to use card's item, then it
/// will log an error message about it.
public function bool AuthorizeGroupWithConfig(BaseText groupName, optional BaseText configName) {
local Text itemKey;
local Text storedConfigName;
if (storedClass == none) return false;
if (groupToConfig == none) return false;
if (groupName == none) return false;
if (groupName.IsEmpty()) return false;
/// Make group name immutable and have its characters have a uniform case to
/// be usable as case-insensitive keys for [`HashTable`].
itemKey = groupName.LowerCopy();
storedConfigName = groupToConfig.GetText(itemKey);
if (storedConfigName != none) {
_.logger.Auto(errGroupAlreadyHasConfig)
.ArgClass(storedClass)
.Arg(groupName.Copy())
.Arg(storedConfigName)
.Arg(configName.Copy());
_.memory.Free(itemKey);
return false;
}
// We don't actually record "default" value at this point, instead opting
// to return "default" in getter functions in case stored `configName`
// is `none`.
groupToConfig.SetItem(itemKey, configName);
_.memory.Free(itemKey);
return true;
}
/// Returns item instance for the caller [`ItemCard`].
///
/// Returns `none` iff this card wasn't initialized with an instance.
public function AcediaObject GetItem() {
if (storedInstance != none) {
storedInstance.NewRef();
}
return storedInstance;
}
/// Returns item class for the caller [`ItemCard`].
///
/// Returns `none` iff this card wasn't initialized.
public function class<AcediaObject> GetItemClass() {
return storedClass;
}
/// Returns the name of config that was authorized for the specified group.
///
/// Returns `none` if group wasn't authorized, otherwise guaranteed to
/// return non-`none` and non-empty `Text` value.
public function Text GetConfigNameForGroup(BaseText groupName) {
local Text groupNameAsKey, result;
if (storedClass == none) return none;
if (groupToConfig == none) return none;
if (groupName == none) return none;
/// Make group name immutable and have its characters a uniform case to
/// be usable as case-insensitive keys for [`HashTable`]
groupNameAsKey = groupName.LowerCopy();
if (groupToConfig.HasKey(groupNameAsKey)) {
result = groupToConfig.GetText(groupNameAsKey);
if (result == none) {
// If we do have specified group recorded as a key, then we must
// return non-`none` config name, defaulting to "default" value
// if none was provided
result = P("default").Copy();
}
}
_.memory.Free(groupNameAsKey);
return result;
}
defaultproperties {
errGroupAlreadyHasConfig = (l=LOG_Error,m="Item `%1` is already added to group '%2' with config '%3'. Attempt to add it with config '%4' is ignored.")
}