1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 16:57:16 +01:00
SqMod/module/Core/Privilege/Unit.hpp

317 lines
15 KiB
C++
Raw Normal View History

#pragma once
// ------------------------------------------------------------------------------------------------
#include "Core/Privilege/Base.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* An individual unit/entity that inherits the privileges of a class/group and can
* change their status without affecting other units and/or their associated class.
* A unit cannot extend it's privileges to other entities.
* Units cost more to query if they differ from their class but save memory in large numbers.
* Each unit must have a unique numerical identifier within their associated manager.
*/
struct PvUnit
{
/* --------------------------------------------------------------------------------------------
* Strong and weak reference types.
*/
typedef std::shared_ptr< PvUnit > Ref;
typedef std::weak_ptr< PvUnit > Ptr;
/* --------------------------------------------------------------------------------------------
* Type of container used to store privilege units.
*/
typedef VecMap< PvIdentity, Ref, PvIdPred > List;
/* --------------------------------------------------------------------------------------------
* User identifier associated with this unit instance. Always unique in the same manager!
*/
const SQInteger mID;
/* --------------------------------------------------------------------------------------------
* Authority level associated with a particular unit.
*/
SQInteger mAuthority;
/* --------------------------------------------------------------------------------------------
* A container with unique privilege status values associated with this unit.
*/
PvStatusList mPrivileges;
/* --------------------------------------------------------------------------------------------
* Dedicated callback for privilege query event.
*/
Function mOnQuery;
/* --------------------------------------------------------------------------------------------
* Dedicated callback for privilege gained event.
*/
Function mOnGained;
/* --------------------------------------------------------------------------------------------
* Dedicated callback for privilege lost event.
*/
Function mOnLost;
/* --------------------------------------------------------------------------------------------
* User tag associated with this instance.
*/
StackStrF mTag;
/* --------------------------------------------------------------------------------------------
* User data associated with this instance.
*/
LightObj mData;
/* --------------------------------------------------------------------------------------------
* Weak pointer to the associated class. Units always have an associated class!
*/
std::weak_ptr< PvClass > mClass;
/* -------------------------------------------------------------------------------------------
* Default constructor.
*/
PvUnit(SQInteger id, std::weak_ptr< PvClass > cls)
: mID(id)
, mAuthority(0)
, mPrivileges()
, mOnQuery(), mOnGained(), mOnLost()
, mTag(), mData()
, mClass(std::move(cls))
{
}
/* -------------------------------------------------------------------------------------------
* Default constructor.
*/
PvUnit(SQInteger id, StackStrF && tag, std::weak_ptr< PvClass > cls)
: mID(id)
, mAuthority(0)
, mPrivileges()
, mOnQuery(), mOnGained(), mOnLost()
, mTag(std::move(tag)), mData()
, mClass(std::move(cls))
{
}
/* -------------------------------------------------------------------------------------------
* Copy constructor (disabled).
*/
PvUnit(const PvUnit & o) = delete;
/* -------------------------------------------------------------------------------------------
* Move constructor (disabled).
*/
PvUnit(PvUnit && o) = delete;
/* -------------------------------------------------------------------------------------------
* Destructor.
*/
~PvUnit() = default;
/* -------------------------------------------------------------------------------------------
* Copy assignment operator (disabled).
*/
PvUnit & operator = (const PvUnit & o) = delete;
/* -------------------------------------------------------------------------------------------
* Move assignment operator (disabled).
*/
PvUnit & operator = (PvUnit && o) = delete;
/* --------------------------------------------------------------------------------------------
* Modify the associated user tag.
*/
void SetTag(StackStrF & tag);
/* --------------------------------------------------------------------------------------------
* Release all script resources.
*/
void Release();
/* --------------------------------------------------------------------------------------------
* Make sure the referenced parent class is valid.
*/
void ValidateClass() const
{
if (mClass.expired())
{
STHROWF("Unit ({} : {}) has invalid class reference", mID, mTag.mPtr);
}
}
/* --------------------------------------------------------------------------------------------
* Make sure the referenced parent class is valid and return a reference to it.
*/
SQMOD_NODISCARD PvClass & ValidClass() const
{
ValidateClass();
// Acquire a reference and return it
return *(mClass.lock().get());
}
/* --------------------------------------------------------------------------------------------
* Make sure the referenced manger is valid.
*/
void ValidateManager() const;
/* --------------------------------------------------------------------------------------------
* Make sure the referenced manger is valid and return a reference to it.
*/
SQMOD_NODISCARD PvManager & ValidManager() const;
/* --------------------------------------------------------------------------------------------
* Find out the callback that must be invoked to handle query events for a certain entry.
*/
SQMOD_NODISCARD const Function & GetOnQuery(SQInteger id) const;
/* --------------------------------------------------------------------------------------------
* Find out the callback that must be invoked to handle gained events for a certain entry.
*/
SQMOD_NODISCARD const Function & GetOnGained(SQInteger id) const;
/* --------------------------------------------------------------------------------------------
* Find out the callback that must be invoked to handle lost events for a certain entry.
*/
SQMOD_NODISCARD const Function & GetOnLost(SQInteger id) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the current value of an entry for this particular unit.
*/
SQMOD_NODISCARD SQInteger GetEntryValue(SQInteger id) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the inherited value of an entry for this particular unit.
*/
SQMOD_NODISCARD SQInteger GetInheritedEntryValue(SQInteger id) const;
/* --------------------------------------------------------------------------------------------
* Perform the actions necessary to handle a privilege gain event.
*/
void DoGained(SQInteger id, SQInteger value) const;
/* --------------------------------------------------------------------------------------------
* Perform the actions necessary to handle a privilege lost event.
*/
void DoLost(SQInteger id, SQInteger value) const;
/* --------------------------------------------------------------------------------------------
* Perform the actions necessary to handle a privilege change event.
*/
void DoChanged(SQInteger id, bool status, SQInteger value) const;
/* --------------------------------------------------------------------------------------------
* Assign a status value. Does not care if a parent (class or global) has the same status.
* Later if the parent changes this status, we will keep having this status value.
*/
2021-02-05 13:06:13 +01:00
void AssignPrivilege(SQInteger id, SQInteger value);
/* --------------------------------------------------------------------------------------------
* Remove a status value. If the specified status value is not assigned, nothing happens.
*/
2021-02-05 13:06:13 +01:00
void RemovePrivilege(SQInteger id);
/* --------------------------------------------------------------------------------------------
* Assign a status value. If a parent (class or global) has the same value, nothing changes.
* Same as AssignStatus but the status will not be enforced if we have it (inherited or not).
*/
2021-02-05 13:06:13 +01:00
void ModifyPrivilege(SQInteger id, SQInteger value);
/* --------------------------------------------------------------------------------------------
* See AssignPrivilege().
*/
void AssignPrivilege(StackStrF & tag, SQInteger value);
/* --------------------------------------------------------------------------------------------
* See RemovePrivilege().
*/
void RemovePrivilege(StackStrF & tag);
/* --------------------------------------------------------------------------------------------
* See ModifyPrivilege().
*/
void ModifyPrivilege(StackStrF & tag, SQInteger value);
2021-02-05 13:19:15 +01:00
/* --------------------------------------------------------------------------------------------
* Remove all status values. Basically it reverts to the current class privileges.
*/
void RemoveAllPrivileges();
/* --------------------------------------------------------------------------------------------
* Assign a new class.
*/
void AssignClass(const std::shared_ptr< PvClass > & cls);
/* --------------------------------------------------------------------------------------------
* Check if this unit has a certain privilege.
*/
2021-02-05 14:56:24 +01:00
SQMOD_NODISCARD bool Can(SQInteger id, SQInteger req) const;
2021-02-05 14:42:27 +01:00
/* --------------------------------------------------------------------------------------------
* Invoke a given callback with every owned entry identifier.
*/
2021-02-05 15:03:04 +01:00
void EachEntryID(Object & ctx, Function & func) const;
};
/* ------------------------------------------------------------------------------------------------
* Privilege unit wrapper. Mostly calls functions of the actual implementation.
* Used to avoid having to involve hard script references that can persist.
* Breaks away from usual formatting.
*/
struct SqPvUnit
{
PvUnit::Ptr mI;
// --------------------------------------------------------------------------------------------
explicit SqPvUnit(PvUnit::Ptr i) : mI(std::move(i)) { } // NOLINT(modernize-pass-by-value)
explicit SqPvUnit(const PvUnit::Ref & i) : mI(i) { }
SqPvUnit(const SqPvUnit & o) = default;
SqPvUnit(SqPvUnit && o) noexcept = default;
~SqPvUnit() = default;
SqPvUnit & operator = (const SqPvUnit & o) = default;
SqPvUnit & operator = (SqPvUnit && o) noexcept = default;
// --------------------------------------------------------------------------------------------
void Validate() const { if (mI.expired()) STHROWF("Invalid unit reference"); }
SQMOD_NODISCARD PvUnit & Valid() const { Validate(); return *(mI.lock().get()); }
// --------------------------------------------------------------------------------------------
void ValidateCls() const { Validate(); if (mI.lock()->mClass.expired()) STHROWF("Invalid class reference"); }
SQMOD_NODISCARD PvClass & ValidCls() const { ValidateCls(); return *(mI.lock()->mClass.lock().get()); }
// --------------------------------------------------------------------------------------------
SQMOD_NODISCARD SQInteger GetID() const { return Valid().mID; }
// --------------------------------------------------------------------------------------------
SQMOD_NODISCARD auto ToString() const { return Valid().mTag.mObj; }
SQMOD_NODISCARD auto GetTag() const { return Valid().mTag.mObj; }
void SetTag(StackStrF & tag) const { Valid().SetTag(tag); }
SQMOD_NODISCARD SqPvUnit & ApplyTag(StackStrF & tag) { SetTag(tag); return *this; }
SQMOD_NODISCARD LightObj & GetData() const { return Valid().mData; }
void SetData(LightObj & data) const { Valid().mData = data; }
// --------------------------------------------------------------------------------------------
void SetOnQuery(Function & func) const { Valid().mOnQuery = std::move(func); }
void SetOnLost(Function & func) const { Valid().mOnLost = std::move(func); }
void SetOnGained(Function & func) const { Valid().mOnGained = std::move(func); }
// --------------------------------------------------------------------------------------------
SQMOD_NODISCARD SQInteger GetAuthority() const { return Valid().mAuthority; }
void SetAuthority(SQInteger a) const { Valid().mAuthority = a; }
// --------------------------------------------------------------------------------------------
SQMOD_NODISCARD LightObj GetClass() const;
void SetClass(const SqPvClass & cls) const;
// --------------------------------------------------------------------------------------------
SQMOD_NODISCARD LightObj GetManager() const;
// --------------------------------------------------------------------------------------------
2021-02-05 14:56:24 +01:00
bool Can(LightObj & obj, SQInteger req) const;
2021-02-05 13:06:13 +01:00
// --------------------------------------------------------------------------------------------
2021-02-05 15:03:04 +01:00
void AssignPrivilegeWithID(SQInteger id, SQInteger value) const { Valid().AssignPrivilege(id, value); }
void AssignPrivilegeWithTag(StackStrF & tag, SQInteger value) const { Valid().AssignPrivilege(tag, value); }
void RemovePrivilegeWithID(SQInteger id) const { Valid().RemovePrivilege(id); }
void RemovePrivilegeWithTag(StackStrF & tag) const { Valid().RemovePrivilege(tag); }
void ModifyPrivilegeWithID(SQInteger id, SQInteger value) const { Valid().ModifyPrivilege(id, value); }
void ModifyPrivilegeWithTag(StackStrF & tag, SQInteger value) const { Valid().ModifyPrivilege(tag, value); }
void RemoveAllPrivileges() const { Valid().RemoveAllPrivileges(); }
2021-02-05 14:42:27 +01:00
// --------------------------------------------------------------------------------------------
2021-02-05 15:03:04 +01:00
void EachEntryID(Object & ctx, Function & func) const { return Valid().EachEntryID(ctx, func); }
};
} // Namespace:: SqMod