StationObscurum/Assets/com.rlabrecque.steamworks.net/Runtime/InteropHelp.cs

268 lines
8.1 KiB
C#
Raw Normal View History

2023-11-13 03:08:23 +01:00
// This file is provided under The MIT License as part of Steamworks.NET.
// Copyright (c) 2013-2022 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_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX)
#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);
}
public static string ByteArrayToStringUTF8(byte[] buffer) {
int length = 0;
while (length < buffer.Length && buffer[length] != 0) {
length++;
}
return Encoding.UTF8.GetString(buffer, 0, length);
}
public static void StringToByteArrayUTF8(string str, byte[] outArrayBuffer, int outArrayBufferSize)
{
outArrayBuffer = new byte[outArrayBufferSize];
int length = Encoding.UTF8.GetBytes(str, 0, str.Length, outArrayBuffer, 0);
outArrayBuffer[length] = 0;
}
// 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<string> 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() {
if (m_Strings != null) {
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
/// <summary>
/// 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.
/// </summary>
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