add steam

This commit is contained in:
_nebula 2023-06-09 23:57:11 +01:00
parent b4a6280e3d
commit ca99454139
11 changed files with 882 additions and 7 deletions

View File

@ -0,0 +1,88 @@
using System.Collections;
using System.Collections.Generic;
namespace Mirror.FizzySteam;
public class BidirectionalDictionary<T1, T2> : IEnumerable
{
private Dictionary<T1, T2> t1ToT2Dict = new Dictionary<T1, T2>();
private Dictionary<T2, T1> t2ToT1Dict = new Dictionary<T2, T1>();
public IEnumerable<T1> FirstTypes => t1ToT2Dict.Keys;
public IEnumerable<T2> SecondTypes => t2ToT1Dict.Keys;
public IEnumerator GetEnumerator() => t1ToT2Dict.GetEnumerator();
public int Count => t1ToT2Dict.Count;
public void Add(T1 key, T2 value)
{
if (t1ToT2Dict.ContainsKey(key))
{
Remove(key);
}
t1ToT2Dict[key] = value;
t2ToT1Dict[value] = key;
}
public void Add(T2 key, T1 value)
{
if (t2ToT1Dict.ContainsKey(key))
{
Remove(key);
}
t2ToT1Dict[key] = value;
t1ToT2Dict[value] = key;
}
public T2 Get(T1 key) => t1ToT2Dict[key];
public T1 Get(T2 key) => t2ToT1Dict[key];
public bool TryGetValue(T1 key, out T2 value) => t1ToT2Dict.TryGetValue(key, out value);
public bool TryGetValue(T2 key, out T1 value) => t2ToT1Dict.TryGetValue(key, out value);
public bool Contains(T1 key) => t1ToT2Dict.ContainsKey(key);
public bool Contains(T2 key) => t2ToT1Dict.ContainsKey(key);
public void Remove(T1 key)
{
if (Contains(key))
{
T2 val = t1ToT2Dict[key];
t1ToT2Dict.Remove(key);
t2ToT1Dict.Remove(val);
}
}
public void Remove(T2 key)
{
if (Contains(key))
{
T1 val = t2ToT1Dict[key];
t1ToT2Dict.Remove(val);
t2ToT1Dict.Remove(key);
}
}
public T1 this[T2 key]
{
get => t2ToT1Dict[key];
set
{
Add(key, value);
}
}
public T2 this[T1 key]
{
get => t1ToT2Dict[key];
set
{
Add(key, value);
}
}
}

View File

@ -0,0 +1,228 @@
using Steamworks;
using System;
using UnityEngine;
namespace Mirror.FizzySteam;
public class FizzySteamworks : Transport
{
private const string STEAM_SCHEME = "steam";
private static SteamClient client;
private static SteamServer server;
[SerializeField]
public EP2PSend[] Channels = new EP2PSend[2] { EP2PSend.k_EP2PSendReliable, EP2PSend.k_EP2PSendUnreliableNoDelay };
[Tooltip("Timeout for connecting in seconds.")]
public int Timeout = 25;
private void OnEnable()
{
Debug.Assert(Channels != null && Channels.Length > 0, "No channel configured for FizzySteamworks.");
Invoke(nameof(InitRelayNetworkAccess), 1f);
}
public override void ClientEarlyUpdate()
{
if (enabled)
{
client?.ReceiveData();
}
}
public override void ServerEarlyUpdate()
{
if (enabled)
{
server?.ReceiveData();
}
}
public override void ClientLateUpdate()
{
if (enabled)
{
client?.FlushData();
}
}
public override void ServerLateUpdate()
{
if (enabled)
{
server?.FlushData();
}
}
public override bool ClientConnected() => ClientActive() && client.Connected;
public override void ClientConnect(string address)
{
try
{
SteamNetworkingUtils.InitRelayNetworkAccess();
InitRelayNetworkAccess();
if (ServerActive())
{
Debug.LogError("Transport already running as server!");
return;
}
if (!ClientActive() || client.Error)
{
Debug.Log($"Starting client [SteamSockets], target address {address}.");
client = SteamClient.CreateClient(this, address);
}
else
{
Debug.LogError("Client already running!");
}
}
catch (Exception ex)
{
Debug.LogError("Exception: " + ex.Message + ". Client could not be started.");
OnClientDisconnected.Invoke();
}
}
public override void ClientConnect(Uri uri)
{
if (uri.Scheme != STEAM_SCHEME)
{
throw new ArgumentException($"Invalid url {uri}, use {STEAM_SCHEME}://SteamID instead", nameof(uri));
}
ClientConnect(uri.Host);
}
public override void ClientSend(ArraySegment<byte> segment, int channelId)
{
var data = new byte[segment.Count];
Array.Copy(segment.Array, segment.Offset, data, 0, segment.Count);
client.Send(data, channelId);
}
public override void ClientDisconnect()
{
if (ClientActive())
{
Shutdown();
}
}
public bool ClientActive() => client != null;
public override bool ServerActive() => server != null;
public override void ServerStart()
{
try
{
SteamNetworkingUtils.InitRelayNetworkAccess();
InitRelayNetworkAccess();
if (ClientActive())
{
Debug.LogError("Transport already running as client!");
return;
}
if (!ServerActive())
{
Debug.Log($"Starting server [SteamSockets].");
server = SteamServer.CreateServer(this, NetworkManager.singleton.maxConnections);
}
else
{
Debug.LogError("Server already started!");
}
}
catch (Exception ex)
{
Debug.LogException(ex);
return;
}
}
public override Uri ServerUri()
{
var steamBuilder = new UriBuilder
{
Scheme = STEAM_SCHEME,
Host = SteamUser.GetSteamID().m_SteamID.ToString()
};
return steamBuilder.Uri;
}
public override void ServerSend(int connectionId, ArraySegment<byte> segment, int channelId)
{
if (ServerActive())
{
var data = new byte[segment.Count];
Array.Copy(segment.Array, segment.Offset, data, 0, segment.Count);
server.Send(connectionId, data, channelId);
}
}
public override void ServerDisconnect(int connectionId)
{
if (ServerActive())
{
server.Disconnect(connectionId);
}
}
public override string ServerGetClientAddress(int connectionId) => ServerActive() ? server.ServerGetClientAddress(connectionId) : string.Empty;
public override void ServerStop()
{
if (ServerActive())
{
Shutdown();
}
}
public override void Shutdown()
{
if (server != null)
{
server.Shutdown();
server = null;
Debug.Log("Transport shut down - was server.");
}
if (client != null)
{
client.Disconnect();
client = null;
Debug.Log("Transport shut down - was client.");
}
}
public override int GetMaxPacketSize(int channelId)
=> Constants.k_cbMaxSteamNetworkingSocketsMessageSizeSend;
public override bool Available()
{
try
{
SteamNetworkingUtils.InitRelayNetworkAccess();
return true;
}
catch
{
return false;
}
}
private void InitRelayNetworkAccess()
{
try
{
SteamNetworkingUtils.InitRelayNetworkAccess();
}
catch { }
}
private void OnDestroy()
=> Shutdown();
}

View File

@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<RootNamespace>Mirror.FizzySteam</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Reference Include="com.rlabrecque.steamworks.net">
<HintPath>F:\Steam\steamapps\common\Outer Wilds\OuterWilds_Data\Managed\com.rlabrecque.steamworks.net.dll</HintPath>
</Reference>
<Reference Include="kcp2k">
<HintPath>..\Mirror\kcp2k.dll</HintPath>
</Reference>
<Reference Include="Mirror">
<HintPath>..\Mirror\Mirror.dll</HintPath>
</Reference>
<Reference Include="Mirror.Components">
<HintPath>..\Mirror\Mirror.Components.dll</HintPath>
</Reference>
<Reference Include="Mirror.Transports">
<HintPath>..\Mirror\Mirror.Transports.dll</HintPath>
</Reference>
<Reference Include="Telepathy">
<HintPath>..\Mirror\Telepathy.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>F:\Steam\steamapps\common\Outer Wilds\OuterWilds_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@ -0,0 +1,222 @@
using Steamworks;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
namespace Mirror.FizzySteam
{
public class SteamClient : SteamCommon
{
public bool Connected { get; private set; }
public bool Error { get; private set; }
private TimeSpan ConnectionTimeout;
private event Action<byte[], int> OnReceivedData;
private event Action OnConnected;
private event Action OnDisconnected;
private Callback<SteamNetConnectionStatusChangedCallback_t> c_onConnectionChange = null;
private CancellationTokenSource cancelToken;
private TaskCompletionSource<Task> connectedComplete;
private CSteamID hostSteamID = CSteamID.Nil;
private HSteamNetConnection HostConnection;
private List<Action> BufferedData;
private SteamClient(FizzySteamworks transport)
{
ConnectionTimeout = TimeSpan.FromSeconds(Math.Max(1, transport.Timeout));
BufferedData = new List<Action>();
}
public static SteamClient CreateClient(FizzySteamworks transport, string host)
{
var c = new SteamClient(transport);
c.OnConnected += () => transport.OnClientConnected.Invoke();
c.OnDisconnected += () => transport.OnClientDisconnected.Invoke();
c.OnReceivedData += (data, ch) => transport.OnClientDataReceived.Invoke(new ArraySegment<byte>(data), ch);
try
{
SteamNetworkingUtils.InitRelayNetworkAccess();
c.Connect(host);
}
catch (Exception ex)
{
Debug.LogException(ex);
c.OnConnectionFailed();
}
return c;
}
private async void Connect(string host)
{
cancelToken = new CancellationTokenSource();
c_onConnectionChange = Callback<SteamNetConnectionStatusChangedCallback_t>.Create(OnConnectionStatusChanged);
try
{
hostSteamID = new CSteamID(ulong.Parse(host));
connectedComplete = new TaskCompletionSource<Task>();
OnConnected += SetConnectedComplete;
var smi = new SteamNetworkingIdentity();
smi.SetSteamID(hostSteamID);
var options = new SteamNetworkingConfigValue_t[] { };
HostConnection = SteamNetworkingSockets.ConnectP2P(ref smi, 0, options.Length, options);
Task connectedCompleteTask = connectedComplete.Task;
var timeOutTask = Task.Delay(ConnectionTimeout, cancelToken.Token);
if (await Task.WhenAny(connectedCompleteTask, timeOutTask) != connectedCompleteTask)
{
if (cancelToken.IsCancellationRequested)
{
Debug.LogError($"The connection attempt was cancelled.");
}
else if (timeOutTask.IsCompleted)
{
Debug.LogError($"Connection to {host} timed out.");
}
OnConnected -= SetConnectedComplete;
OnConnectionFailed();
}
OnConnected -= SetConnectedComplete;
}
catch (FormatException)
{
Debug.LogError($"Connection string was not in the right format. Did you enter a SteamId?");
Error = true;
OnConnectionFailed();
}
catch (Exception ex)
{
Debug.LogError(ex.Message);
Error = true;
OnConnectionFailed();
}
finally
{
if (Error)
{
Debug.LogError("Connection failed.");
OnConnectionFailed();
}
}
}
private void OnConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t param)
{
var clientSteamID = param.m_info.m_identityRemote.GetSteamID64();
if (param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_Connected)
{
Connected = true;
OnConnected.Invoke();
Debug.Log("Connection established.");
if (BufferedData.Count > 0)
{
Debug.Log($"{BufferedData.Count} received before connection was established. Processing now.");
{
foreach (var a in BufferedData)
{
a();
}
}
}
}
else if (param.m_info.m_eState is ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ClosedByPeer or ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ProblemDetectedLocally)
{
Debug.Log($"Connection was closed by peer, {param.m_info.m_szEndDebug}");
Disconnect();
}
else
{
Debug.Log($"Connection state changed: {param.m_info.m_eState} - {param.m_info.m_szEndDebug}");
}
}
public void Disconnect()
{
cancelToken?.Cancel();
Dispose();
if (HostConnection.m_HSteamNetConnection != 0)
{
Debug.Log("Sending Disconnect message");
SteamNetworkingSockets.CloseConnection(HostConnection, 0, "Graceful disconnect", false);
HostConnection.m_HSteamNetConnection = 0;
}
}
protected void Dispose()
{
if (c_onConnectionChange != null)
{
c_onConnectionChange.Dispose();
c_onConnectionChange = null;
}
}
private void InternalDisconnect()
{
Connected = false;
OnDisconnected.Invoke();
Debug.Log("Disconnected.");
SteamNetworkingSockets.CloseConnection(HostConnection, 0, "Disconnected", false);
}
public void ReceiveData()
{
var ptrs = new IntPtr[MAX_MESSAGES];
int messageCount;
if ((messageCount = SteamNetworkingSockets.ReceiveMessagesOnConnection(HostConnection, ptrs, MAX_MESSAGES)) > 0)
{
for (var i = 0; i < messageCount; i++)
{
(var data, var ch) = ProcessMessage(ptrs[i]);
if (Connected)
{
OnReceivedData(data, ch);
}
else
{
BufferedData.Add(() => OnReceivedData(data, ch));
}
}
}
}
public void Send(byte[] data, int channelId)
{
var res = SendSocket(HostConnection, data, channelId);
if (res is EResult.k_EResultNoConnection or EResult.k_EResultInvalidParam)
{
Debug.Log($"Connection to server was lost.");
InternalDisconnect();
}
else if (res != EResult.k_EResultOK)
{
Debug.LogError($"Could not send: {res}");
}
}
private void SetConnectedComplete()
=> connectedComplete.SetResult(connectedComplete.Task);
private void OnConnectionFailed()
=> OnDisconnected.Invoke();
public void FlushData()
=> SteamNetworkingSockets.FlushMessagesOnConnection(HostConnection);
}
}

View File

@ -0,0 +1,42 @@
using Steamworks;
using System;
using System.Runtime.InteropServices;
using UnityEngine;
namespace Mirror.FizzySteam
{
public abstract class SteamCommon
{
protected const int MAX_MESSAGES = 256;
protected EResult SendSocket(HSteamNetConnection conn, byte[] data, int channelId)
{
Array.Resize(ref data, data.Length + 1);
data[data.Length - 1] = (byte)channelId;
GCHandle pinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr pData = pinnedArray.AddrOfPinnedObject();
int sendFlag = channelId == Channels.Unreliable ? Constants.k_nSteamNetworkingSend_Unreliable : Constants.k_nSteamNetworkingSend_Reliable;
EResult res = SteamNetworkingSockets.SendMessageToConnection(conn, pData, (uint)data.Length, sendFlag, out long _);
if (res != EResult.k_EResultOK)
{
Debug.LogWarning($"Send issue: {res}");
}
pinnedArray.Free();
return res;
}
protected (byte[], int) ProcessMessage(IntPtr ptrs)
{
SteamNetworkingMessage_t data = Marshal.PtrToStructure<SteamNetworkingMessage_t>(ptrs);
byte[] managedArray = new byte[data.m_cbSize];
Marshal.Copy(data.m_pData, managedArray, 0, data.m_cbSize);
SteamNetworkingMessage_t.Release(ptrs);
int channel = managedArray[managedArray.Length - 1];
Array.Resize(ref managedArray, managedArray.Length - 1);
return (managedArray, channel);
}
}
}

View File

@ -0,0 +1,208 @@
using Steamworks;
using System;
using System.Linq;
using UnityEngine;
namespace Mirror.FizzySteam
{
public class SteamServer : SteamCommon
{
private event Action<int> OnConnected;
private event Action<int, byte[], int> OnReceivedData;
private event Action<int> OnDisconnected;
private event Action<int, TransportError, string> OnReceivedError;
private BidirectionalDictionary<HSteamNetConnection, int> connToMirrorID;
private BidirectionalDictionary<CSteamID, int> steamIDToMirrorID;
private int maxConnections;
private int nextConnectionID;
private HSteamListenSocket listenSocket;
private Callback<SteamNetConnectionStatusChangedCallback_t> c_onConnectionChange = null;
private SteamServer(int maxConnections)
{
this.maxConnections = maxConnections;
connToMirrorID = new BidirectionalDictionary<HSteamNetConnection, int>();
steamIDToMirrorID = new BidirectionalDictionary<CSteamID, int>();
nextConnectionID = 1;
c_onConnectionChange = Callback<SteamNetConnectionStatusChangedCallback_t>.Create(OnConnectionStatusChanged);
}
public static SteamServer CreateServer(FizzySteamworks transport, int maxConnections)
{
SteamServer s = new SteamServer(maxConnections);
s.OnConnected += (id) => transport.OnServerConnected.Invoke(id);
s.OnDisconnected += (id) => transport.OnServerDisconnected.Invoke(id);
s.OnReceivedData += (id, data, ch) => transport.OnServerDataReceived.Invoke(id, new ArraySegment<byte>(data), ch);
s.OnReceivedError += (id, error, reason) => transport.OnServerError.Invoke(id, error, reason);
try
{
SteamNetworkingUtils.InitRelayNetworkAccess();
}
catch (Exception ex)
{
Debug.LogException(ex);
}
s.Host();
return s;
}
private void Host()
{
SteamNetworkingConfigValue_t[] options = new SteamNetworkingConfigValue_t[] { };
listenSocket = SteamNetworkingSockets.CreateListenSocketP2P(0, options.Length, options);
}
private void OnConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t param)
{
ulong clientSteamID = param.m_info.m_identityRemote.GetSteamID64();
if (param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_Connecting)
{
if (connToMirrorID.Count >= maxConnections)
{
Debug.Log($"Incoming connection {clientSteamID} would exceed max connection count. Rejecting.");
SteamNetworkingSockets.CloseConnection(param.m_hConn, 0, "Max Connection Count", false);
return;
}
EResult res;
if ((res = SteamNetworkingSockets.AcceptConnection(param.m_hConn)) == EResult.k_EResultOK)
{
Debug.Log($"Accepting connection {clientSteamID}");
}
else
{
Debug.Log($"Connection {clientSteamID} could not be accepted: {res.ToString()}");
}
}
else if (param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_Connected)
{
int connectionId = nextConnectionID++;
connToMirrorID.Add(param.m_hConn, connectionId);
steamIDToMirrorID.Add(param.m_info.m_identityRemote.GetSteamID(), connectionId);
OnConnected.Invoke(connectionId);
Debug.Log($"Client with SteamID {clientSteamID} connected. Assigning connection id {connectionId}");
}
else if (param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ClosedByPeer || param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ProblemDetectedLocally)
{
if (connToMirrorID.TryGetValue(param.m_hConn, out int connId))
{
InternalDisconnect(connId, param.m_hConn);
}
}
else
{
Debug.Log($"Connection {clientSteamID} state changed: {param.m_info.m_eState.ToString()}");
}
}
private void InternalDisconnect(int connId, HSteamNetConnection socket)
{
OnDisconnected.Invoke(connId);
SteamNetworkingSockets.CloseConnection(socket, 0, "Graceful disconnect", false);
connToMirrorID.Remove(connId);
steamIDToMirrorID.Remove(connId);
Debug.Log($"Client with ConnectionID {connId} disconnected.");
}
public void Disconnect(int connectionId)
{
if (connToMirrorID.TryGetValue(connectionId, out HSteamNetConnection conn))
{
Debug.Log($"Connection id {connectionId} disconnected.");
SteamNetworkingSockets.CloseConnection(conn, 0, "Disconnected by server", false);
steamIDToMirrorID.Remove(connectionId);
connToMirrorID.Remove(connectionId);
OnDisconnected(connectionId);
}
else
{
Debug.LogWarning("Trying to disconnect unknown connection id: " + connectionId);
}
}
public void FlushData()
{
foreach (HSteamNetConnection conn in connToMirrorID.FirstTypes)
{
SteamNetworkingSockets.FlushMessagesOnConnection(conn);
}
}
public void ReceiveData()
{
foreach (HSteamNetConnection conn in connToMirrorID.FirstTypes.ToList())
{
if (connToMirrorID.TryGetValue(conn, out int connId))
{
IntPtr[] ptrs = new IntPtr[MAX_MESSAGES];
int messageCount;
if ((messageCount = SteamNetworkingSockets.ReceiveMessagesOnConnection(conn, ptrs, MAX_MESSAGES)) > 0)
{
for (int i = 0; i < messageCount; i++)
{
(byte[] data, int ch) = ProcessMessage(ptrs[i]);
OnReceivedData(connId, data, ch);
}
}
}
}
}
public void Send(int connectionId, byte[] data, int channelId)
{
if (connToMirrorID.TryGetValue(connectionId, out HSteamNetConnection conn))
{
EResult res = SendSocket(conn, data, channelId);
if (res == EResult.k_EResultNoConnection || res == EResult.k_EResultInvalidParam)
{
Debug.Log($"Connection to {connectionId} was lost.");
InternalDisconnect(connectionId, conn);
}
else if (res != EResult.k_EResultOK)
{
Debug.LogError($"Could not send: {res.ToString()}");
}
}
else
{
Debug.LogError("Trying to send on unknown connection: " + connectionId);
OnReceivedError.Invoke(connectionId, TransportError.Unexpected, "ERROR Unknown Connection");
}
}
public string ServerGetClientAddress(int connectionId)
{
if (steamIDToMirrorID.TryGetValue(connectionId, out CSteamID steamId))
{
return steamId.ToString();
}
else
{
Debug.LogError("Trying to get info on unknown connection: " + connectionId);
OnReceivedError.Invoke(connectionId, TransportError.Unexpected, "ERROR Unknown Connection");
return string.Empty;
}
}
public void Shutdown()
{
SteamNetworkingSockets.CloseListenSocket(listenSocket);
if (c_onConnectionChange != null)
{
c_onConnectionChange.Dispose();
c_onConnectionChange = null;
}
}
}
}

View File

@ -15,6 +15,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MirrorWeaver", "MirrorWeaver\MirrorWeaver.csproj", "{DA8A467E-15BA-456C-9034-6EB80BAF1FF9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FizzySteamworks", "FizzySteamworks\FizzySteamworks.csproj", "{D47034D8-B92D-47DA-884C-C76F735E2D5D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -29,6 +31,10 @@ Global
{DA8A467E-15BA-456C-9034-6EB80BAF1FF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA8A467E-15BA-456C-9034-6EB80BAF1FF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA8A467E-15BA-456C-9034-6EB80BAF1FF9}.Release|Any CPU.Build.0 = Release|Any CPU
{D47034D8-B92D-47DA-884C-C76F735E2D5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D47034D8-B92D-47DA-884C-C76F735E2D5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D47034D8-B92D-47DA-884C-C76F735E2D5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D47034D8-B92D-47DA-884C-C76F735E2D5D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -7,6 +7,7 @@ using QSB.SaveSync;
using QSB.SaveSync.Messages;
using QSB.Utility;
using QSB.WorldSync;
using Steamworks;
using System;
using System.Linq;
using System.Text;
@ -634,22 +635,22 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
if (!QSBCore.UseKcpTransport)
{
/*var productUserId = EOSSDKComponent.LocalUserProductIdString;
var steamUserId = SteamUser.GetSteamID().ToString();
PopupClose += confirm =>
{
if (confirm)
{
GUIUtility.systemCopyBuffer = productUserId;
GUIUtility.systemCopyBuffer = steamUserId;
}
LoadGame(PlayerData.GetWarpedToTheEye());
Delay.RunWhen(() => TimeLoop._initialized, QSBNetworkManager.singleton.StartHost);
};
OpenInfoPopup(string.Format(QSBLocalization.Current.CopyProductUserIDToClipboard, productUserId)
OpenInfoPopup(string.Format(QSBLocalization.Current.CopyProductUserIDToClipboard, steamUserId)
, QSBLocalization.Current.Yes
, QSBLocalization.Current.No);*/
, QSBLocalization.Current.No);
}
else
{

View File

@ -72,6 +72,7 @@
<PackageReference Include="OWML" Version="2.9.0" IncludeAssets="compile" />
<Reference Include="..\Mirror\*.dll" />
<Reference Include="..\UniTask\*.dll" />
<ProjectReference Include="..\FizzySteamworks\FizzySteamworks.csproj" />
<ProjectReference Include="..\MirrorWeaver\MirrorWeaver.csproj" ReferenceOutputAssembly="false" />
</ItemGroup>
</Project>

View File

@ -11,6 +11,7 @@ using QSB.SaveSync;
using QSB.ServerSettings;
using QSB.Utility;
using QSB.WorldSync;
using Steamworks;
using System;
using System.Collections.Generic;
using System.IO;
@ -110,9 +111,11 @@ public class QSBCore : ModBehaviour
DebugLog.ToConsole($"FATAL - Could not determine game vendor.", MessageType.Fatal);
}
DebugLog.DebugWrite($"Determined game vendor as {GameVendor}", MessageType.Info);
DebugLog.ToConsole($"Determined game vendor as {GameVendor}", MessageType.Info);
}
private bool _steamworksInitialized;
public void Awake()
{
// no, we cant localize this - languages are loaded after the splash screen
@ -123,6 +126,39 @@ public class QSBCore : ModBehaviour
QSBPatchManager.Init();
QSBPatchManager.DoPatchType(QSBPatchTypes.OnModStart);
if (GameVendor != GameVendor.Steam)
{
DebugLog.ToConsole($"Not steam, initializing Steamworks...");
if (!Packsize.Test())
{
DebugLog.ToConsole("[Steamworks.NET] Packsize Test returned false, the wrong version of Steamworks.NET is being run in this platform.", MessageType.Error);
}
if (!DllCheck.Test())
{
DebugLog.ToConsole("[Steamworks.NET] DllCheck Test returned false, One or more of the Steamworks binaries seems to be the wrong version.", MessageType.Error);
}
System.Environment.SetEnvironmentVariable("SteamAppId", "480");
System.Environment.SetEnvironmentVariable("SteamGameId", "480");
if (!SteamAPI.Init())
{
DebugLog.ToConsole($"FATAL - SteamAPI.Init() failed. Refer to Valve's documentation.", MessageType.Fatal);
}
_steamworksInitialized = true;
}
}
public void OnDestroy()
{
if (_steamworksInitialized)
{
SteamAPI.Shutdown();
}
}
public void Start()
@ -282,6 +318,11 @@ public class QSBCore : ModBehaviour
DebugLog.ToConsole($"DEBUG MODE = {DebugSettings.DebugMode}");
}
if (_steamworksInitialized)
{
SteamAPI.RunCallbacks();
}
}
private void CheckCompatibilityMods()

View File

@ -1,5 +1,6 @@
using Epic.OnlineServices.Logging;
using Mirror;
using Mirror.FizzySteam;
using OWML.Common;
using OWML.Utils;
using QSB.Anglerfish.TransformSync;
@ -67,6 +68,7 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
private (TransportError error, string reason) _lastTransportError = (TransportError.Unexpected, "transport did not give an error. uh oh");
private static kcp2k.KcpTransport _kcpTransport;
private static FizzySteamworks _steamTransport;
public override void Awake()
{
@ -76,7 +78,11 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
_kcpTransport = gameObject.AddComponent<kcp2k.KcpTransport>();
}
transport = QSBCore.UseKcpTransport ? _kcpTransport : null;
{
_steamTransport = gameObject.AddComponent<FizzySteamworks>();
}
transport = QSBCore.UseKcpTransport ? _kcpTransport : _steamTransport;
gameObject.SetActive(true);
@ -147,7 +153,7 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
}
if (singleton != null)
{
singleton.transport = Transport.active = QSBCore.UseKcpTransport ? _kcpTransport : null;
singleton.transport = Transport.active = QSBCore.UseKcpTransport ? _kcpTransport : _steamTransport;
}
if (MenuManager.Instance != null)
{