Metadata dig findings (Assembly-CSharp, 2349 types):
- SteamInventoryValidator.PlayerHasItem(connId, steamItemDefID): multiplayer/purchase
validation gate used by WaitForPurchased{Pet,Emote,Flashlight,Outfit}Validation
coroutines (<validator>5__4) -> hooked true
- SteamInventoryManager.HasRetrievedUserInventoryItems(): gates PopulateInventoryWhenAvailable;
if Steam inventory query under Proton returns nothing, item views never populate ->
hooked true so lobby tabs build with UserHasItem=true
- SteamInventoryManager.userItems cache read directly by UI in some paths — covered by
UserHasItem+PlayerHasItem+HasRetrieved trio
Now 15 hooks: IsRobeUnlocked/IsCharacterUnlocked/HasPerk/HasOutfit->true,
UserHasItem/PlayerHasItem->owned, GetCurrentTokens->9999999,
HasRetrievedUserItems->true, UpdateLocked*(6)+WaitForPurchasedPetValidation call-through.
Pets/perks/flashlights/emotes/outfits route through the game's own grant path — no
purchase browser, no coin spoofing visible anywhere.
52 lines
2.1 KiB
C++
52 lines
2.1 KiB
C++
#pragma once
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
// Minimal IL2CPP types — avoids needing il2cpp headers at compile time
|
|
struct Il2CppString { void* klass; void* monitor; int32_t length; wchar_t chars[1]; };
|
|
struct MethodInfo;
|
|
|
|
namespace devour {
|
|
|
|
// Resolves IL2CPP method pointers without hard offsets.
|
|
// Strategy 1: via il2cpp exports (class/method lookup)
|
|
// Strategy 2: xref string sigscan as fallback
|
|
|
|
struct ResolvedMethod {
|
|
std::string name;
|
|
void* address = nullptr;
|
|
bool valid() const { return address != nullptr; }
|
|
};
|
|
|
|
class Il2CppResolver {
|
|
public:
|
|
static bool init(); // wait for GameAssembly.dll
|
|
static void* getProc(const char* name);
|
|
static std::vector<void*> scanPattern(const char* pattern, const char* mask, uintptr_t start, size_t size);
|
|
|
|
static ResolvedMethod resolve(const char* klassName, const char* methodName, int argc = -1);
|
|
static ResolvedMethod resolveByStringXref(const char* str, int occurrence = 0);
|
|
|
|
static ResolvedMethod isRobeUnlocked();
|
|
static ResolvedMethod isCharacterUnlocked();
|
|
static ResolvedMethod hasOutfit();
|
|
static ResolvedMethod hasPerk();
|
|
static ResolvedMethod hasPet(); // may fallback to UpdateLockedPets
|
|
static ResolvedMethod updateLockedPets();
|
|
static ResolvedMethod updateLockedPerks();
|
|
static ResolvedMethod updateLockedFlashlights();
|
|
static ResolvedMethod updateLockedEmotes();
|
|
static ResolvedMethod updateLockedOutfits();
|
|
static ResolvedMethod updateLockedRobes();
|
|
static ResolvedMethod waitForPurchasedPet();
|
|
static ResolvedMethod userHasItem(); // SteamInventoryManager.UserHasItem(steamItemDefID)
|
|
static ResolvedMethod getCurrentTokens(); // Horror.Menu.GetCurrentTokens()
|
|
static ResolvedMethod playerHasItem(); // SteamInventoryValidator.PlayerHasItem(connId, steamItemDefID)
|
|
static ResolvedMethod hasRetrievedUserItems(); // SteamInventoryManager.HasRetrievedUserInventoryItems()
|
|
static void dumpDiagnostics();
|
|
static uintptr_t gameAssemblyBase();
|
|
static size_t gameAssemblySize();
|
|
};
|
|
|
|
} // namespace devour
|