This commit is contained in:
James McGhee 2022-10-02 22:09:42 +01:00 коммит произвёл GitHub
Родитель 9a480a5863
Коммит fddadc8364
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
17 изменённых файлов: 693 добавлений и 9 удалений

Просмотреть файл

@ -27,6 +27,7 @@ Check our [contribution guidelines](CONTRIBUTING.md) for information on how to c
|**[Enet](/Transports/com.community.netcode.transport.enet)**| Desktop, Mobile\* | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|**[LiteNetLib](/Transports/com.community.netcode.transport.litenetlib)**| Desktop, Mobile | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|**[SteamNetworking](/Transports/com.community.netcode.transport.steamnetworking)**| Steam | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|**[SteamNetworkingSockets](/Transports/com.community.netcode.transport.steamnetworkingsockets)**| Steam | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|**[WebSocket](/Transports/com.community.netcode.transport.websocket)**| Desktop, Mobile, WebGL | :heavy_check_mark: | :heavy_check_mark:||
|**[Photon Realtime](/Transports/com.community.netcode.transport.photon-realtime)**| Desktop, Mobile, WebGL\** | :heavy_check_mark: | :heavy_check_mark: | |
|**[Facepunch](/Transports/com.community.netcode.transport.facepunch)**| Steam | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |

Просмотреть файл

@ -16,7 +16,7 @@ The SteamNetworking Transport leverages Valve's SteamNetworking APIs enabling se
This transport does require that you first initalize the Steam API before use. To do so you will need to either
- Author your own initalization logic using the documentation provided by [Steamworks.NET](https://github.com/rlabrecque/Steamworks.NET)
- Use a 3rd party solution such as [Steamworks V2 Foundaiton (free)](https://assetstore.unity.com/packages/tools/integration/steamworks-v2-foundation-186949) or [Steamworks V2 Complete (paid)](https://assetstore.unity.com/packages/tools/integration/steamworks-v2-complete-190316) or comparable solution
- Use a 3rd party solution such as [Steamworks Foundaiton (lite & free)](https://github.com/heathen-engineering/SteamworksFoundation) or [Steamworks Complete (full & paid)](https://www.heathen.group/steamworks) or comparable solution
- Use the example SteamManager from [Steamworks.NET](https://github.com/rlabrecque/Steamworks.NET) **NOTE This is not recomended as the SteamManager does not support Steam Game Server and is very limited in funcitonlity, it can however be a good learning tool for creating your own logic**

Просмотреть файл

@ -252,7 +252,7 @@ namespace Netcode.Transports
connectedUsers.Remove(clientId);
#if UNITY_SERVER
SteamGameServerNetworking.CloseP2PSessionWithUser(remoteId);
SteamGameServerNetworking.CloseP2PSessionWithUser(remoteId);
#else
SteamNetworking.CloseP2PSessionWithUser(remoteId);
#endif
@ -264,7 +264,7 @@ namespace Netcode.Transports
if (isServer)
{
#if UNITY_SERVER
SteamGameServerNetworking.SendP2PPacket(remoteId, new byte[] { 0 }, 1, EP2PSend.k_EP2PSendReliable, (int)InternalChannelType.Connect);
SteamGameServerNetworking.SendP2PPacket(remoteId, new byte[] { 0 }, 1, EP2PSend.k_EP2PSendReliable, (int)InternalChannelType.Connect);
#else
SteamNetworking.SendP2PPacket(remoteId, new byte[] { 0 }, 1, EP2PSend.k_EP2PSendReliable, (int)InternalChannelType.Connect);
#endif
@ -290,7 +290,7 @@ namespace Netcode.Transports
pingPongMessageBuffer[0] = messageBuffer[0];
#if UNITY_SERVER
SteamGameServerNetworking.SendP2PPacket(remoteId, pingPongMessageBuffer, msgSize, EP2PSend.k_EP2PSendUnreliableNoDelay, (int)InternalChannelType.Pong);
SteamGameServerNetworking.SendP2PPacket(remoteId, pingPongMessageBuffer, msgSize, EP2PSend.k_EP2PSendUnreliableNoDelay, (int)InternalChannelType.Pong);
#else
SteamNetworking.SendP2PPacket(remoteId, pingPongMessageBuffer, msgSize, EP2PSend.k_EP2PSendUnreliableNoDelay, (int)InternalChannelType.Pong);
#endif
@ -302,7 +302,8 @@ namespace Netcode.Transports
uint pingValue = sentPings[messageBuffer[0]].getPingTime();
if (isServer)
{
connectedUsers[remoteId.m_SteamID].Ping.SetPing(pingValue);
if (connectedUsers.ContainsKey(remoteId.m_SteamID))
connectedUsers[remoteId.m_SteamID].Ping.SetPing(pingValue);
}
else
{
@ -313,9 +314,18 @@ namespace Netcode.Transports
break;
case (byte)InternalChannelType.NetcodeData:
payload = new ArraySegment<byte>(messageBuffer, 0, (int)msgSize);
receiveTime = Time.realtimeSinceStartup;
return NetworkEvent.Data;
if (connectedUsers.ContainsKey(clientId))
{
payload = new ArraySegment<byte>(messageBuffer, 0, (int)msgSize);
receiveTime = Time.realtimeSinceStartup;
return NetworkEvent.Data;
}
else
{
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
NetworkLog.LogInfoServer(nameof(SteamNetworkingTransport) + " - PollEvent - Recieved a message from an unknown user with clientId: " + clientId);
}
break;
default:
throw new InvalidOperationException();
}
@ -573,6 +583,39 @@ namespace Netcode.Transports
await Task.Delay(TimeSpan.FromSeconds(PingInterval));
}
}
private void OnDestroy()
{
try
{
if (connectedUsers != null && connectedUsers.Count > 0)
{
foreach (User user in connectedUsers.Values)
{
#if UNITY_SERVER
SteamGameServerNetworking.CloseP2PSessionWithUser(user.SteamId);
#else
SteamNetworking.CloseP2PSessionWithUser(user.SteamId);
#endif
}
connectedUsers.Clear();
}
if (serverUser != null)
{
#if UNITY_SERVER
SteamGameServerNetworking.CloseP2PSessionWithUser(serverUser.SteamId);
#else
SteamNetworking.CloseP2PSessionWithUser(serverUser.SteamId);
#endif
}
}
catch(Exception ex)
{
UnityEngine.Debug.LogError("Failed to properly close network sessions: " + ex.Message);
}
}
}
}
#endif

Просмотреть файл

@ -5,7 +5,7 @@
"unity": "2020.3",
"description": "SteamNetworking Transport for NetCode for GameObjects with support for both peer to peer and client server architectures. Derived from SteamAPI originally authored by Petter Vernersson",
"author": {
"name": "Heathen Engineering",
"name": "Heathen Group",
"url": "https://assetstore.unity.com/publishers/5836"
}
}

Просмотреть файл

@ -0,0 +1,31 @@
# Changelog
All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
v2.0.0 submitted by [Heathen Engineering](https://assetstore.unity.com/publishers/5836). The objective of these changes is to allow this transport to
1. Work with any implamentation of [Steamworks.NET](https://github.com/rlabrecque/Steamworks.NET) including [Heathen's Steamworks V2](https://assetstore.unity.com/packages/tools/integration/steamworks-v2-complete-190316)
2. To enable this transport to be used in both Peer to Peer and Client Server architectures
The [Heathen Assets Discord](https://discord.gg/6X3xrRc) server can be used to ask any questions regarding Heathen's modifications or to see community support with Heathen related Steam integration and Steam networking questions
## [2.0.1] - 2021-01-06
### Fixed
- Fixed a bug in the internal channel implementation which did not allow Netcode for GameObject to send any data over the transport.
## [2.0.0] - 2021-11-25
### Add
- Added support for Steam Game Server Networking APIs
### Changed
- Transport is now named SteamNetworkingTransport as it is no longer limited to peer to peer architectures
- Namespace simplified to Netcode.Transports
- Updated all API calls to test for platform, in the case of UNITY_SERVER being defined the transport will use the SteamGameServerNetworking APIs otherwise it will use the client equivelent SteamNetworking APIs
### Removed
- dependency on SteamManager and SteamManager code has been removed. This makes it easier for users to use whatever initalization logic the user wishes including SteamManager but also custom logic and 3rd party logic such as SteamworksBehaviour from [Heathen's Steamworks V2](https://assetstore.unity.com/packages/tools/integration/steamworks-v2-complete-190316)
- pre-packaged Steamworks.NET; this being removed allows the user to use whatever version they please including other 3rd party extensions such as [Heathen's Steamworks V2](https://assetstore.unity.com/packages/tools/integration/steamworks-v2-complete-190316)
- Removed unused and unessisary Client API calls such as calls to SteamUser in various debug log messages
## 1.0.0
First version of the Steam transport as a Unity package.

Просмотреть файл

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 217833d4ffbc2834191c103e3637b0f7
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
MIT License
Copyright (c) 2021 Unity Technologies
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Просмотреть файл

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 4eb039928356500468c82ad21fb735c6
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,23 @@
# SteamNetworkingSockets Transport for Unity NetCode for GameObjects
The SteamNetworkingSockets Transport leverages Valve's SteamNetworkingSockets APIs enabling secure and efficent networking in both peer to peer and client server architectures. The Steam networking sockets APIs address via CSteamID, not IP/Port. These APIs handle routing via Valve's backend services and do not require NAT punch or additional routing solutions.
## Dependencies
**[Steamworks.NET](https://github.com/rlabrecque/Steamworks.NET)** This transport relies on Steamworks.NET to communicate with the **[Steamworks API](https://partner.steamgames.com/doc/sdk)**.
**[Steamworks.NET](https://github.com/rlabrecque/Steamworks.NET) its self requires .Net 4.x**
## Set Up
1. Install [Steamworks.NET](https://github.com/rlabrecque/Steamworks.NET) via the package manager by clicking the '+' (plus) button located in the upper left of the window and selecting `Add package from git URL...` when prompted provide the following URL:
`https://github.com/rlabrecque/Steamworks.NET.git?path=/com.rlabrecque.steamworks.net`
2. Install this package via the package manager by clicking the '+' (plus) button located in the upper left of the window and selecting `Add package from git URL...` when prompted provide the following URL:
`https://github.com/Unity-Technologies/multiplayer-community-contributions.git?path=/Transports/com.community.netcode.transport.steamnetworkingsockets`
## Usage
This transport does require that you first initalize the Steam API before use. To do so you will need to either
- Author your own initalization logic using the documentation provided by [Steamworks.NET](https://github.com/rlabrecque/Steamworks.NET)
- Use a 3rd party solution such as [Steamworks Foundaiton (lite & free)](https://github.com/heathen-engineering/SteamworksFoundation) or [Steamworks Complete (full & paid)](https://www.heathen.group/steamworks) or comparable solution
- Use the example SteamManager from [Steamworks.NET](https://github.com/rlabrecque/Steamworks.NET) **NOTE This is not recomended as the SteamManager does not support Steam Game Server and is very limited in funcitonlity, it can however be a good learning tool for creating your own logic**
Steam Networking Sockets uses the CSteamID as the network address to connect to. For P2P games this would require you to provide the Steam ID of the peer to connect to. For Client Server games this would require you to log your server onto Steam as a Steam Game Server, this act will issue your server a Steam ID which would be used as the address in this transport.

Просмотреть файл

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7a09aff8ae82b434db8621094fa64645
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a8e5e412fec28534c86d8f84fe01a075
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,478 @@
#if !DISABLESTEAMWORKS && STEAMWORKSNET && NETCODEGAMEOBJECTS
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Steamworks;
using System;
using Unity.Netcode;
using Debug = UnityEngine.Debug;
using System.Runtime.InteropServices;
namespace Netcode.Transports
{
public class SteamNetworkingSocketsTransport : NetworkTransport
{
#region Internal Object Model
private class SteamConnectionData
{
internal SteamConnectionData(CSteamID steamId)
{
id = steamId;
}
internal CSteamID id;
internal HSteamNetConnection connection;
}
private Callback<SteamNetConnectionStatusChangedCallback_t> c_onConnectionChange = null;
private HSteamListenSocket listenSocket;
private SteamConnectionData serverUser;
private readonly Dictionary<ulong, SteamConnectionData> connectionMapping = new Dictionary<ulong, SteamConnectionData>();
private readonly Queue<SteamNetConnectionStatusChangedCallback_t> connectionStatusChangeQueue = new Queue<SteamNetConnectionStatusChangedCallback_t>();
private bool isServer = false;
#endregion
public ulong ConnectToSteamID;
public SteamNetworkingConfigValue_t[] options = new SteamNetworkingConfigValue_t[0];
public override ulong ServerClientId => 0;
public override bool IsSupported
{
get
{
try
{
#if UNITY_SERVER
InteropHelp.TestIfAvailableGameServer();
#else
InteropHelp.TestIfAvailableClient();
#endif
return true;
}
catch
{
return false;
}
}
}
public override void DisconnectLocalClient()
{
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer) NetworkLog.LogInfoServer(nameof(SteamNetworkingSocketsTransport) + " - DisconnectLocalClient");
if (connectionMapping.ContainsKey(serverUser.id.m_SteamID))
connectionMapping.Remove(serverUser.id.m_SteamID);
#if UNITY_SERVER
SteamGameServerNetworkingSockets.CloseConnection(serverUser.connection, 0, "Disconnected", false);
#else
SteamNetworkingSockets.CloseConnection(serverUser.connection, 0, "Disconnected", false);
#endif
serverUser = null;
}
public override void DisconnectRemoteClient(ulong clientId)
{
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
NetworkLog.LogInfoServer(nameof(SteamNetworkingSocketsTransport.DisconnectRemoteClient) + " - clientId: " + clientId);
if (!connectionMapping.ContainsKey(clientId))
{
if (NetworkManager.Singleton.LogLevel <= LogLevel.Error)
NetworkLog.LogErrorServer(nameof(SteamNetworkingSocketsTransport) + " - Can't disconect client, client not connected, clientId: " + clientId);
return;
}
#if UNITY_SERVER
SteamGameServerNetworkingSockets.CloseConnection(connectionMapping[clientId].connection, 0, "Disconnected", false);
#else
SteamNetworkingSockets.CloseConnection(connectionMapping[clientId].connection, 0, "Disconnected", false);
#endif
connectionMapping.Remove(clientId);
}
public override ulong GetCurrentRtt(ulong clientId)
{
if (isServer)
{
if (connectionMapping.ContainsKey(clientId))
{
//TODO: We need to figure out how Valve expects you to use ISteamNetworkingUtils ... the issue is no one thought to document WTF a SteamNetworkingPingLocation was or how to get them
return 0ul;
}
else
{
if (NetworkManager.Singleton.LogLevel <= LogLevel.Error)
NetworkLog.LogErrorServer(nameof(SteamNetworkingSocketsTransport) + " - Can't GetCurrentRtt from client, client not connected, clientId: " + clientId);
}
}
else
{
return 0ul;
}
return 0ul;
}
public override void Initialize(NetworkManager networkManager = null)
{
if (!IsSupported)
{
if (NetworkManager.Singleton.LogLevel <= LogLevel.Error)
NetworkLog.LogErrorServer(nameof(SteamNetworkingSocketsTransport) + " - Initialize - Steamworks.NET not ready, " + nameof(SteamNetworkingSocketsTransport) + " can not run without it");
return;
}
}
public override NetworkEvent PollEvent(out ulong clientId, out ArraySegment<byte> payload, out float receiveTime)
{
//Handle any connection state changes we may have
#region Connnection State Changes
while (connectionStatusChangeQueue.Count > 0)
{
var param = connectionStatusChangeQueue.Dequeue();
if (param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_Connecting)
{
//This happens when someone asked to connect to us, in the case of NetCode for GameObject this should only happen if we are a server/host
//the current standard is to blindly accept ... NetCode for GO should really consider a validation model for connections
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
NetworkLog.LogInfoServer(nameof(SteamNetworkingSocketsTransport) + " - connection request from " + param.m_info.m_identityRemote.GetSteamID64());
if (isServer)
{
EResult res;
#if UNITY_SERVER
if ((res = SteamGameServerNetworkingSockets.AcceptConnection(param.m_hConn)) == EResult.k_EResultOK)
#else
if ((res = SteamNetworkingSockets.AcceptConnection(param.m_hConn)) == EResult.k_EResultOK)
#endif
{
if (isServer)
{
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
Debug.Log($"Accepting connection {param.m_info.m_identityRemote.GetSteamID64()}");
clientId = param.m_info.m_identityRemote.GetSteamID64();
payload = new ArraySegment<byte>();
receiveTime = Time.realtimeSinceStartup;
//This should be a new connection, record it
if (connectionMapping.ContainsKey(clientId) == false)
{
var nCon = new SteamConnectionData(param.m_info.m_identityRemote.GetSteamID());
nCon.connection = param.m_hConn;
connectionMapping.Add(clientId, nCon);
}
}
else
{
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
Debug.Log($"Connection {param.m_info.m_identityRemote.GetSteamID64()} could not be accepted: this is not a server");
}
}
else
{
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
Debug.Log($"Connection {param.m_info.m_identityRemote.GetSteamID64()} could not be accepted: {res}");
}
}
}
else if (param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_Connected)
{
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
NetworkLog.LogInfoServer(nameof(SteamNetworkingSocketsTransport) + " - connection request to " + param.m_info.m_identityRemote.GetSteamID64() + " was accepted!");
clientId = param.m_info.m_identityRemote.GetSteamID64();
payload = new ArraySegment<byte>();
receiveTime = Time.realtimeSinceStartup;
//We should already have it but if not record the server connection that was just accepted
if (connectionMapping.ContainsKey(clientId) == false)
{
var nCon = new SteamConnectionData(param.m_info.m_identityRemote.GetSteamID());
nCon.connection = param.m_hConn;
connectionMapping.Add(clientId, nCon);
}
else
{
//Should be redundent but update the conneciton handle anyway
connectionMapping[clientId].connection = param.m_hConn;
}
return NetworkEvent.Connect;
}
else if (param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ClosedByPeer
|| param.m_info.m_eState == ESteamNetworkingConnectionState.k_ESteamNetworkingConnectionState_ProblemDetectedLocally)
{
//The connection is no more
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
NetworkLog.LogInfoServer(nameof(SteamNetworkingSocketsTransport) + $" - connection closed for {param.m_info.m_identityRemote.GetSteamID64()} state responce: {param.m_info.m_eState}");
clientId = param.m_info.m_identityRemote.GetSteamID64();
payload = new ArraySegment<byte>();
receiveTime = Time.realtimeSinceStartup;
//Remove the mapped connection info
if (connectionMapping.ContainsKey(clientId) != false)
connectionMapping.Remove(clientId);
return NetworkEvent.Disconnect;
}
else
{
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
Debug.Log($"Connection {param.m_info.m_identityRemote.GetSteamID64()} state changed: {param.m_info.m_eState}");
}
}
#endregion
foreach (var connectionData in connectionMapping.Values)
{
IntPtr[] ptrs = new IntPtr[1];
int messageCount;
#if UNITY_SERVER
if ((messageCount = SteamGameServerNetworkingSockets.ReceiveMessagesOnConnection(connectionData.connection, ptrs, 1)) > 0)
#else
if ((messageCount = SteamNetworkingSockets.ReceiveMessagesOnConnection(connectionData.connection, ptrs, 1)) > 0)
#endif
{
if (messageCount > 0)
{
clientId = connectionData.id.m_SteamID;
SteamNetworkingMessage_t data = Marshal.PtrToStructure<SteamNetworkingMessage_t>(ptrs[0]);
var buffer = new byte[data.m_cbSize];
Marshal.Copy(data.m_pData, buffer, 0, data.m_cbSize);
payload = buffer;
SteamNetworkingMessage_t.Release(ptrs[0]);
receiveTime = Time.realtimeSinceStartup;
return NetworkEvent.Data;
}
}
}
payload = new ArraySegment<byte>();
clientId = 0;
receiveTime = Time.realtimeSinceStartup;
return NetworkEvent.Nothing;
}
public override void Send(ulong clientId, ArraySegment<byte> segment, NetworkDelivery delivery)
{
if(clientId == 0)
clientId = serverUser.id.m_SteamID;
//Check if we have a mapped user for this ID
if (connectionMapping.ContainsKey(clientId))
{
//Grab a pointer to the user's connection
var connection = connectionMapping[clientId].connection;
//Build a standard array + 1 for the channel
byte[] data = new byte[segment.Count + 1];
Array.Copy(segment.Array, segment.Offset, data, 0, segment.Count);
//The segment count is the last index in our (+1) array, on that last index write a byte indicating the delivery channel
data[segment.Count] = Convert.ToByte((int)delivery);
//Create an unmanaged array and get a pointer to it
GCHandle pinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr pData = pinnedArray.AddrOfPinnedObject();
//Translate the NetworkDelivery (channle) to the Steam QoS send type .. we assume unreliable if nothing matches
int sendFlag = Constants.k_nSteamNetworkingSend_Unreliable;
switch (delivery)
{
case NetworkDelivery.Reliable:
case NetworkDelivery.ReliableFragmentedSequenced:
sendFlag = Constants.k_nSteamNetworkingSend_Reliable;
break;
case NetworkDelivery.ReliableSequenced:
sendFlag = Constants.k_nSteamNetworkingSend_ReliableNoNagle;
break;
case NetworkDelivery.UnreliableSequenced:
sendFlag = Constants.k_nSteamNetworkingSend_UnreliableNoNagle;
break;
}
//Send to the target
#if UNITY_SERVER
EResult responce = SteamGameServerNetworkingSockets.SendMessageToConnection(connection, pData, (uint)data.Length, sendFlag, out long _);
#else
EResult responce = SteamNetworkingSockets.SendMessageToConnection(connection, pData, (uint)data.Length, sendFlag, out long _);
#endif
//Free the unmanaged array
pinnedArray.Free();
//If we had some error report that and move on
if ((responce == EResult.k_EResultNoConnection || responce == EResult.k_EResultInvalidParam)
&& NetworkManager.Singleton.LogLevel <= LogLevel.Normal)
{
Debug.LogWarning($"Connection to server was lost.");
#if UNITY_SERVER
SteamGameServerNetworkingSockets.CloseConnection(connection, 0, "Disconnected", false);
#else
SteamNetworkingSockets.CloseConnection(connection, 0, "Disconnected", false);
#endif
}
else if (responce != EResult.k_EResultOK
&& NetworkManager.Singleton.LogLevel <= LogLevel.Error)
{
Debug.LogError($"Could not send: {responce}");
}
}
else
{
//No client found so report that
if (NetworkManager.Singleton.LogLevel <= LogLevel.Error)
{
Debug.LogError("Trying to send on unknown connection: " + clientId);
NetworkLog.LogErrorServer(nameof(SteamNetworkingSocketsTransport.Send) + " - Trying to send on unknown connection: " + clientId);
}
}
}
public override void Shutdown()
{
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
UnityEngine.Debug.Log(nameof(SteamNetworkingSocketsTransport.Shutdown));
if (isServer)
{
#if UNITY_SERVER
SteamGameServerNetworkingSockets.CloseListenSocket(listenSocket);
#else
SteamNetworkingSockets.CloseListenSocket(listenSocket);
#endif
}
else
{
if (serverUser != null)
{
if (connectionMapping.ContainsKey(serverUser.id.m_SteamID))
connectionMapping.Remove(serverUser.id.m_SteamID);
#if UNITY_SERVER
SteamGameServerNetworkingSockets.CloseConnection(serverUser.connection, 0, "Disconnected", false);
#else
SteamNetworkingSockets.CloseConnection(serverUser.connection, 0, "Disconnected", false);
#endif
}
}
isServer = false;
if (NetworkManager.Singleton != null)
{
//Delay
NetworkManager.Singleton.StartCoroutine(Delay(0.1f, () =>
{
CloseP2PSessions();
}));
}
else
{
CloseP2PSessions();
}
}
public override bool StartClient()
{
if (c_onConnectionChange == null)
c_onConnectionChange = Callback<SteamNetConnectionStatusChangedCallback_t>.Create(OnConnectionStatusChanged);
serverUser = new SteamConnectionData(new CSteamID(ConnectToSteamID));
try
{
#if UNITY_SERVER
SteamGameServerNetworkingUtils.InitRelayNetworkAccess();
#else
SteamNetworkingUtils.InitRelayNetworkAccess();
#endif
SteamNetworkingIdentity smi = new SteamNetworkingIdentity();
smi.SetSteamID(serverUser.id);
#if UNITY_SERVER
serverUser.connection = SteamGameServerNetworkingSockets.ConnectP2P(ref smi, 0, options.Length, options);
#else
serverUser.connection = SteamNetworkingSockets.ConnectP2P(ref smi, 0, options.Length, options);
#endif
connectionMapping.Add(ConnectToSteamID, serverUser);
return true;
}
catch (Exception ex)
{
Debug.LogError("Exception: " + ex.Message + ". Client could not be started.");
return false;
}
}
public override bool StartServer()
{
isServer = true;
if(c_onConnectionChange == null)
c_onConnectionChange = Callback<SteamNetConnectionStatusChangedCallback_t>.Create(OnConnectionStatusChanged);
if (options == null)
options = new SteamNetworkingConfigValue_t[0];
#if UNITY_SERVER
listenSocket = SteamGameServerNetworkingSockets.CreateListenSocketP2P(0, options.Length, options);
#else
listenSocket = SteamNetworkingSockets.CreateListenSocketP2P(0, options.Length, options);
#endif
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
UnityEngine.Debug.Log(nameof(SteamNetworkingSocketsTransport.StartServer));
return true;
}
private void CloseP2PSessions()
{
if (serverUser != null)
{
if(connectionMapping.ContainsKey(serverUser.id.m_SteamID))
connectionMapping.Remove(serverUser.id.m_SteamID);
#if UNITY_SERVER
SteamGameServerNetworkingSockets.CloseConnection(serverUser.connection, 0, "Disconnected", false);
#else
SteamNetworkingSockets.CloseConnection(serverUser.connection, 0, "Disconnected", false);
#endif
}
foreach (SteamConnectionData user in connectionMapping.Values)
{
#if UNITY_SERVER
SteamGameServerNetworkingSockets.CloseConnection(user.connection, 0, "Disconnected", false);
#else
SteamNetworkingSockets.CloseConnection(user.connection, 0, "Disconnected", false);
#endif
}
connectionMapping.Clear();
serverUser = null;
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
UnityEngine.Debug.Log(nameof(SteamNetworkingSocketsTransport) + " - CloseP2PSessions - has Closed P2P Sessions With all Users");
if (c_onConnectionChange != null)
{
c_onConnectionChange.Dispose();
c_onConnectionChange = null;
}
}
private void OnConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t param)
{
connectionStatusChangeQueue.Enqueue(param);
}
private static IEnumerator Delay(float time, Action action)
{
yield return new WaitForSeconds(time);
action.Invoke();
}
}
}
#endif

Просмотреть файл

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fc4ccaff1920208429cca7c350560301
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,34 @@
{
"name": "SteamNetworkingSockets Transport for Netcode for GameObjects",
"rootNamespace": "",
"references": [
"GUID:1491147abca9d7d4bb7105af628b223e",
"GUID:68bd7fdb68ef2684e982e8a9825b18a5"
],
"includePlatforms": [
"Editor",
"LinuxStandalone64",
"macOSStandalone",
"WindowsStandalone32",
"WindowsStandalone64"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.rlabrecque.steamworks.net",
"expression": "",
"define": "STEAMWORKSNET"
},
{
"name": "com.unity.netcode.gameobjects",
"expression": "",
"define": "NETCODEGAMEOBJECTS"
}
],
"noEngineReferences": false
}

Просмотреть файл

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 98d94cfe204587a4f92ed81e64a8e624
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,11 @@
{
"name": "com.community.netcode.transport.steamnetworkingsockets",
"displayName": "SteamNetworkingSockets Transport for NetCode for Gameobjects",
"version": "1.0.0",
"unity": "2020.3",
"description": "SteamNetworkingSockets Transport for NetCode for GameObjects with support for both peer to peer and client server architectures.",
"author": {
"name": "Heathen Group",
"url": "https://assetstore.unity.com/publishers/5836"
}
}

Просмотреть файл

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 553e5c0d0214d5849abdd9a465394696
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: