mirror of
https://github.com/Jous99/F4MP.git
synced 2026-01-13 00:40:53 +01:00
354 lines
7.2 KiB
C++
354 lines
7.2 KiB
C++
#pragma once
|
|
|
|
#include <Games/Memory.h>
|
|
|
|
template <class T> struct GameArray
|
|
{
|
|
T* data;
|
|
alignas(sizeof(void*)) uint32_t capacity; // Might be size_t
|
|
alignas(sizeof(void*)) uint32_t length; // Might be size_t
|
|
|
|
GameArray()
|
|
: data{nullptr}
|
|
, capacity{}
|
|
, length{0}
|
|
{
|
|
}
|
|
~GameArray() = default;
|
|
|
|
T& operator[](uint32_t aIndex) { return data[aIndex]; }
|
|
const T& operator[](uint32_t aIndex) const { return data[aIndex]; }
|
|
|
|
void Resize(size_t aLength) noexcept;
|
|
|
|
// Range for loop compatibility
|
|
struct Iterator
|
|
{
|
|
Iterator(T* apEntry)
|
|
: m_pEntry(apEntry)
|
|
{
|
|
}
|
|
Iterator operator++()
|
|
{
|
|
++m_pEntry;
|
|
return *this;
|
|
}
|
|
bool operator!=(const Iterator& acRhs) const { return m_pEntry != acRhs.m_pEntry; }
|
|
const T& operator*() const { return *m_pEntry; }
|
|
|
|
private:
|
|
T* m_pEntry;
|
|
};
|
|
|
|
Iterator begin() { return Iterator(&data[0]); }
|
|
|
|
Iterator end() { return Iterator(&data[length]); }
|
|
|
|
struct ConstIterator
|
|
{
|
|
ConstIterator(const T* apEntry)
|
|
: m_pEntry(apEntry)
|
|
{}
|
|
ConstIterator operator++()
|
|
{
|
|
++m_pEntry;
|
|
return *this;
|
|
}
|
|
bool operator!=(const ConstIterator& acRhs) const { return m_pEntry != acRhs.m_pEntry; }
|
|
const T& operator*() const { return *m_pEntry; }
|
|
|
|
private:
|
|
const T* m_pEntry;
|
|
};
|
|
|
|
ConstIterator begin() const { return ConstIterator(&data[0]); }
|
|
|
|
ConstIterator end() const { return ConstIterator(&data[length]); }
|
|
|
|
inline bool Empty() const noexcept { return length == 0; }
|
|
};
|
|
|
|
template <class T> void GameArray<T>::Resize(size_t aLength) noexcept
|
|
{
|
|
if (capacity >= aLength)
|
|
{
|
|
length = aLength & 0xFFFFFFFF;
|
|
}
|
|
else
|
|
{
|
|
T* pNewData = reinterpret_cast<T*>(Memory::Allocate(sizeof(T) * aLength));
|
|
std::copy(data, data + length, pNewData);
|
|
Memory::Free(data);
|
|
data = pNewData;
|
|
capacity = length = aLength;
|
|
}
|
|
}
|
|
|
|
static_assert(offsetof(GameArray<int>, length) == 0x10);
|
|
static_assert(sizeof(GameArray<int>) == 0x18);
|
|
|
|
template <class T> struct BSTSmallArray
|
|
{
|
|
int32_t capacity; // 0
|
|
T** data; // 8
|
|
uint32_t size; // 10
|
|
|
|
T* Get(uint32_t aIndex)
|
|
{
|
|
auto pData = reinterpret_cast<T**>(&data);
|
|
if (capacity >= 0)
|
|
pData = data;
|
|
|
|
return pData[aIndex];
|
|
}
|
|
};
|
|
|
|
#if TP_PLATFORM_64
|
|
static_assert(offsetof(BSTSmallArray<int>, size) == 0x10);
|
|
static_assert(sizeof(BSTSmallArray<int>) == 0x18);
|
|
#else
|
|
static_assert(offsetof(BSTSmallArray<int>, size) == 0x8);
|
|
static_assert(sizeof(BSTSmallArray<int>) == 0xC);
|
|
#endif
|
|
|
|
template <class T> struct GameList
|
|
{
|
|
struct Entry
|
|
{
|
|
T* data;
|
|
Entry* next;
|
|
};
|
|
|
|
Entry entry;
|
|
|
|
inline bool Empty() const noexcept { return entry.data == nullptr; }
|
|
inline size_t Size() const noexcept
|
|
{
|
|
if (entry.data == nullptr)
|
|
return 0ULL;
|
|
|
|
size_t size = 0;
|
|
for (const Entry* current = &entry; current; current = current->next)
|
|
size++;
|
|
|
|
return size;
|
|
}
|
|
|
|
// Range for loop compatibility
|
|
struct Iterator
|
|
{
|
|
Iterator(Entry* apEntry)
|
|
: m_pEntry(apEntry)
|
|
{
|
|
}
|
|
Iterator operator++()
|
|
{
|
|
m_pEntry = m_pEntry->next;
|
|
return *this;
|
|
}
|
|
bool operator!=(const Iterator& acRhs) const { return m_pEntry != acRhs.m_pEntry; }
|
|
T* operator*() const { return m_pEntry->data; }
|
|
|
|
private:
|
|
Entry* m_pEntry;
|
|
};
|
|
|
|
Iterator begin() { return Iterator(&entry); }
|
|
|
|
Iterator end() { return Iterator(nullptr); }
|
|
};
|
|
|
|
#if TP_PLATFORM_64
|
|
static_assert(offsetof(GameArray<int>, length) == 0x10);
|
|
static_assert(sizeof(GameArray<int>) == 0x18);
|
|
#else
|
|
static_assert(offsetof(GameArray<int>, length) == 0x8);
|
|
#endif
|
|
|
|
struct NiRefObject
|
|
{
|
|
virtual ~NiRefObject();
|
|
|
|
virtual void Destroy();
|
|
|
|
void IncRef();
|
|
void DecRef();
|
|
bool Release();
|
|
|
|
volatile long refCount;
|
|
uint32_t padC;
|
|
};
|
|
|
|
#if TP_PLATFORM_64
|
|
static_assert(sizeof(NiRefObject) == 0x10);
|
|
#endif
|
|
|
|
struct BSHandleRefObject : NiRefObject
|
|
{
|
|
void DecRefHandle()
|
|
{
|
|
if ((InterlockedDecrement(&refCount) & 0x3FF) == 0)
|
|
Destroy();
|
|
}
|
|
};
|
|
|
|
struct NiPoint3 : glm::vec3
|
|
{
|
|
NiPoint3()
|
|
: glm::vec3()
|
|
{
|
|
}
|
|
NiPoint3(const glm::vec3& acRhs)
|
|
: glm::vec3(acRhs)
|
|
{
|
|
}
|
|
|
|
float* AsArray() { return &x; }
|
|
};
|
|
|
|
static_assert(sizeof(NiPoint3) == 12);
|
|
static_assert(offsetof(NiPoint3, x) == 0);
|
|
static_assert(offsetof(NiPoint3, y) == 4);
|
|
static_assert(offsetof(NiPoint3, z) == 8);
|
|
|
|
struct NiPoint2 : glm::vec2
|
|
{
|
|
float* AsArray() { return &x; }
|
|
};
|
|
|
|
static_assert(sizeof(NiPoint2) == 8);
|
|
static_assert(offsetof(NiPoint2, x) == 0);
|
|
static_assert(offsetof(NiPoint2, y) == 4);
|
|
|
|
struct BSRecursiveLock
|
|
{
|
|
volatile DWORD m_tid;
|
|
volatile LONG m_counter;
|
|
|
|
void Lock();
|
|
void Unlock();
|
|
};
|
|
|
|
template <class T> struct BSScopedLock
|
|
{
|
|
BSScopedLock(T& aLock)
|
|
: m_lock(aLock)
|
|
{
|
|
m_lock.Lock();
|
|
}
|
|
~BSScopedLock() { m_lock.Unlock(); }
|
|
|
|
private:
|
|
T& m_lock;
|
|
};
|
|
|
|
template <class T> struct GamePtr
|
|
{
|
|
GamePtr()
|
|
: m_pPointer(nullptr)
|
|
{
|
|
}
|
|
|
|
GamePtr(T* apPointer)
|
|
: m_pPointer(apPointer)
|
|
{
|
|
if (m_pPointer)
|
|
m_pPointer->handleRefObject.IncRef();
|
|
}
|
|
|
|
GamePtr(const GamePtr<T>& acRhs)
|
|
: m_pPointer(acRhs.m_pPointer)
|
|
{
|
|
if (m_pPointer)
|
|
m_pPointer->handleRefObject.IncRef();
|
|
}
|
|
|
|
GamePtr(GamePtr<T>&& aRhs) { std::swap(m_pPointer, aRhs.m_pPointer); }
|
|
|
|
GamePtr& operator=(const GamePtr<T>& acRhs)
|
|
{
|
|
Release();
|
|
|
|
m_pPointer = acRhs.m_pPointer;
|
|
|
|
if (m_pPointer)
|
|
m_pPointer->handleRefObject.IncRef();
|
|
|
|
return *this;
|
|
}
|
|
|
|
GamePtr& operator=(T* apPointer)
|
|
{
|
|
Release();
|
|
|
|
m_pPointer = apPointer;
|
|
|
|
if (m_pPointer)
|
|
m_pPointer->handleRefObject.IncRef();
|
|
|
|
return *this;
|
|
}
|
|
|
|
GamePtr& operator=(GamePtr<T>&& aRhs)
|
|
{
|
|
std::swap(m_pPointer, aRhs.m_pPointer);
|
|
|
|
return *this;
|
|
}
|
|
|
|
T* operator->() { return m_pPointer; }
|
|
|
|
T* operator*() { return m_pPointer; }
|
|
|
|
operator T*() { return m_pPointer; }
|
|
|
|
~GamePtr() { Release(); }
|
|
|
|
void Release()
|
|
{
|
|
if (m_pPointer)
|
|
m_pPointer->handleRefObject.DecRefHandle();
|
|
|
|
m_pPointer = nullptr;
|
|
}
|
|
|
|
private:
|
|
T* m_pPointer;
|
|
};
|
|
|
|
struct alignas(sizeof(void*)) BSIntrusiveRefCounted
|
|
{
|
|
volatile int32_t refCount;
|
|
};
|
|
|
|
static_assert(sizeof(BSIntrusiveRefCounted) == sizeof(void*));
|
|
|
|
enum ETiltedFlags : uint8_t
|
|
{
|
|
kRemote = 1 << 0
|
|
};
|
|
|
|
template <class Target, class Source> Target* niptr_cast(const Source& acSrc)
|
|
{
|
|
return static_cast<Target*>(acSrc.object);
|
|
}
|
|
|
|
template <uint32_t FREE_LIST_BITS = 21, uint32_t AGE_SHIFT = 5> struct BSUntypedPointerHandle
|
|
{
|
|
uint32_t iBits = 0;
|
|
};
|
|
|
|
template <class T, class THandle = BSUntypedPointerHandle<>> struct BSPointerHandle
|
|
{
|
|
BSPointerHandle() = default;
|
|
|
|
operator bool() const { return handle.iBits != 0; }
|
|
|
|
THandle handle{};
|
|
};
|
|
|
|
struct BSReadWriteLock
|
|
{
|
|
uint32_t uiWriterThread;
|
|
volatile uint32_t uiLock;
|
|
};
|