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
14 changes: 7 additions & 7 deletions dll/dll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2020,24 +2020,24 @@ STEAMCLIENT_API steam_bool Steam3_GSSetStatus( HSteamUser hUser, int32 nAppIdSer
return gs->Obsolete_GSSetStatus(nAppIdServed, unServerFlags, cPlayers, cPlayersMax, cBotPlayers, unGamePort, pchServerName, pchGameDir, pchMapName, pchVersion);
}

static std::map<HSteamUser, CCAPICMCallBack> capi_cmcallback_map;
static std::map<HSteamUser, CAPI_CMCallback> capi_cmcallback_map;

STEAMCLIENT_API void Steam3_Init( HSteamUser hUser,
OnLogonSuccessFunc func1,
OnLogonFailureFunc func2,
OnLoggedOffFunc func3,
OnBeginLogonRetryFunc func4,
HandleVACChallengeFunc func5,
GSHandleClientApproveFunc func6,
GSHandleClientDenyFunc func7,
GSHandleClientKickFunc func8 )
GSHandleClientApproveFunc func5,
GSHandleClientDenyFunc func6,
GSHandleClientKickFunc func7,
Steam2GetValueFunc func8 )
{
PRINT_DEBUG_ENTRY();
get_steam_client()->steamclient_version = 2;
ISteamUser002 *su = reinterpret_cast<ISteamUser002 *>(get_steam_client()->GetISteamUser(hUser, "SteamUser002"));
CCAPICMCallBack new_cmcallback(func1, func2, func3, func4, func5, func6, func7, func8);
CAPI_CMCallback new_cmcallback(func1, func2, func3, func4, func5, func6, func7, func8);
auto [it, _] = capi_cmcallback_map.insert_or_assign(hUser, new_cmcallback);
su->Init(&it->second, nullptr);
su->Init(static_cast<ICMCallback *>(&it->second), static_cast<ISteam2Auth *>(&it->second));
}
// SteamClient002 -----------------------------------------------------

Expand Down
62 changes: 32 additions & 30 deletions dll/dll/capicmcallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,54 +22,56 @@

typedef void (*OnLogonSuccessFunc)();
typedef void (*OnLogonFailureFunc)(EResult);
typedef void (*OnLoggedOffFunc)();
typedef void (*OnLoggedOffFunc)(EResult);
typedef void (*OnBeginLogonRetryFunc)();
typedef void (*HandleVACChallengeFunc)(int, uint8 *, int);
typedef void (*GSHandleClientApproveFunc)(CSteamID &);
typedef void (*GSHandleClientDenyFunc)(CSteamID &, EDenyReason);
typedef void (*GSHandleClientKickFunc)(CSteamID &, EDenyReason);
typedef void (*GSHandleClientApproveFunc)(uint64);
typedef void (*GSHandleClientDenyFunc)(uint64, EDenyReason);
typedef void (*GSHandleClientKickFunc)(uint64, EDenyReason);
typedef int (*Steam2GetValueFunc)(const char *, char *, int);

class CCAPICMCallBack : public ICMCallback
class CAPI_CMCallback : public ICMCallback, public ISteam2Auth
{
OnLogonSuccessFunc OnLogonSuccess_ptr{};
OnLogonFailureFunc OnLogonFailure_ptr{};
OnLoggedOffFunc OnLoggedOff_ptr{};
OnBeginLogonRetryFunc OnBeginLogonRetry_ptr{};
GSHandleClientApproveFunc GSHandleClientApprove_ptr{};
GSHandleClientDenyFunc GSHandleClientDeny_ptr{};
GSHandleClientKickFunc GSHandleClientKick_ptr{};
Steam2GetValueFunc GetValue_ptr{};

public:
CCAPICMCallBack(OnLogonSuccessFunc func1,
CAPI_CMCallback(OnLogonSuccessFunc func1,
OnLogonFailureFunc func2,
OnLoggedOffFunc func3,
OnBeginLogonRetryFunc func4,
HandleVACChallengeFunc func5,
GSHandleClientApproveFunc func6,
GSHandleClientDenyFunc func7,
GSHandleClientKickFunc func8)
GSHandleClientApproveFunc func5,
GSHandleClientDenyFunc func6,
GSHandleClientKickFunc func7,
Steam2GetValueFunc func8)
{
OnLogonSuccess_ptr = func1;
OnLogonFailure_ptr = func2;
OnLoggedOff_ptr = func3;
OnBeginLogonRetry_ptr = func4;
HandleVACChallenge_ptr = func5;
GSHandleClientApprove_ptr = func6;
GSHandleClientDeny_ptr = func7;
GSHandleClientKick_ptr = func8;
GSHandleClientApprove_ptr = func5;
GSHandleClientDeny_ptr = func6;
GSHandleClientKick_ptr = func7;
GetValue_ptr = func8;
}
~CCAPICMCallBack() {}
~CAPI_CMCallback() {}

void OnLogonSuccess() { OnLogonSuccess_ptr(); }
void OnLogonFailure(EResult eResult) { OnLogonFailure_ptr(eResult); }
void OnLoggedOff() { OnLoggedOff_ptr(); }
void OnLoggedOff(EResult eResult) { OnLoggedOff_ptr(eResult); }
void OnBeginLogonRetry() { OnBeginLogonRetry_ptr(); }
void HandleVACChallenge(int nClientGameID, uint8 *pubChallenge, int cubChallenge) { HandleVACChallenge_ptr(nClientGameID, pubChallenge, cubChallenge); }
void GSHandleClientApprove(CSteamID &steamID) { GSHandleClientApprove_ptr(steamID); }
void GSHandleClientDeny(CSteamID &steamID, EDenyReason eDenyReason) { GSHandleClientDeny_ptr(steamID, eDenyReason); }
void GSHandleClientKick(CSteamID &steamID, EDenyReason eDenyReason) { GSHandleClientKick_ptr(steamID, eDenyReason); }
void HandleVACChallenge(int nClientGameID, uint8 *pubChallenge, int cubChallenge) {}
void GSHandleClientApprove(CSteamID &steamID) { GSHandleClientApprove_ptr(steamID.ConvertToUint64()); }
void GSHandleClientDeny(CSteamID &steamID, EDenyReason eDenyReason) { GSHandleClientDeny_ptr(steamID.ConvertToUint64(), eDenyReason); }
void GSHandleClientKick(CSteamID &steamID, EDenyReason eDenyReason) { GSHandleClientKick_ptr(steamID.ConvertToUint64(), eDenyReason); }

private:
OnLogonSuccessFunc OnLogonSuccess_ptr{};
OnLogonFailureFunc OnLogonFailure_ptr{};
OnLoggedOffFunc OnLoggedOff_ptr{};
OnBeginLogonRetryFunc OnBeginLogonRetry_ptr{};
HandleVACChallengeFunc HandleVACChallenge_ptr{};
GSHandleClientApproveFunc GSHandleClientApprove_ptr{};
GSHandleClientDenyFunc GSHandleClientDeny_ptr{};
GSHandleClientKickFunc GSHandleClientKick_ptr{};
int GetValue(const char *var, char *buf, int bufsize) { return GetValue_ptr(var, buf, bufsize); }
int GetServerReadableTicket(uint32 unk1, uint32 unk2, void *unk3, uint32 unk4, uint32 *unk5) { return 0; }
};

#endif // __INCLUDED_CAPICMCALLBACK_H__
41 changes: 39 additions & 2 deletions dll/dll/steam_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ struct Steam_Pipe {
bool got_last_cb{};
};

struct User_Ref {
HSteamUser user{};
HSteamPipe pipe{};
};

class Steam_Client :
public ISteamClient001,
public ISteamClient002,
Expand Down Expand Up @@ -191,11 +196,42 @@ public ISteamClient
bool gameserver_has_ipv6_functions{};
int steamclient_version{};
bool using_old_callbacks{};

int client_user_ref_count{};

template <class T>
class Reusable_Numbers {
T counter{};
std::priority_queue<T, std::vector<T>, std::greater<>> freed_numbers{};

public:
T get_number()
{
T retval{};
if (!freed_numbers.empty()) {
retval = freed_numbers.top();
freed_numbers.pop();
} else {
if (!counter) ++counter;
retval = counter;
++counter;
}

return retval;
}

void free_number(T number)
{
freed_numbers.push(number);
}
};

uint32 steam_pipe_counter = 1;
std::priority_queue<uint32, std::vector<uint32>, std::greater<>> freed_steam_pipes{};
Reusable_Numbers<uint32> steam_pipe_numbers{};
std::map<HSteamPipe, Steam_Pipe> steam_pipes{};

Reusable_Numbers<uint32> old_user_ref_numbers{};
std::map<HSteamUser, User_Ref> old_user_refs{};


Steam_Client();
~Steam_Client();
Expand Down Expand Up @@ -427,6 +463,7 @@ public ISteamClient
void report_missing_impl(std::string_view itf, std::string_view caller);
[[noreturn]] void report_missing_impl_and_exit(std::string_view itf, std::string_view caller);

HSteamUser create_old_user_ref(HSteamUser hUser, HSteamPipe hSteamPipe);
HSteamPipe get_pipe_for_user(HSteamUser hUser);

};
Expand Down
98 changes: 59 additions & 39 deletions dll/steam_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,15 +317,7 @@ HSteamPipe Steam_Client::CreateSteamPipe()
{
PRINT_DEBUG_ENTRY();

HSteamPipe pipe{};
if (!freed_steam_pipes.empty()) {
pipe = freed_steam_pipes.top();
freed_steam_pipes.pop();
} else {
if (!steam_pipe_counter) ++steam_pipe_counter;
pipe = steam_pipe_counter;
++steam_pipe_counter;
}
HSteamPipe pipe = steam_pipe_numbers.get_number();

PRINT_DEBUG(" returned pipe handle %i", pipe);
steam_pipes[pipe] = { Steam_Pipe_Type::NO_USER, false };
Expand All @@ -341,7 +333,7 @@ bool Steam_Client::BReleaseSteamPipe( HSteamPipe hSteamPipe )
{
PRINT_DEBUG("%i", hSteamPipe);
if (steam_pipes.count(hSteamPipe)) {
freed_steam_pipes.push(hSteamPipe);
steam_pipe_numbers.free_number(hSteamPipe);
return steam_pipes.erase(hSteamPipe) > 0;
}

Expand All @@ -358,20 +350,23 @@ HSteamUser Steam_Client::ConnectToGlobalUser( HSteamPipe hSteamPipe )
return 0;
}

userLogIn();
if (client_user_ref_count == 0) {
userLogIn();

// initialize GC now so that we have user's inventory ready right away
steam_game_coordinator->initialize_gc();

// games like appid 1740720 and 2379780 do not call SteamAPI_RunCallbacks() or SteamAPI_ManualDispatch_RunFrame() or Steam_BGetCallback()
// hence all run_callbacks() will never run, which might break the assumption that these callbacks are always run
// also networking callbacks won't run
// hence we spawn the background thread here which trigger all run_callbacks() and run networking callbacks
PRINT_DEBUG("started background thread");
background_thread->start(this);
// initialize GC now so that we have user's inventory ready right away
steam_game_coordinator->initialize_gc();

steam_overlay->SetupOverlay();

// games like appid 1740720 and 2379780 do not call SteamAPI_RunCallbacks() or SteamAPI_ManualDispatch_RunFrame() or Steam_BGetCallback()
// hence all run_callbacks() will never run, which might break the assumption that these callbacks are always run
// also networking callbacks won't run
// hence we spawn the background thread here which trigger all run_callbacks() and run networking callbacks
PRINT_DEBUG("started background thread");
background_thread->start(this);

steam_overlay->SetupOverlay();
}

client_user_ref_count++;
steam_pipes[hSteamPipe] = {Steam_Pipe_Type::CLIENT, false};
return CLIENT_HSTEAMUSER;
}
Expand Down Expand Up @@ -408,7 +403,7 @@ HSteamUser Steam_Client::CreateLocalUser( HSteamPipe *phSteamPipe )
// NOT THREADSAFE - ensure that no other threads are accessing Steamworks API when calling
void Steam_Client::ReleaseUser( HSteamPipe hSteamPipe, HSteamUser hUser )
{
PRINT_DEBUG_ENTRY();
PRINT_DEBUG("%i %i", hSteamPipe, hUser);

if (!steam_pipes.count(hSteamPipe))
return;
Expand All @@ -420,7 +415,13 @@ void Steam_Client::ReleaseUser( HSteamPipe hSteamPipe, HSteamUser hUser )

serverShutdown();
} else if (hUser == CLIENT_HSTEAMUSER) {
clientShutdown();
if (client_user_ref_count > 0) {
client_user_ref_count--;

if (client_user_ref_count == 0) {
clientShutdown();
}
}
}
}

Expand Down Expand Up @@ -1047,42 +1048,53 @@ HSteamUser Steam_Client::CreateGlobalInstance()
{
PRINT_DEBUG_ENTRY();
HSteamPipe pipe = 0;
return CreateGlobalUser(&pipe);
HSteamUser user = CreateGlobalUser(&pipe);
return create_old_user_ref(user, pipe);
}

HSteamUser Steam_Client::ConnectToGlobalInstance()
{
PRINT_DEBUG_ENTRY();
HSteamPipe pipe = get_pipe_for_user(CLIENT_HSTEAMUSER);
if (!pipe) {
pipe = CreateSteamPipe();
if (steamclient_version < 4) {
for (auto &[key, val] : old_user_refs) {
if (val.user == CLIENT_HSTEAMUSER) {
return key;
}
}
}

return ConnectToGlobalUser(pipe);
HSteamPipe pipe = CreateSteamPipe();
HSteamUser user = ConnectToGlobalUser(pipe);
return create_old_user_ref(user, pipe);
}

HSteamUser Steam_Client::CreateLocalInstance()
{
PRINT_DEBUG_ENTRY();
HSteamPipe pipe = 0;
return CreateLocalUser(&pipe);
HSteamUser user = CreateLocalUser(&pipe);
return create_old_user_ref(user, pipe);
}

void Steam_Client::ReleaseInstance( HSteamUser hSteamUser )
{
PRINT_DEBUG_ENTRY();
HSteamPipe pipe = get_pipe_for_user(hSteamUser);
if (pipe) {
ReleaseUser(pipe, hSteamUser);
BReleaseSteamPipe(pipe);
}
auto it = old_user_refs.find(hSteamUser);
if (it == old_user_refs.end()) return;

ReleaseUser(it->second.pipe, it->second.user);
BReleaseSteamPipe(it->second.pipe);

old_user_ref_numbers.free_number(hSteamUser);
old_user_refs.erase(it);
}

ISteamUser *Steam_Client::GetISteamUser( HSteamUser hSteamUser, const char *pchVersion )
{
PRINT_DEBUG_ENTRY();
HSteamPipe pipe = get_pipe_for_user(hSteamUser);
return GetISteamUser(hSteamUser, pipe, pchVersion);
if (!old_user_refs.count(hSteamUser)) return nullptr;
User_Ref &user_ref = old_user_refs[hSteamUser];
return GetISteamUser(user_ref.user, user_ref.pipe, pchVersion);
}

// retrieves the IVac interface associated with the handle
Expand Down Expand Up @@ -1115,8 +1127,9 @@ bool Steam_Client::BMainLoop( uint64 time )
ISteamGameServer *Steam_Client::GetISteamGameServer( HSteamUser hSteamUser, const char *pchVersion )
{
PRINT_DEBUG_ENTRY();
HSteamPipe pipe = get_pipe_for_user(hSteamUser);
return GetISteamGameServer(hSteamUser, pipe, pchVersion);
if (!old_user_refs.count(hSteamUser)) return nullptr;
User_Ref &user_ref = old_user_refs[hSteamUser];
return GetISteamGameServer(user_ref.user, user_ref.pipe, pchVersion);
}
// SteamClient004 -----------------------------------------------------

Expand Down Expand Up @@ -1182,6 +1195,13 @@ void Steam_Client::SetEUniverse( EUniverse universe )
}
// SteamClient005 -----------------------------------------------------

HSteamUser Steam_Client::create_old_user_ref(HSteamUser hUser, HSteamPipe hSteamPipe)
{
HSteamUser ref = old_user_ref_numbers.get_number();
old_user_refs[ref] = { hUser, hSteamPipe };
return ref;
}

HSteamPipe Steam_Client::get_pipe_for_user(HSteamUser hUser)
{
if (hUser == CLIENT_HSTEAMUSER) {
Expand Down
5 changes: 3 additions & 2 deletions dll/steam_user.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,7 @@ void Steam_User::Init( ICMCallback *cmcallback, ISteam2Auth *steam2auth )
bool Steam_User::BGetCallback( int *piCallback, uint8 **ppubParam, int *unk )
{
PRINT_DEBUG_ENTRY();
// HACK: Use the first available pipe.
HSteamUser user = is_server ? SERVER_HSTEAMUSER : CLIENT_HSTEAMUSER;
HSteamPipe pipe = get_steam_client()->get_pipe_for_user(user);
if (!pipe)
Expand Down Expand Up @@ -1138,7 +1139,7 @@ void Steam_User::RunCallbacks()

if (call_logged_off && check_timedout(logoff_time, 0.1)) {
PRINT_DEBUG("ICMCallback -> OnLoggedOff");
callbacks_old1->OnLoggedOff();
callbacks_old1->OnLoggedOff(k_EResultOK);
call_logged_off = false;
}

Expand All @@ -1161,7 +1162,7 @@ void Steam_User::RunCallbacks()

if (call_logged_off && check_timedout(logoff_time, 0.1)) {
PRINT_DEBUG("ICMCallback -> OnLoggedOff");
callbacks_old2->OnLoggedOff();
callbacks_old2->OnLoggedOff(k_EResultOK);
call_logged_off = false;
}

Expand Down
2 changes: 1 addition & 1 deletion sdk/steam/isteamuser001.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ICMCallback001

virtual void OnLogonSuccess() = 0;
virtual void OnLogonFailure( EResult eResult ) = 0;
virtual void OnLoggedOff() = 0;
virtual void OnLoggedOff( EResult eResult ) = 0;
virtual void HandleVACChallenge( int nClientGameID, uint8 *pubChallenge, int cubChallenge ) = 0;
virtual void GSHandleClientApprove( CSteamID &steamID ) = 0;
virtual void GSHandleClientDeny( CSteamID &steamID, EDenyReason eDenyReason ) = 0;
Expand Down
Loading