Clean up SteamNetworking transports (#190)
This commit is contained in:
Родитель
30e981825b
Коммит
858f6df327
|
@ -26,7 +26,6 @@ Check our [contribution guidelines](CONTRIBUTING.md) for information on how to c
|
|||
| **[Ruffles](/Transports/com.community.netcode.transport.ruffles)**| Desktop, Mobile | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
|**[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: | |
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
# 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.
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9746f0698c7a05240b4f299fc8b3047a
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,9 +0,0 @@
|
|||
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.
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 94dd2752415262347aa0ce728b11fbd4
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,23 +0,0 @@
|
|||
# SteamNetworking Transport for Unity NetCode for GameObjects
|
||||
The SteamNetworking Transport leverages Valve's SteamNetworking APIs enabling secure and efficent networking in both peer to peer and client server architectures. The Steam networking 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.steamnetworking`
|
||||
|
||||
## 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 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.
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8bf956c44ab625349a98b15d1abaa780
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a8e5e412fec28534c86d8f84fe01a075
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,621 +0,0 @@
|
|||
#if !DISABLESTEAMWORKS
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Steamworks;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Unity.Netcode;
|
||||
|
||||
/*
|
||||
* Steamworks API Reference for ISteamNetworking: https://partner.steamgames.com/doc/api/ISteamNetworking
|
||||
* Steamworks.NET: https://steamworks.github.io/
|
||||
*/
|
||||
|
||||
namespace Netcode.Transports
|
||||
{
|
||||
public class SteamNetworkingTransport : NetworkTransport
|
||||
{
|
||||
private Callback<P2PSessionRequest_t> _p2PSessionRequestCallback;
|
||||
private Callback<P2PSessionConnectFail_t> _p2PSessionConnectFailCallback;
|
||||
|
||||
public ulong ConnectToSteamID;
|
||||
|
||||
private class User
|
||||
{
|
||||
public User(CSteamID steamId)
|
||||
{
|
||||
SteamId = steamId;
|
||||
}
|
||||
|
||||
public CSteamID SteamId;
|
||||
public Ping Ping = new Ping();
|
||||
}
|
||||
|
||||
private User serverUser;
|
||||
private Dictionary<ulong, User> connectedUsers = new Dictionary<ulong, User>();
|
||||
private bool isServer = false;
|
||||
|
||||
//holds information for a failed connection attempt to use in poll function to forward the event.
|
||||
private bool connectionAttemptFailed = false;
|
||||
private ulong connectionAttemptFailedClientId;
|
||||
|
||||
private enum InternalChannelType
|
||||
{
|
||||
Connect = 0,
|
||||
Disconnect = 1,
|
||||
Ping = 2,
|
||||
Pong = 3,
|
||||
NetcodeData = 4,
|
||||
InternalChannelsCount = 5,
|
||||
}
|
||||
|
||||
private class Ping
|
||||
{
|
||||
private List<uint> lastPings = new List<uint>();
|
||||
private List<uint> sortedPings = new List<uint>();
|
||||
private uint pingValue = 0;
|
||||
|
||||
public void SetPing(uint ping)
|
||||
{
|
||||
lastPings.Add(ping);
|
||||
sortedPings.Add(ping);
|
||||
|
||||
if (lastPings.Count > 10)
|
||||
{
|
||||
sortedPings.Remove(lastPings[0]);
|
||||
lastPings.RemoveAt(0);
|
||||
}
|
||||
|
||||
sortedPings.Sort();
|
||||
|
||||
pingValue = sortedPings[Mathf.FloorToInt(lastPings.Count / 2)];
|
||||
}
|
||||
|
||||
public uint Get()
|
||||
{
|
||||
return pingValue;
|
||||
}
|
||||
}
|
||||
|
||||
private class PingTracker
|
||||
{
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
|
||||
public PingTracker()
|
||||
{
|
||||
stopwatch.Start();
|
||||
}
|
||||
|
||||
public uint getPingTime()
|
||||
{
|
||||
return (uint)stopwatch.ElapsedMilliseconds;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<byte, PingTracker> sentPings = new Dictionary<byte, PingTracker>(128);
|
||||
private byte pingIdCounter = 0;
|
||||
public readonly double PingInterval = 0.25;
|
||||
private bool sendPings = false;
|
||||
|
||||
byte[] messageBuffer = new byte[1200];
|
||||
byte[] pingPongMessageBuffer = new byte[1];
|
||||
|
||||
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(SteamNetworkingTransport) + " - DisconnectLocalClient");
|
||||
|
||||
#if UNITY_SERVER
|
||||
SteamGameServerNetworking.SendP2PPacket(serverUser.SteamId, new byte[] { 0 }, 1, EP2PSend.k_EP2PSendReliable, (int)InternalChannelType.Disconnect);
|
||||
#else
|
||||
SteamNetworking.SendP2PPacket(serverUser.SteamId, new byte[] { 0 }, 1, EP2PSend.k_EP2PSendReliable, (int)InternalChannelType.Disconnect);
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void DisconnectRemoteClient(ulong clientId)
|
||||
{
|
||||
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer) NetworkLog.LogInfoServer(nameof(SteamNetworkingTransport) + " - DisconnectRemoteClient clientId: " + clientId);
|
||||
|
||||
if (!connectedUsers.ContainsKey(clientId))
|
||||
{
|
||||
if (NetworkManager.Singleton.LogLevel <= LogLevel.Error) NetworkLog.LogErrorServer(nameof(SteamNetworkingTransport) + " - Can't disconect client, client not connected, clientId: " + clientId);
|
||||
return;
|
||||
}
|
||||
|
||||
#if UNITY_SERVER
|
||||
SteamGameServerNetworking.SendP2PPacket(connectedUsers[clientId].SteamId, new byte[] { 0 }, 1, EP2PSend.k_EP2PSendReliable, (int)InternalChannelType.Disconnect);
|
||||
#else
|
||||
SteamNetworking.SendP2PPacket(connectedUsers[clientId].SteamId, new byte[] { 0 }, 1, EP2PSend.k_EP2PSendReliable, (int)InternalChannelType.Disconnect);
|
||||
#endif
|
||||
CSteamID steamId = connectedUsers[clientId].SteamId;
|
||||
|
||||
NetworkManager.Singleton.StartCoroutine(Delay(100, () =>
|
||||
{
|
||||
//Need to delay the closing of the p2p sessions to not block the disconect message before it is sent.
|
||||
#if UNITY_SERVER
|
||||
SteamGameServerNetworking.CloseP2PSessionWithUser(steamId);
|
||||
#else
|
||||
SteamNetworking.CloseP2PSessionWithUser(steamId);
|
||||
#endif
|
||||
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
|
||||
NetworkLog.LogInfoServer(nameof(SteamNetworkingTransport) + " - DisconnectRemoteClient - has Closed P2P Session With clientId: " + clientId);
|
||||
}));
|
||||
|
||||
connectedUsers.Remove(clientId);
|
||||
}
|
||||
|
||||
public override ulong GetCurrentRtt(ulong clientId)
|
||||
{
|
||||
if (isServer)
|
||||
{
|
||||
if (clientId == ServerClientId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (connectedUsers.ContainsKey(clientId))
|
||||
{
|
||||
return connectedUsers[clientId].Ping.Get();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NetworkManager.Singleton.LogLevel <= LogLevel.Error)
|
||||
NetworkLog.LogErrorServer(nameof(SteamNetworkingTransport) + " - Can't GetCurrentRtt from client, client not connected, clientId: " + clientId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return serverUser.Ping.Get();
|
||||
}
|
||||
|
||||
return 0ul;
|
||||
}
|
||||
|
||||
public override void Initialize(NetworkManager networkManager = null)
|
||||
{
|
||||
if (!IsSupported)
|
||||
{
|
||||
if (NetworkManager.Singleton.LogLevel <= LogLevel.Error)
|
||||
NetworkLog.LogErrorServer(nameof(SteamNetworkingTransport) + " - Initialize - Steamworks.NET not ready, " + nameof(SteamNetworkingTransport) + " can not run without it");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public override NetworkEvent PollEvent(out ulong clientId, out ArraySegment<byte> payload, out float receiveTime)
|
||||
{
|
||||
//Connect fail disconnect
|
||||
if (connectionAttemptFailed)
|
||||
{
|
||||
clientId = connectionAttemptFailedClientId;
|
||||
payload = new ArraySegment<byte>();
|
||||
connectionAttemptFailed = false;
|
||||
receiveTime = Time.realtimeSinceStartup;
|
||||
return NetworkEvent.Disconnect;
|
||||
}
|
||||
|
||||
var currentPollChannel = 0;
|
||||
while (currentPollChannel < (int)InternalChannelType.InternalChannelsCount)
|
||||
{
|
||||
#if UNITY_SERVER
|
||||
if (SteamGameServerNetworking.IsP2PPacketAvailable(out uint msgSize, currentPollChannel))
|
||||
#else
|
||||
|
||||
if (SteamNetworking.IsP2PPacketAvailable(out uint msgSize, currentPollChannel))
|
||||
#endif
|
||||
{
|
||||
uint bytesRead;
|
||||
CSteamID remoteId;
|
||||
if (messageBuffer.Length < msgSize)
|
||||
{
|
||||
messageBuffer = new byte[msgSize];
|
||||
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
|
||||
NetworkLog.LogInfoServer(nameof(SteamNetworkingTransport) + " - PollEvent - Increase buffer size to: " + msgSize);
|
||||
}
|
||||
|
||||
#if UNITY_SERVER
|
||||
if (SteamGameServerNetworking.ReadP2PPacket(messageBuffer, msgSize, out bytesRead, out remoteId, currentPollChannel))
|
||||
#else
|
||||
|
||||
if (SteamNetworking.ReadP2PPacket(messageBuffer, msgSize, out bytesRead, out remoteId, currentPollChannel))
|
||||
#endif
|
||||
{
|
||||
clientId = remoteId.m_SteamID;
|
||||
|
||||
payload = new ArraySegment<byte>();
|
||||
|
||||
switch (currentPollChannel)
|
||||
{
|
||||
case (byte)InternalChannelType.Disconnect:
|
||||
|
||||
connectedUsers.Remove(clientId);
|
||||
#if UNITY_SERVER
|
||||
SteamGameServerNetworking.CloseP2PSessionWithUser(remoteId);
|
||||
#else
|
||||
SteamNetworking.CloseP2PSessionWithUser(remoteId);
|
||||
#endif
|
||||
receiveTime = Time.realtimeSinceStartup;
|
||||
return NetworkEvent.Disconnect;
|
||||
|
||||
case (byte)InternalChannelType.Connect:
|
||||
|
||||
if (isServer)
|
||||
{
|
||||
#if UNITY_SERVER
|
||||
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
|
||||
}
|
||||
|
||||
if (connectedUsers.ContainsKey(remoteId.m_SteamID) == false)
|
||||
{
|
||||
clientId = remoteId.m_SteamID;
|
||||
connectedUsers.Add(clientId, new User(remoteId));
|
||||
receiveTime = Time.realtimeSinceStartup;
|
||||
|
||||
if (!isServer)
|
||||
{
|
||||
OnConnected();
|
||||
}
|
||||
|
||||
return NetworkEvent.Connect;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case (byte)InternalChannelType.Ping:
|
||||
|
||||
pingPongMessageBuffer[0] = messageBuffer[0];
|
||||
#if UNITY_SERVER
|
||||
SteamGameServerNetworking.SendP2PPacket(remoteId, pingPongMessageBuffer, msgSize, EP2PSend.k_EP2PSendUnreliableNoDelay, (int)InternalChannelType.Pong);
|
||||
#else
|
||||
SteamNetworking.SendP2PPacket(remoteId, pingPongMessageBuffer, msgSize, EP2PSend.k_EP2PSendUnreliableNoDelay, (int)InternalChannelType.Pong);
|
||||
#endif
|
||||
receiveTime = Time.realtimeSinceStartup;
|
||||
break;
|
||||
|
||||
case (byte)InternalChannelType.Pong:
|
||||
|
||||
uint pingValue = sentPings[messageBuffer[0]].getPingTime();
|
||||
if (isServer)
|
||||
{
|
||||
if (connectedUsers.ContainsKey(remoteId.m_SteamID))
|
||||
connectedUsers[remoteId.m_SteamID].Ping.SetPing(pingValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
serverUser.Ping.SetPing(pingValue);
|
||||
}
|
||||
|
||||
receiveTime = Time.realtimeSinceStartup;
|
||||
break;
|
||||
|
||||
case (byte)InternalChannelType.NetcodeData:
|
||||
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();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentPollChannel++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentPollChannel++;
|
||||
}
|
||||
}
|
||||
|
||||
currentPollChannel = 0;
|
||||
payload = new ArraySegment<byte>();
|
||||
clientId = 0;
|
||||
receiveTime = Time.realtimeSinceStartup;
|
||||
return NetworkEvent.Nothing;
|
||||
}
|
||||
|
||||
public override void Send(ulong clientId, ArraySegment<byte> data, NetworkDelivery delivery)
|
||||
{
|
||||
EP2PSend sendType = NetworkDeliveryToEP2PSend(delivery);
|
||||
|
||||
if (clientId == ServerClientId)
|
||||
{
|
||||
#if UNITY_SERVER
|
||||
SteamGameServerNetworking.SendP2PPacket(serverUser.SteamId, data.Array, (uint)data.Count, sendType, (int)InternalChannelType.NetcodeData);
|
||||
#else
|
||||
SteamNetworking.SendP2PPacket(serverUser.SteamId, data.Array, (uint)data.Count, sendType, (int)InternalChannelType.NetcodeData);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (connectedUsers.ContainsKey(clientId))
|
||||
{
|
||||
#if UNITY_SERVER
|
||||
SteamGameServerNetworking.SendP2PPacket(connectedUsers[clientId].SteamId, data.Array, (uint)data.Count, sendType, (int)InternalChannelType.NetcodeData);
|
||||
#else
|
||||
SteamNetworking.SendP2PPacket(connectedUsers[clientId].SteamId, data.Array, (uint)data.Count, sendType, (int)InternalChannelType.NetcodeData);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NetworkManager.Singleton.LogLevel <= LogLevel.Error)
|
||||
NetworkLog.LogErrorServer(nameof(SteamNetworkingTransport) + " - Can't Send to client, client not connected, clientId: " + clientId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
|
||||
UnityEngine.Debug.Log(nameof(SteamNetworkingTransport) + " - Shutdown");
|
||||
|
||||
if (_p2PSessionRequestCallback != null)
|
||||
_p2PSessionRequestCallback.Dispose();
|
||||
if (_p2PSessionConnectFailCallback != null)
|
||||
_p2PSessionConnectFailCallback.Dispose();
|
||||
|
||||
sendPings = false;
|
||||
isServer = false;
|
||||
connectionAttemptFailed = false;
|
||||
|
||||
sentPings.Clear();
|
||||
pingIdCounter = 0;
|
||||
|
||||
if (NetworkManager.Singleton != null)
|
||||
{
|
||||
NetworkManager.Singleton.StartCoroutine(Delay(100, () =>
|
||||
{
|
||||
//Need to delay the closing of the p2p sessions to not block the disconect message before it is sent.
|
||||
CloseP2PSessions();
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseP2PSessions();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool StartClient()
|
||||
{
|
||||
serverUser = new User(new CSteamID(ConnectToSteamID));
|
||||
|
||||
#if UNITY_SERVER
|
||||
if (SteamGameServerNetworking.SendP2PPacket(serverUser.SteamId, new byte[] { 0 }, 1, EP2PSend.k_EP2PSendReliable, (int)InternalChannelType.Connect))
|
||||
#else
|
||||
|
||||
if (SteamNetworking.SendP2PPacket(serverUser.SteamId, new byte[] { 0 }, 1, EP2PSend.k_EP2PSendReliable, (int)InternalChannelType.Connect))
|
||||
#endif
|
||||
{
|
||||
_p2PSessionConnectFailCallback = Callback<P2PSessionConnectFail_t>.Create((sessionConnectFailInfo) =>
|
||||
{
|
||||
OnP2PSessionConnectFail(sessionConnectFailInfo);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
P2PSessionConnectFail_t sessionConnectFailInfo = new P2PSessionConnectFail_t()
|
||||
{
|
||||
m_eP2PSessionError = (byte)EP2PSessionError.k_EP2PSessionErrorMax,
|
||||
m_steamIDRemote = serverUser.SteamId
|
||||
};
|
||||
|
||||
OnP2PSessionConnectFail(sessionConnectFailInfo);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool StartServer()
|
||||
{
|
||||
isServer = true;
|
||||
|
||||
// setup the callback method
|
||||
_p2PSessionRequestCallback = Callback<P2PSessionRequest_t>.Create(OnP2PSessionRequest);
|
||||
_p2PSessionConnectFailCallback = Callback<P2PSessionConnectFail_t>.Create(OnP2PSessionConnectFail);
|
||||
OnConnected();
|
||||
|
||||
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
|
||||
UnityEngine.Debug.Log(nameof(SteamNetworkingTransport) + " - StartServer");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private EP2PSend NetworkDeliveryToEP2PSend(NetworkDelivery type)
|
||||
{
|
||||
EP2PSend options = EP2PSend.k_EP2PSendReliableWithBuffering;
|
||||
switch (type)
|
||||
{
|
||||
case NetworkDelivery.Unreliable:
|
||||
options = EP2PSend.k_EP2PSendUnreliable;
|
||||
break;
|
||||
case NetworkDelivery.UnreliableSequenced:
|
||||
options = EP2PSend.k_EP2PSendUnreliable;
|
||||
break;
|
||||
case NetworkDelivery.Reliable:
|
||||
options = EP2PSend.k_EP2PSendReliableWithBuffering;
|
||||
break;
|
||||
case NetworkDelivery.ReliableSequenced:
|
||||
options = EP2PSend.k_EP2PSendReliableWithBuffering;
|
||||
break;
|
||||
case NetworkDelivery.ReliableFragmentedSequenced:
|
||||
options = EP2PSend.k_EP2PSendReliableWithBuffering;
|
||||
break;
|
||||
default:
|
||||
options = EP2PSend.k_EP2PSendReliableWithBuffering;
|
||||
break;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private void CloseP2PSessions()
|
||||
{
|
||||
foreach (User user in connectedUsers.Values)
|
||||
{
|
||||
#if UNITY_SERVER
|
||||
SteamGameServerNetworking.CloseP2PSessionWithUser(user.SteamId);
|
||||
#else
|
||||
SteamNetworking.CloseP2PSessionWithUser(user.SteamId);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (serverUser != null)
|
||||
{
|
||||
#if UNITY_SERVER
|
||||
SteamGameServerNetworking.CloseP2PSessionWithUser(serverUser.SteamId);
|
||||
#else
|
||||
SteamNetworking.CloseP2PSessionWithUser(serverUser.SteamId);
|
||||
#endif
|
||||
}
|
||||
|
||||
connectedUsers.Clear();
|
||||
serverUser = null;
|
||||
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
|
||||
UnityEngine.Debug.Log(nameof(SteamNetworkingTransport) + " - CloseP2PSessions - has Closed P2P Sessions With all Users");
|
||||
}
|
||||
|
||||
private void OnP2PSessionRequest(P2PSessionRequest_t request)
|
||||
{
|
||||
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
|
||||
NetworkLog.LogInfoServer(nameof(SteamNetworkingTransport) + " - OnP2PSessionRequest - m_steamIDRemote: " + request.m_steamIDRemote);
|
||||
|
||||
CSteamID userId = request.m_steamIDRemote;
|
||||
|
||||
//Todo: Might want to check if we expect the user before just accepting it.
|
||||
#if UNITY_SERVER
|
||||
SteamGameServerNetworking.AcceptP2PSessionWithUser(userId);
|
||||
#else
|
||||
SteamNetworking.AcceptP2PSessionWithUser(userId);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void OnP2PSessionConnectFail(P2PSessionConnectFail_t request)
|
||||
{
|
||||
if (NetworkManager.Singleton.LogLevel <= LogLevel.Developer)
|
||||
NetworkLog.LogInfoServer(nameof(SteamNetworkingTransport) + " - OnP2PSessionConnectFail - m_steamIDRemote: " + request.m_eP2PSessionError.ToString() + " Error: " + request.m_eP2PSessionError.ToString());
|
||||
connectionAttemptFailed = true;
|
||||
connectionAttemptFailedClientId = request.m_steamIDRemote.m_SteamID;
|
||||
}
|
||||
|
||||
private static IEnumerator Delay(int milliseconds, Action action)
|
||||
{
|
||||
yield return new WaitForSeconds(milliseconds / 1000f);
|
||||
action.Invoke();
|
||||
}
|
||||
|
||||
private void OnConnected()
|
||||
{
|
||||
StartPingSendingLoop();
|
||||
}
|
||||
|
||||
private async void StartPingSendingLoop()
|
||||
{
|
||||
await PingSendingLoop();
|
||||
}
|
||||
|
||||
private async Task PingSendingLoop()
|
||||
{
|
||||
sendPings = true;
|
||||
while (sendPings)
|
||||
{
|
||||
pingIdCounter = (byte)((pingIdCounter + 1) % 128);
|
||||
sentPings.Remove(pingIdCounter);
|
||||
sentPings.Add(pingIdCounter, new PingTracker());
|
||||
|
||||
pingPongMessageBuffer[0] = pingIdCounter;
|
||||
|
||||
if (isServer)
|
||||
{
|
||||
foreach (User user in connectedUsers.Values)
|
||||
{
|
||||
#if UNITY_SERVER
|
||||
SteamGameServerNetworking.SendP2PPacket(user.SteamId, pingPongMessageBuffer, (uint)pingPongMessageBuffer.Length, EP2PSend.k_EP2PSendUnreliableNoDelay, (int)InternalChannelType.Ping);
|
||||
#else
|
||||
SteamNetworking.SendP2PPacket(user.SteamId, pingPongMessageBuffer, (uint)pingPongMessageBuffer.Length, EP2PSend.k_EP2PSendUnreliableNoDelay, (int)InternalChannelType.Ping);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if UNITY_SERVER
|
||||
SteamGameServerNetworking.SendP2PPacket(serverUser.SteamId, pingPongMessageBuffer, (uint)pingPongMessageBuffer.Length, EP2PSend.k_EP2PSendUnreliableNoDelay, (int)InternalChannelType.Ping);
|
||||
#else
|
||||
SteamNetworking.SendP2PPacket(serverUser.SteamId, pingPongMessageBuffer, (uint)pingPongMessageBuffer.Length, EP2PSend.k_EP2PSendUnreliableNoDelay, (int)InternalChannelType.Ping);
|
||||
#endif
|
||||
}
|
||||
|
||||
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
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3b81d70b2c3b41142a37e631239ef533
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"name": "SteamNetworking Transport for Netcode for GameObjects",
|
||||
"references": [
|
||||
"GUID:1491147abca9d7d4bb7105af628b223e",
|
||||
"GUID:68bd7fdb68ef2684e982e8a9825b18a5"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor",
|
||||
"LinuxStandalone64",
|
||||
"macOSStandalone",
|
||||
"WindowsStandalone32",
|
||||
"WindowsStandalone64"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e4ee367787d95d546a38c2d316861fb5
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"name": "com.community.netcode.transport.steamnetworking",
|
||||
"displayName": "SteamNetworking Transport for NetCode for Gameobjects",
|
||||
"version": "2.0.1",
|
||||
"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 Group",
|
||||
"url": "https://assetstore.unity.com/publishers/5836"
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8d776b4500b73fc4f8f5f56535b53889
|
||||
PackageManifestImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -246,7 +246,7 @@ namespace Netcode.Transports
|
|||
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;
|
||||
payload = new ArraySegment<byte>(buffer);
|
||||
SteamNetworkingMessage_t.Release(ptrs[0]);
|
||||
|
||||
receiveTime = Time.realtimeSinceStartup;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "com.community.netcode.transport.steamnetworkingsockets",
|
||||
"displayName": "SteamNetworkingSockets Transport for NetCode for Gameobjects",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"unity": "2020.3",
|
||||
"description": "SteamNetworkingSockets Transport for NetCode for GameObjects with support for both peer to peer and client server architectures.",
|
||||
"author": {
|
||||
|
|
Загрузка…
Ссылка в новой задаче