From 3db2bfaedee6cfd421c77b108b1d792c0461fc8d Mon Sep 17 00:00:00 2001 From: Riley Labrecque Date: Sun, 28 Jul 2024 19:02:28 -0700 Subject: [PATCH] Fix initializing on GameServers and added InitEx for them (Fixes #632, 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 --- CodeGen/templates/nativemethods.txt | 4 +- .../Runtime/Steam.cs | 119 +++++++++++++----- .../Runtime/autogen/NativeMethods.cs | 4 +- 3 files changed, 90 insertions(+), 37 deletions(-) diff --git a/CodeGen/templates/nativemethods.txt b/CodeGen/templates/nativemethods.txt index 5f170556..4cba12e9 100644 --- a/CodeGen/templates/nativemethods.txt +++ b/CodeGen/templates/nativemethods.txt @@ -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(); @@ -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)] diff --git a/com.rlabrecque.steamworks.net/Runtime/Steam.cs b/com.rlabrecque.steamworks.net/Runtime/Steam.cs index 24af0f43..4cb90518 100644 --- a/com.rlabrecque.steamworks.net/Runtime/Steam.cs +++ b/com.rlabrecque.steamworks.net/Runtime/Steam.cs @@ -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. @@ -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. diff --git a/com.rlabrecque.steamworks.net/Runtime/autogen/NativeMethods.cs b/com.rlabrecque.steamworks.net/Runtime/autogen/NativeMethods.cs index c91db23e..1aa54797 100644 --- a/com.rlabrecque.steamworks.net/Runtime/autogen/NativeMethods.cs +++ b/com.rlabrecque.steamworks.net/Runtime/autogen/NativeMethods.cs @@ -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(); @@ -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)]