Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Hook/Hooks_Package.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,11 @@ namespace {
TryProcessPendingLicenseRefresh();

// LOG_PACKAGE_TRACE("CheckAppOwnership: AppId={} result={} {}", appId, result, pOwn->DebugString());
if (LuaConfig::HasDepot(appId)) {
if (LuaConfig::HasDepot(appId,false)) {
if (result && pOwn->ExistInPackageNums > 1) {
// Actually owned — record so HasDepot excludes it going forward
LuaConfig::MarkOwned(appId);
pOwn->ReleaseState = EAppReleaseState::Released;
} else {
pOwn->PackageId = kInjectedPackageId;
pOwn->ReleaseState = EAppReleaseState::Released;
Expand Down
22 changes: 19 additions & 3 deletions src/Hook/Hooks_SteamUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,23 @@
#include "steam_messages.pb.h"
#include "Utils/VehCommon.h"

#include <chrono>
#include <thread>

namespace {

CAPTURE_THIS_FUNC(GetAppByID, CSteamApp*, g_pController,void* pThis, AppId_t appId, bool bCreate);
CAPTURE_THIS_FUNC(MarkAppChange,void*,g_pAppChangeSource,void* pThis,AppId_t appId, EAppChangeFlags changeFlags);

HOOK_FUNC(FillInAppOverview,void*,void* pThis,void* pAppOverview,CSteamApp* pApp)
{
if (pApp && LuaConfig::HasDepot(pApp->nAppID,false)) {
uint32_t t = LuaConfig::GetPurchaseTime(pApp->nAppID);
if(t) {
pApp->PurchasedTime = t;
LOG_STEAMUI_TRACE("FillInAppOverview: set PurchasedTime={} for appId={}",
pApp->PurchasedTime, pApp->nAppID);
}
}
return oFillInAppOverview(pThis, pAppOverview, pApp);
}
}

namespace Hooks_SteamUI {
Expand All @@ -22,16 +31,23 @@ namespace Hooks_SteamUI {
ARM_CAPTURE_U(MarkAppChange);

HOOK_BEGIN();
INSTALL_HOOK_U(FillInAppOverview);
HOOK_END();

}

void Uninstall() {
UNHOOK_BEGIN();
UNINSTALL_HOOK(FillInAppOverview);
UNHOOK_END();
}

void RemoveAppAndSendChange(AppId_t appId) {
// skip on owned apps
if(LuaConfig::IsOwned(appId)){
LOG_STEAMUI_WARN("RemoveAppAndSendChange: appId={} is owned, skipping", appId);
return;
}
if(CAPTURE_READY(GetAppByID) && CAPTURE_READY(MarkAppChange)) {
CSteamApp* pApp = oGetAppByID(g_pController, appId, false);
if(pApp) {
Expand Down
4 changes: 3 additions & 1 deletion src/Steam/Structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ struct CAppData
}
};

#pragma pack(push,1)
struct CSteamApp
{
void** fptr;
Expand All @@ -345,4 +346,5 @@ struct CSteamApp
uint32 _unknown3;
uint64 SteamID;
uint32 PurchasedTime;
};
};
#pragma pack(pop)
42 changes: 41 additions & 1 deletion src/Utils/LuaConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ namespace LuaConfig{
static std::unordered_map<std::string, std::unordered_set<AppId_t>> g_fileDepots;
// Reference count: how many files provide each depot.
static std::unordered_map<AppId_t, uint32_t> g_depotRefCount;
// mtime (unix epoch seconds) of each parsed .lua file, captured at ParseFile entry.
static std::unordered_map<std::string, uint32_t> g_fileMtime;
// Per-appId purchase time: max(mtime) across every file that currently contributes it.
// Simple variant: never lowered on UnloadFile unless the refcount drops to zero.
static std::unordered_map<AppId_t, uint32_t> g_purchaseTime;
// Depot IDs removed by UnloadFile / added by ParseFile, consumed by NotifyLicenseChanged.
static std::vector<AppId_t> g_pendingRemovals;
static std::vector<AppId_t> g_pendingAdditions;
Expand Down Expand Up @@ -174,6 +179,15 @@ namespace LuaConfig{
if (g_fileDepots[g_currentFile].insert(DepotId).second) {
if (++g_depotRefCount[DepotId] == 1)
g_pendingAdditions.push_back(DepotId);

// Update the appId's purchase time with the current file's mtime,
// keeping the maximum across every contributing file.
auto mtIt = g_fileMtime.find(g_currentFile);
if (mtIt != g_fileMtime.end()) {
uint32_t mt = mtIt->second;
auto& slot = g_purchaseTime[DepotId];
if (mt > slot) slot = mt;
}
}
}

Expand Down Expand Up @@ -404,7 +418,11 @@ namespace LuaConfig{

// ── public query API ─────────────────────────────────────────
bool HasDepot(AppId_t DepotId,bool checkOwned) {
return DepotKeySet.count(DepotId) && (!checkOwned || !OwnedAppIdSet.count(DepotId));
return DepotKeySet.count(DepotId) && (!checkOwned || !IsOwned(DepotId));
}

bool IsOwned(AppId_t AppId) {
return OwnedAppIdSet.count(AppId);
}

void MarkOwned(AppId_t AppId) {
Expand Down Expand Up @@ -453,6 +471,11 @@ namespace LuaConfig{
return kDefaultStatSteamId;
}

uint32_t GetPurchaseTime(AppId_t AppId) {
auto it = g_purchaseTime.find(AppId);
return it != g_purchaseTime.end() ? it->second : 0;
}

const std::unordered_map<uint64_t, ManifestOverride>& GetManifestOverrides() {
return ManifestOverrides;
}
Expand Down Expand Up @@ -568,12 +591,14 @@ namespace LuaConfig{
if (--g_depotRefCount[id] == 0) {
g_depotRefCount.erase(id);
DepotKeySet.erase(id);
g_purchaseTime.erase(id);
g_pendingRemovals.push_back(id);
}
}

LOG_PACKAGE_INFO("UnloadFile: removed {} depots from {}", it->second.size(), filePath);
g_fileDepots.erase(it);
g_fileMtime.erase(filePath);
}

std::vector<AppId_t> TakePendingRemovals() {
Expand Down Expand Up @@ -602,6 +627,21 @@ namespace LuaConfig{
LOG_WARN("ParseFile: failed to open {}", path.filename().string());
return;
}

// Capture the file's last-modified time (unix epoch, seconds) so
// lua_addappid can stamp it onto every appId this file contributes.
// Portable conversion that does not require C++20 clock_cast.
{
std::error_code ec;
auto ftime = std::filesystem::last_write_time(path, ec);
uint32_t mtime = 0;
if (!ec) {
auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
ftime - decltype(ftime)::clock::now() + std::chrono::system_clock::now());
mtime = static_cast<uint32_t>(std::chrono::system_clock::to_time_t(sctp));
}
g_fileMtime[filePath] = mtime;
}

std::string chunk, line;
int lineNo = 0;
Expand Down
4 changes: 3 additions & 1 deletion src/Utils/LuaConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@

namespace LuaConfig{
bool HasDepot(AppId_t appId, bool checkOwned=true);
bool IsOwned(AppId_t appId);
void MarkOwned(AppId_t appId);
std::vector<AppId_t> GetAllDepotIds();
std::vector<uint8> GetDecryptionKey(AppId_t appId);
uint64_t GetAccessToken(AppId_t appId);
uint64_t GetStatSteamId(AppId_t appId);
bool pinApp(AppId_t appId);

uint32_t GetPurchaseTime(AppId_t appId);

struct ManifestOverride {
uint64_t gid;
uint64_t size;
Expand Down
Loading