1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00
SqMod/module/Core/Privilege/Class.hpp
2021-02-05 15:56:24 +02:00

377 lines
17 KiB
C++

#pragma once
// ------------------------------------------------------------------------------------------------
#include "Core/Privilege/Unit.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* An individual class/group that can optionally inherit the privileges of another and can
* change their status to affect their children but not their parent class.
* A class can extend it's privileges to units and/or other classes.
* These cost less to query but use more memory because they're fewer and they preallocate it.
* Each class must have a unique numerical identifier within their associated manager.
*/
struct PvClass
{
/* --------------------------------------------------------------------------------------------
* Strong and weak reference types.
*/
typedef std::shared_ptr< PvClass > Ref;
typedef std::weak_ptr< PvClass > Ptr;
/* --------------------------------------------------------------------------------------------
* Type of container used to store privilege classes.
*/
typedef VecMap< PvIdentity, Ref, PvIdPred > List;
/* --------------------------------------------------------------------------------------------
* User identifier associated with this class instance. Always unique in the same manager!
*/
const SQInteger mID;
/* --------------------------------------------------------------------------------------------
* The parent class from which we are inheriting privileges, if any.
*/
Ptr mParent;
/* --------------------------------------------------------------------------------------------
* A container with unique privilege status values associated with this class.
*/
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;
/* --------------------------------------------------------------------------------------------
* Container that stores all the associated units.
*/
PvUnit::List mUnits;
/* --------------------------------------------------------------------------------------------
* User tag associated with this instance.
*/
StackStrF mTag;
/* --------------------------------------------------------------------------------------------
* User data associated with this instance.
*/
LightObj mData;
/* --------------------------------------------------------------------------------------------
* Pointer to the associated manager. Should always be present.
*
*/
PvManager * mManager;
/* -------------------------------------------------------------------------------------------
* Default constructor.
*/
PvClass(SQInteger id, PvManager * mgr)
: mID(id)
, mParent()
, mPrivileges()
, mOnQuery(), mOnGained(), mOnLost()
, mUnits()
, mTag(), mData()
, mManager(mgr)
{
}
/* -------------------------------------------------------------------------------------------
* Default constructor.
*/
PvClass(SQInteger id, StackStrF && tag, PvManager * mgr)
: mID(id)
, mParent()
, mPrivileges()
, mOnQuery(), mOnGained(), mOnLost()
, mUnits()
, mTag(std::move(tag)), mData()
, mManager(mgr)
{
}
/* -------------------------------------------------------------------------------------------
* Copy constructor (disabled).
*/
PvClass(const PvClass & o) = delete;
/* -------------------------------------------------------------------------------------------
* Move constructor (disabled).
*/
PvClass(PvClass && o) = delete;
/* -------------------------------------------------------------------------------------------
* Destructor.
*/
~PvClass() = default;
/* -------------------------------------------------------------------------------------------
* Copy assignment operator (disabled).
*/
PvClass & operator = (const PvClass & o) = delete;
/* -------------------------------------------------------------------------------------------
* Move assignment operator (disabled).
*/
PvClass & operator = (PvClass && o) = delete;
/* --------------------------------------------------------------------------------------------
* Update the hash of the specified unit.
*/
void UpdateUnitHash(SQInteger id, size_t hash)
{
auto itr = mUnits.find(PvIdentity(id));
// Only update if it exists
if (itr != mUnits.end())
{
itr->first.mHash = hash;
}
}
/* --------------------------------------------------------------------------------------------
* Modify the associated user tag.
*/
void SetTag(StackStrF & tag);
/* --------------------------------------------------------------------------------------------
* Release all script resources. Recursively forward request.
*/
void Release();
/* --------------------------------------------------------------------------------------------
* Make sure the referenced parent class is valid.
*/
void ValidateParent() const
{
if (mParent.expired())
{
STHROWF("Class ({} : {}) has invalid parent class reference", mID, mTag.mPtr);
}
}
/* --------------------------------------------------------------------------------------------
* Make sure the referenced parent class is valid and return a reference to it.
*/
SQMOD_NODISCARD PvClass & ValidParent() const
{
ValidateParent();
// Acquire a reference and return it
return *(mParent.lock().get());
}
/* --------------------------------------------------------------------------------------------
* Make sure the referenced manager is valid.
*/
void ValidateManager() const
{
if (!mManager)
{
STHROWF("Class ({} : {}) has invalid manager reference", mID, mTag.mPtr);
}
}
/* --------------------------------------------------------------------------------------------
* 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 class.
*/
SQMOD_NODISCARD SQInteger GetEntryValue(SQInteger id) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the inherited value of an entry for this particular class.
*/
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.
*/
void AssignPrivilege(SQInteger id, SQInteger value);
/* --------------------------------------------------------------------------------------------
* Remove a status value. If the specified status value is not assigned, nothing happens.
*/
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).
*/
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);
/* --------------------------------------------------------------------------------------------
* Remove all status values. Basically it reverts to the parent class privileges.
*/
void RemoveAllPrivileges();
/* --------------------------------------------------------------------------------------------
* Change the parent class.
*/
void AssignParent(const Ref & parent);
/* --------------------------------------------------------------------------------------------
* Check if this class has a certain privilege.
*/
SQMOD_NODISCARD bool Can(SQInteger id, SQInteger req) const;
/* --------------------------------------------------------------------------------------------
* See if a unit with a certain identifier inherits this class.
*/
SQMOD_NODISCARD LightObj GetUnitWithID(SQInteger id);
/* --------------------------------------------------------------------------------------------
* See if a unit with a certain tag inherits this class.
*/
SQMOD_NODISCARD LightObj GetUnitWithTag(StackStrF & tag);
/* --------------------------------------------------------------------------------------------
* See if a unit with a certain identifier inherits this class.
*/
bool HaveUnitWithID(SQInteger id);
/* --------------------------------------------------------------------------------------------
* See if a unit with a certain tag inherits this class.
*/
bool HaveUnitWithTag(StackStrF & tag);
/* --------------------------------------------------------------------------------------------
* Invoke a given callback with every owned entry identifier.
*/
void EachEntryID(Object & ctx, Function & func);
/* --------------------------------------------------------------------------------------------
* Invoke a given callback with every parented unit identifier.
*/
void EachUnitID(Object & ctx, Function & func);
};
/* ------------------------------------------------------------------------------------------------
* Privilege class 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 SqPvClass
{
PvClass::Ptr mI;
// --------------------------------------------------------------------------------------------
explicit SqPvClass(PvClass::Ptr i) : mI(std::move(i)) { } // NOLINT(modernize-pass-by-value)
explicit SqPvClass(const PvClass::Ref & i) : mI(i) { }
SqPvClass(const SqPvClass & o) = default;
SqPvClass(SqPvClass && o) noexcept = default;
~SqPvClass() = default;
SqPvClass & operator = (const SqPvClass & o) = default;
SqPvClass & operator = (SqPvClass && o) noexcept = default;
// --------------------------------------------------------------------------------------------
void Validate() const { if (mI.expired()) STHROWF("Invalid unit reference"); }
SQMOD_NODISCARD PvClass & Valid() const { Validate(); return *(mI.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 SqPvClass & 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 LightObj GetManager() const { return LightObj(Valid().mManager); }
// --------------------------------------------------------------------------------------------
SQMOD_NODISCARD LightObj GetParent() const
{
return LightObj(SqTypeIdentity< SqPvClass >{}, SqVM(), Valid().mParent);
}
void SetParent(const SqPvClass & cls) const
{
Validate();
cls.Validate();
mI.lock()->AssignParent(cls.mI.lock());
}
// --------------------------------------------------------------------------------------------
bool Can(LightObj & obj, SQInteger req) const;
// --------------------------------------------------------------------------------------------
void AssignPrivilegeWithID(SQInteger id, SQInteger value) { Valid().AssignPrivilege(id, value); }
void AssignPrivilegeWithTag(StackStrF & tag, SQInteger value) { Valid().AssignPrivilege(tag, value); }
void RemovePrivilegeWithID(SQInteger id) { Valid().RemovePrivilege(id); }
void RemovePrivilegeWithTag(StackStrF & tag) { Valid().RemovePrivilege(tag); }
void ModifyPrivilegeWithID(SQInteger id, SQInteger value) { Valid().ModifyPrivilege(id, value); }
void ModifyPrivilegeWithTag(StackStrF & tag, SQInteger value) { Valid().ModifyPrivilege(tag, value); }
void RemoveAllPrivileges() { Valid().RemoveAllPrivileges(); }
// --------------------------------------------------------------------------------------------
SQMOD_NODISCARD LightObj GetUnitWithID(SQInteger id) const { return Valid().GetUnitWithID(id); }
SQMOD_NODISCARD LightObj GetUnitWithTag(StackStrF & tag) const { return Valid().GetUnitWithTag(tag); }
SQMOD_NODISCARD bool HaveUnitWithID(SQInteger id) const { return Valid().HaveUnitWithID(id); }
SQMOD_NODISCARD bool HaveUnitWithTag(StackStrF & tag) const { return Valid().HaveUnitWithTag(tag); }
// --------------------------------------------------------------------------------------------
void EachEntryID(Object & ctx, Function & func) { return Valid().EachEntryID(ctx, func); }
void EachUnitID(Object & ctx, Function & func) { return Valid().EachUnitID(ctx, func); }
};
} // Namespace:: SqMod