CFramework/CFramework/Cheat/SDK/CExfil/CExfil.cpp

110 lines
2.9 KiB
C++

#include "CExfil.h"
#include <cstdint>
#include <string>
#include <vector>
namespace
{
std::string ReadManagedName(uintptr_t stringObject)
{
if (!Memory::IsUserAddress(stringObject))
return {};
int32_t length = 0;
if (!m.TryRead(stringObject + offset::ManagedString::Length, length) ||
length <= 0 || length > 127)
{
return {};
}
std::vector<char16_t> chars;
if (!m.TryReadVector<char16_t>(stringObject + offset::ManagedString::Data,
static_cast<std::size_t>(length), chars, 127))
{
return {};
}
std::string name;
name.reserve(chars.size());
for (const char16_t ch : chars)
{
if (ch == 0)
break;
name.push_back(ch >= 0x20 && ch <= 0x7E ? static_cast<char>(ch) : '?');
}
return name;
}
}
ExfilDisplayCategory ClassifyExfilStatus(const uint8_t status) noexcept
{
switch (status)
{
case static_cast<uint8_t>(CLOSE):
return ExfilDisplayCategory::Closed;
case static_cast<uint8_t>(NOTREADY):
return ExfilDisplayCategory::Pending;
case static_cast<uint8_t>(OPEN):
case static_cast<uint8_t>(READY):
return ExfilDisplayCategory::Open;
default:
return ExfilDisplayCategory::Unknown;
}
}
const char* GetExfilStatusText(const uint8_t status) noexcept
{
switch (status)
{
case static_cast<uint8_t>(CLOSE): return "Closed";
case static_cast<uint8_t>(NOTREADY): return "Not ready";
case static_cast<uint8_t>(OPEN): return "Open";
case static_cast<uint8_t>(READY): return "Ready";
default: return "Unknown";
}
}
bool CExfil::GetAddress(uintptr_t& address)
{
ptr = address;
return Memory::IsUserAddress(ptr);
}
uint8_t CExfil::GetStatus()
{
uint8_t status = 0;
if (!Memory::IsUserAddress(ptr) || !m.TryRead(ptr + offset::Exfil::Status, status))
return 0;
return status;
}
std::string CExfil::GetName()
{
uintptr_t settings = 0;
uintptr_t namePtr = 0;
if (!Memory::IsUserAddress(ptr) ||
!m.TryRead(ptr + offset::Exfil::Settings, settings) || !Memory::IsUserAddress(settings) ||
!m.TryRead(settings + offset::Exfil::Name, namePtr) || !Memory::IsUserAddress(namePtr))
{
return {};
}
return ReadManagedName(namePtr);
}
bool CExfil::Update()
{
// Status is diagnostic data; a status read failure must not discard a valid position.
m_pExfilStatus = GetStatus();
m_pVecLocation = {};
if (!Memory::IsUserAddress(ptr))
return false;
const uintptr_t transform = m.ReadChain(ptr,
{ offset::UnityComponent::Step0, offset::UnityComponent::Step1, offset::UnityComponent::Step2,
offset::UnityComponent::Step3, offset::UnityComponent::Step4, offset::UnityComponent::Transform });
m_pVecLocation = GetTransformPosition(transform);
return !Vec3_Empty(m_pVecLocation);
}