initial commit; cv 0.0.3
This commit is contained in:
123
Api/Pal/PalUtility.hpp
Normal file
123
Api/Pal/PalUtility.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <Reflection/UnrealObjectRef.hpp>
|
||||
|
||||
#include <Api/UnrealWrapper.hpp>
|
||||
#include "PalDatabaseCharacterParameter.hpp"
|
||||
|
||||
namespace PalUIExtension::Api::Pal
|
||||
{
|
||||
|
||||
class PalUtility : public UnrealWrapper
|
||||
{
|
||||
public:
|
||||
static auto ClassPath() -> const TCHAR* { return STR("/Script/Pal.PalUtility"); }
|
||||
static auto CDOPath() -> const TCHAR* { return STR("/Script/Pal.Default__PalUtility"); }
|
||||
static auto DebugTag() -> const TCHAR* { return STR("PalUtility"); }
|
||||
|
||||
static auto Instance() -> PalUtility&
|
||||
{
|
||||
static PalUtility Singleton{};
|
||||
return Singleton;
|
||||
}
|
||||
|
||||
// ---- static getters -----------------------------------------
|
||||
//
|
||||
// Add more here as you need them -- see the class comment for
|
||||
// the one-line shape.
|
||||
|
||||
auto GetDatabaseCharacterParameter(UObject* WorldContextObject) -> PalDatabaseCharacterParameter
|
||||
{
|
||||
return GetSingleton<PalDatabaseCharacterParameter>(
|
||||
STR("GetDatabaseCharacterParameter"), WorldContextObject);
|
||||
}
|
||||
|
||||
|
||||
auto ZukanIndexFor(FName CharacterId, UObject* WorldContextObject) -> std::optional<int32>
|
||||
{
|
||||
const uint64_t Key = NameKey(CharacterId);
|
||||
|
||||
if (auto It = s_zukan_cache.find(Key); It != s_zukan_cache.end())
|
||||
{
|
||||
if (It->second == kNoZukanEntry) return std::nullopt;
|
||||
return It->second;
|
||||
}
|
||||
|
||||
PalDatabaseCharacterParameter DB = GetDatabaseCharacterParameter(WorldContextObject);
|
||||
if (!DB)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto Index = DB.GetZukanIndexResolved(CharacterId);
|
||||
s_zukan_cache.emplace(Key, Index.value_or(kNoZukanEntry));
|
||||
return Index;
|
||||
}
|
||||
|
||||
static auto ClearZukanCache() -> void { s_zukan_cache.clear(); }
|
||||
|
||||
auto NocturnalFor(FName CharacterId, UObject* WorldContextObject) -> std::optional<bool>
|
||||
{
|
||||
const uint64_t Key = NameKey(CharacterId);
|
||||
|
||||
if (auto It = s_nocturnal_cache.find(Key); It != s_nocturnal_cache.end())
|
||||
{
|
||||
return It->second != 0;
|
||||
}
|
||||
|
||||
PalDatabaseCharacterParameter DB = GetDatabaseCharacterParameter(WorldContextObject);
|
||||
if (!DB) return std::nullopt;
|
||||
|
||||
const FName RowName = PalDatabaseCharacterParameter::ResolveBaseRowName(CharacterId);
|
||||
|
||||
auto Nocturnal = DB.GetNocturnal(RowName);
|
||||
if (!Nocturnal.has_value()) return std::nullopt;
|
||||
|
||||
s_nocturnal_cache.emplace(Key, *Nocturnal ? uint8_t{ 1 } : uint8_t{ 0 });
|
||||
return Nocturnal;
|
||||
}
|
||||
|
||||
static auto ClearNocturnalCache() -> void { s_nocturnal_cache.clear(); }
|
||||
|
||||
private:
|
||||
PalUtility() : UnrealWrapper(ResolveCDO(), ClassOf<PalUtility>(), DebugTag()) {}
|
||||
|
||||
static constexpr int32 kNoZukanEntry = -1;
|
||||
static inline std::unordered_map<uint64_t, int32> s_zukan_cache{};
|
||||
|
||||
static inline std::unordered_map<uint64_t, uint8_t> s_nocturnal_cache{};
|
||||
|
||||
static auto NameKey(FName N) -> uint64_t
|
||||
{
|
||||
return (static_cast<uint64_t>(N.GetComparisonIndex().ToUnstableInt()) << 32)
|
||||
| static_cast<uint64_t>(static_cast<uint32_t>(N.GetNumber()));
|
||||
}
|
||||
|
||||
PalUtility(const PalUtility&) = delete;
|
||||
auto operator=(const PalUtility&) -> PalUtility & = delete;
|
||||
|
||||
static auto ResolveCDO() -> UObject*
|
||||
{
|
||||
static Reflection::UnrealObjectRef Ref{ CDOPath(), DebugTag() };
|
||||
return Ref.Get();
|
||||
}
|
||||
|
||||
auto CallStaticObjectGetter(const TCHAR* FunctionName, UObject* WorldContextObject) -> UObject*
|
||||
{
|
||||
struct P { UObject* WorldContextObject; UObject* ReturnValue; } p{ WorldContextObject, nullptr };
|
||||
auto Result = CallForReturn(FunctionName, p, &P::ReturnValue);
|
||||
return (Result && *Result) ? *Result : nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto GetSingleton(const TCHAR* FunctionName, UObject* WorldContextObject) -> T
|
||||
{
|
||||
UObject* Obj = CallStaticObjectGetter(FunctionName, WorldContextObject);
|
||||
return Obj ? T{ Obj } : T{};
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user