// This file is provided under The MIT License as part of Steamworks.NET. // Copyright (c) 2013-2019 Riley Labrecque // Please see the included LICENSE.txt for additional information. // This file is automatically generated. // Changes to this file will be reverted when you update Steamworks.NET #if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH #define DISABLESTEAMWORKS #endif #if !DISABLESTEAMWORKS using System.Runtime.InteropServices; using IntPtr = System.IntPtr; using System.Text; namespace Steamworks { public class InteropHelp { public static void TestIfPlatformSupported() { #if !UNITY_EDITOR && !UNITY_STANDALONE && !STEAMWORKS_WIN && !STEAMWORKS_LIN_OSX throw new System.InvalidOperationException("Steamworks functions can only be called on platforms that Steam is available on."); #endif } public static void TestIfAvailableClient() { TestIfPlatformSupported(); if (CSteamAPIContext.GetSteamClient() == System.IntPtr.Zero) { if (!CSteamAPIContext.Init()) { throw new System.InvalidOperationException("Steamworks is not initialized."); } } } public static void TestIfAvailableGameServer() { TestIfPlatformSupported(); if (CSteamGameServerAPIContext.GetSteamClient() == System.IntPtr.Zero) { if (!CSteamGameServerAPIContext.Init()) { throw new System.InvalidOperationException("Steamworks GameServer is not initialized."); } } } // This continues to exist for both 'out string' and strings returned by Steamworks functions. public static string PtrToStringUTF8(IntPtr nativeUtf8) { if (nativeUtf8 == IntPtr.Zero) { return null; } int len = 0; while (Marshal.ReadByte(nativeUtf8, len) != 0) { ++len; } if (len == 0) { return string.Empty; } byte[] buffer = new byte[len]; Marshal.Copy(nativeUtf8, buffer, 0, buffer.Length); return Encoding.UTF8.GetString(buffer); } // This is for 'const char *' arguments which we need to ensure do not get GC'd while Steam is using them. // We can't use an ICustomMarshaler because Unity crashes when a string between 96 and 127 characters long is defined/initialized at the top of class scope... #if UNITY_EDITOR || UNITY_STANDALONE || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX public class UTF8StringHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid { public UTF8StringHandle(string str) : base(true) { if (str == null) { SetHandle(IntPtr.Zero); return; } // +1 for '\0' byte[] strbuf = new byte[Encoding.UTF8.GetByteCount(str) + 1]; Encoding.UTF8.GetBytes(str, 0, str.Length, strbuf, 0); IntPtr buffer = Marshal.AllocHGlobal(strbuf.Length); Marshal.Copy(strbuf, 0, buffer, strbuf.Length); SetHandle(buffer); } protected override bool ReleaseHandle() { if (!IsInvalid) { Marshal.FreeHGlobal(handle); } return true; } } #else public class UTF8StringHandle : IDisposable { public UTF8StringHandle(string str) { } public void Dispose() {} } #endif // TODO - Should be IDisposable // We can't use an ICustomMarshaler because Unity dies when MarshalManagedToNative() gets called with a generic type. public class SteamParamStringArray { // The pointer to each AllocHGlobal() string IntPtr[] m_Strings; // The pointer to the condensed version of m_Strings IntPtr m_ptrStrings; // The pointer to the StructureToPtr version of SteamParamStringArray_t that will get marshaled IntPtr m_pSteamParamStringArray; public SteamParamStringArray(System.Collections.Generic.IList strings) { if (strings == null) { m_pSteamParamStringArray = IntPtr.Zero; return; } m_Strings = new IntPtr[strings.Count]; for (int i = 0; i < strings.Count; ++i) { byte[] strbuf = new byte[Encoding.UTF8.GetByteCount(strings[i]) + 1]; Encoding.UTF8.GetBytes(strings[i], 0, strings[i].Length, strbuf, 0); m_Strings[i] = Marshal.AllocHGlobal(strbuf.Length); Marshal.Copy(strbuf, 0, m_Strings[i], strbuf.Length); } m_ptrStrings = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * m_Strings.Length); SteamParamStringArray_t stringArray = new SteamParamStringArray_t() { m_ppStrings = m_ptrStrings, m_nNumStrings = m_Strings.Length }; Marshal.Copy(m_Strings, 0, stringArray.m_ppStrings, m_Strings.Length); m_pSteamParamStringArray = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SteamParamStringArray_t))); Marshal.StructureToPtr(stringArray, m_pSteamParamStringArray, false); } ~SteamParamStringArray() { foreach (IntPtr ptr in m_Strings) { Marshal.FreeHGlobal(ptr); } if (m_ptrStrings != IntPtr.Zero) { Marshal.FreeHGlobal(m_ptrStrings); } if (m_pSteamParamStringArray != IntPtr.Zero) { Marshal.FreeHGlobal(m_pSteamParamStringArray); } } public static implicit operator IntPtr(SteamParamStringArray that) { return that.m_pSteamParamStringArray; } } } // TODO - Should be IDisposable // MatchMaking Key-Value Pair Marshaller public class MMKVPMarshaller { private IntPtr m_pNativeArray; private IntPtr m_pArrayEntries; public MMKVPMarshaller(MatchMakingKeyValuePair_t[] filters) { if (filters == null) { return; } int sizeOfMMKVP = Marshal.SizeOf(typeof(MatchMakingKeyValuePair_t)); m_pNativeArray = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * filters.Length); m_pArrayEntries = Marshal.AllocHGlobal(sizeOfMMKVP * filters.Length); for (int i = 0; i < filters.Length; ++i) { Marshal.StructureToPtr(filters[i], new IntPtr(m_pArrayEntries.ToInt64() + (i * sizeOfMMKVP)), false); } Marshal.WriteIntPtr(m_pNativeArray, m_pArrayEntries); } ~MMKVPMarshaller() { if (m_pArrayEntries != IntPtr.Zero) { Marshal.FreeHGlobal(m_pArrayEntries); } if (m_pNativeArray != IntPtr.Zero) { Marshal.FreeHGlobal(m_pNativeArray); } } public static implicit operator IntPtr(MMKVPMarshaller that) { return that.m_pNativeArray; } } public class DllCheck { #if DISABLED [DllImport("kernel32.dll")] public static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] extern static int GetModuleFileName(IntPtr hModule, StringBuilder strFullPath, int nSize); #endif /// /// This is an optional runtime check to ensure that the dlls are the correct version. Returns false only if the steam_api.dll is found and it's the wrong size or version number. /// public static bool Test() { #if DISABLED bool ret = CheckSteamAPIDLL(); #endif return true; } #if DISABLED private static bool CheckSteamAPIDLL() { string fileName; int fileBytes; if (IntPtr.Size == 4) { fileName = "steam_api.dll"; fileBytes = Version.SteamAPIDLLSize; } else { fileName = "steam_api64.dll"; fileBytes = Version.SteamAPI64DLLSize; } IntPtr handle = GetModuleHandle(fileName); if (handle == IntPtr.Zero) { return true; } StringBuilder filePath = new StringBuilder(256); GetModuleFileName(handle, filePath, filePath.Capacity); string file = filePath.ToString(); // If we can not find the file we'll just skip it and let the DllNotFoundException take care of it. if (System.IO.File.Exists(file)) { System.IO.FileInfo fInfo = new System.IO.FileInfo(file); if (fInfo.Length != fileBytes) { return false; } if (System.Diagnostics.FileVersionInfo.GetVersionInfo(file).FileVersion != Version.SteamAPIDLLVersion) { return false; } } return true; } #endif } } #endif // !DISABLESTEAMWORKS