DevourUnlocker/src/il2cpp_resolver.hpp
MiTHRAL d9a50caa4f
Some checks failed
Build DevourUnlocker / windows-cross (push) Failing after 8s
Build DevourUnlocker / linux (push) Failing after 6s
Build DevourUnlocker / standalone (push) Successful in 5s
v2.0.9: full store unlock — hook the ownership validators themselves
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.
2026-08-24 01:23:36 -04:00

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