Skip to content

Commit

Permalink
Fix initializing on GameServers and added InitEx for them (Fixes #632,…
Browse files Browse the repository at this point in the history
… thanks to @zackman0010)

- Started using pszInternalCheckInterfaceVersions
- No longer initializing CallbackDispatcher if CSteamAPIContext.Init failed
- Send a custom error message via OutSteamErrMsg if CSteamAPIContext.Init failed
  • Loading branch information
rlabrecque committed Jul 29, 2024
1 parent 4a54dc7 commit 3db2bfa
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 37 deletions.
4 changes: 2 additions & 2 deletions CodeGen/templates/nativemethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace Steamworks {

#region steam_api.h
[DllImport(NativeLibraryName, EntryPoint = "SteamInternal_SteamAPI_Init", CallingConvention = CallingConvention.Cdecl)]
public static extern ESteamAPIInitResult SteamInternal_SteamAPI_Init(IntPtr pszInternalCheckInterfaceVersions, IntPtr pOutErrMsg);
public static extern ESteamAPIInitResult SteamInternal_SteamAPI_Init(InteropHelp.UTF8StringHandle pszInternalCheckInterfaceVersions, IntPtr pOutErrMsg);

[DllImport(NativeLibraryName, EntryPoint = "SteamAPI_Shutdown", CallingConvention = CallingConvention.Cdecl)]
public static extern void SteamAPI_Shutdown();
Expand Down Expand Up @@ -155,7 +155,7 @@ namespace Steamworks {
public static extern int SteamGameServer_GetHSteamUser();

[DllImport(NativeLibraryName, EntryPoint = "SteamInternal_GameServer_Init_V2", CallingConvention = CallingConvention.Cdecl)]
public static extern ESteamAPIInitResult SteamInternal_GameServer_Init_V2(uint unIP, ushort usPort, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, InteropHelp.UTF8StringHandle pchVersionString, IntPtr pszInternalCheckInterfaceVersions, IntPtr pOutErrMsg);
public static extern ESteamAPIInitResult SteamInternal_GameServer_Init_V2(uint unIP, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, InteropHelp.UTF8StringHandle pchVersionString, InteropHelp.UTF8StringHandle pszInternalCheckInterfaceVersions, IntPtr pOutErrMsg);
#endregion
#region SteamAPI Accessors
[DllImport(NativeLibraryName, EntryPoint = "SteamClient", CallingConvention = CallingConvention.Cdecl)]
Expand Down
119 changes: 86 additions & 33 deletions com.rlabrecque.steamworks.net/Runtime/Steam.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,33 +58,64 @@ public static ESteamAPIInitResult InitEx(out string OutSteamErrMsg)
{
InteropHelp.TestIfPlatformSupported();

IntPtr SteamErrorMsgPtr = Marshal.AllocHGlobal(Constants.k_cchMaxSteamErrMsg);
ESteamAPIInitResult initResult = NativeMethods.SteamInternal_SteamAPI_Init(IntPtr.Zero, SteamErrorMsgPtr);
OutSteamErrMsg = InteropHelp.PtrToStringUTF8(SteamErrorMsgPtr);
Marshal.FreeHGlobal(SteamErrorMsgPtr);

// Steamworks.NET specific: We initialize the SteamAPI Context like this for now, but we need to do it
// every time that Unity reloads binaries, so we also check if the pointers are available and initialized
// before each call to any interface functions. That is in InteropHelp.cs
if (initResult == ESteamAPIInitResult.k_ESteamAPIInitResult_OK)
{
bool ret = CSteamAPIContext.Init();
if (!ret) {
initResult = ESteamAPIInitResult.k_ESteamAPIInitResult_FailedGeneric;
var pszInternalCheckInterfaceVersions = new System.Text.StringBuilder();
pszInternalCheckInterfaceVersions.Append(Constants.STEAMUTILS_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMNETWORKINGUTILS_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMAPPS_INTERFACE_VERSION).Append("\0");
//pszInternalCheckInterfaceVersions.Append(Constants.STEAMCONTROLLER_INTERFACE_VERSION).Append("\0"); // ISteamController is deprecated in favor of ISteamInput.
pszInternalCheckInterfaceVersions.Append(Constants.STEAMFRIENDS_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMGAMESEARCH_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMHTMLSURFACE_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMHTTP_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMINPUT_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMINVENTORY_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMMATCHMAKINGSERVERS_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMMATCHMAKING_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMMUSICREMOTE_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMMUSIC_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMNETWORKINGMESSAGES_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMNETWORKINGSOCKETS_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMNETWORKING_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMPARENTALSETTINGS_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMPARTIES_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMREMOTEPLAY_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMREMOTESTORAGE_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMSCREENSHOTS_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMUGC_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMUSERSTATS_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMUSER_INTERFACE_VERSION).Append("\0");
pszInternalCheckInterfaceVersions.Append(Constants.STEAMVIDEO_INTERFACE_VERSION).Append("\0");

using (var pszInternalCheckInterfaceVersions2 = new InteropHelp.UTF8StringHandle(pszInternalCheckInterfaceVersions.ToString())) {
IntPtr SteamErrorMsgPtr = Marshal.AllocHGlobal(Constants.k_cchMaxSteamErrMsg);
ESteamAPIInitResult initResult = NativeMethods.SteamInternal_SteamAPI_Init(pszInternalCheckInterfaceVersions2, SteamErrorMsgPtr);
OutSteamErrMsg = InteropHelp.PtrToStringUTF8(SteamErrorMsgPtr);
Marshal.FreeHGlobal(SteamErrorMsgPtr);

// Steamworks.NET specific: We initialize the SteamAPI Context like this for now, but we need to do it
// every time that Unity reloads binaries, so we also check if the pointers are available and initialized
// before each call to any interface functions. That is in InteropHelp.cs
if (initResult == ESteamAPIInitResult.k_ESteamAPIInitResult_OK)
{
bool ret = CSteamAPIContext.Init();
if (ret) {
CallbackDispatcher.Initialize();
}
else {
initResult = ESteamAPIInitResult.k_ESteamAPIInitResult_FailedGeneric;
OutSteamErrMsg = "[Steamworks.NET] Failed to initialize CSteamAPIContext";
}
}

CallbackDispatcher.Initialize();
return initResult;
}

return initResult;
}

public static bool Init() {
InteropHelp.TestIfPlatformSupported();

string SteamErrorMsg;
ESteamAPIInitResult initResult = InitEx(out SteamErrorMsg);
return initResult == ESteamAPIInitResult.k_ESteamAPIInitResult_OK;
return InitEx(out SteamErrorMsg) == ESteamAPIInitResult.k_ESteamAPIInitResult_OK;
}

// SteamAPI_Shutdown should be called during process shutdown if possible.
Expand Down Expand Up @@ -196,32 +227,54 @@ public static class GameServer {
// ISteamGameServer::GetNextOutgoingPacket.)
// - The version string should be in the form x.x.x.x, and is used by the master server to detect when the
// server is out of date. (Only servers with the latest version will be listed.)
public static bool Init(uint unIP, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, string pchVersionString) {
public static ESteamAPIInitResult InitEx(uint unIP, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, string pchVersionString, out string OutSteamErrMsg) {
InteropHelp.TestIfPlatformSupported();

using (var pchVersionString2 = new InteropHelp.UTF8StringHandle(pchVersionString)) {
var pszInternalCheckInterfaceVersions = new System.Text.StringBuilder();
pszInternalCheckInterfaceVersions.Append(Constants.STEAMUTILS_INTERFACE_VERSION).Append('\0');
pszInternalCheckInterfaceVersions.Append(Constants.STEAMNETWORKINGUTILS_INTERFACE_VERSION).Append('\0');
pszInternalCheckInterfaceVersions.Append(Constants.STEAMGAMESERVER_INTERFACE_VERSION).Append('\0');
pszInternalCheckInterfaceVersions.Append(Constants.STEAMGAMESERVERSTATS_INTERFACE_VERSION).Append('\0');
pszInternalCheckInterfaceVersions.Append(Constants.STEAMHTTP_INTERFACE_VERSION).Append('\0');
pszInternalCheckInterfaceVersions.Append(Constants.STEAMINVENTORY_INTERFACE_VERSION).Append('\0');
pszInternalCheckInterfaceVersions.Append(Constants.STEAMNETWORKING_INTERFACE_VERSION).Append('\0');
pszInternalCheckInterfaceVersions.Append(Constants.STEAMNETWORKINGMESSAGES_INTERFACE_VERSION).Append('\0');
pszInternalCheckInterfaceVersions.Append(Constants.STEAMNETWORKINGSOCKETS_INTERFACE_VERSION).Append('\0');
pszInternalCheckInterfaceVersions.Append(Constants.STEAMUGC_INTERFACE_VERSION).Append('\0');

using (var pchVersionString2 = new InteropHelp.UTF8StringHandle(pchVersionString))
using (var pszInternalCheckInterfaceVersions2 = new InteropHelp.UTF8StringHandle(pszInternalCheckInterfaceVersions.ToString())) {
IntPtr SteamErrorMsgPtr = Marshal.AllocHGlobal(Constants.k_cchMaxSteamErrMsg);
ESteamAPIInitResult initResult = NativeMethods.SteamInternal_GameServer_Init_V2(unIP, 0, usGamePort, usQueryPort, eServerMode, pchVersionString2, IntPtr.Zero, SteamErrorMsgPtr);
string SteamErrorMsg = InteropHelp.PtrToStringUTF8(SteamErrorMsgPtr);
ESteamAPIInitResult initResult = NativeMethods.SteamInternal_GameServer_Init_V2(unIP, usGamePort, usQueryPort, eServerMode, pchVersionString2, pszInternalCheckInterfaceVersions2, SteamErrorMsgPtr);
OutSteamErrMsg = InteropHelp.PtrToStringUTF8(SteamErrorMsgPtr);
Marshal.FreeHGlobal(SteamErrorMsgPtr);

if (initResult != ESteamAPIInitResult.k_ESteamAPIInitResult_OK)
// Steamworks.NET specific: We initialize the SteamAPI Context like this for now, but we need to do it
// every time that Unity reloads binaries, so we also check if the pointers are available and initialized
// before each call to any interface functions. That is in InteropHelp.cs
if (initResult == ESteamAPIInitResult.k_ESteamAPIInitResult_OK)
{
return false;
bool ret = CSteamGameServerAPIContext.Init();
if (ret) {
CallbackDispatcher.Initialize();
}
else {
initResult = ESteamAPIInitResult.k_ESteamAPIInitResult_FailedGeneric;
OutSteamErrMsg = "[Steamworks.NET] Failed to initialize CSteamAPIContext";
}
}
}

// Steamworks.NET specific: We initialize the SteamAPI Context like this for now, but we need to do it
// every time that Unity reloads binaries, so we also check if the pointers are available and initialized
// before each call to any interface functions. That is in InteropHelp.cs
bool ret = CSteamGameServerAPIContext.Init();
if (!ret) {
return false;
return initResult;
}
}

CallbackDispatcher.Initialize();
// This function is included for compatibility with older SDK.
// You can use it if you don't care about decent error handling
public static bool Init(uint unIP, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, string pchVersionString) {
InteropHelp.TestIfPlatformSupported();

return true;
string SteamErrorMsg;
return InitEx(unIP, usGamePort, usQueryPort, eServerMode, pchVersionString, out SteamErrorMsg) == ESteamAPIInitResult.k_ESteamAPIInitResult_OK;
}

// Shutdown SteamGameSeverXxx interfaces, log out, and free resources.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ internal static class NativeMethods {

#region steam_api.h
[DllImport(NativeLibraryName, EntryPoint = "SteamInternal_SteamAPI_Init", CallingConvention = CallingConvention.Cdecl)]
public static extern ESteamAPIInitResult SteamInternal_SteamAPI_Init(IntPtr pszInternalCheckInterfaceVersions, IntPtr pOutErrMsg);
public static extern ESteamAPIInitResult SteamInternal_SteamAPI_Init(InteropHelp.UTF8StringHandle pszInternalCheckInterfaceVersions, IntPtr pOutErrMsg);

[DllImport(NativeLibraryName, EntryPoint = "SteamAPI_Shutdown", CallingConvention = CallingConvention.Cdecl)]
public static extern void SteamAPI_Shutdown();
Expand Down Expand Up @@ -155,7 +155,7 @@ internal static class NativeMethods {
public static extern int SteamGameServer_GetHSteamUser();

[DllImport(NativeLibraryName, EntryPoint = "SteamInternal_GameServer_Init_V2", CallingConvention = CallingConvention.Cdecl)]
public static extern ESteamAPIInitResult SteamInternal_GameServer_Init_V2(uint unIP, ushort usPort, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, InteropHelp.UTF8StringHandle pchVersionString, IntPtr pszInternalCheckInterfaceVersions, IntPtr pOutErrMsg);
public static extern ESteamAPIInitResult SteamInternal_GameServer_Init_V2(uint unIP, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, InteropHelp.UTF8StringHandle pchVersionString, InteropHelp.UTF8StringHandle pszInternalCheckInterfaceVersions, IntPtr pOutErrMsg);
#endregion
#region SteamAPI Accessors
[DllImport(NativeLibraryName, EntryPoint = "SteamClient", CallingConvention = CallingConvention.Cdecl)]
Expand Down

0 comments on commit 3db2bfa

Please sign in to comment.