This commit is contained in:
2025-02-25 13:04:07 +02:00
parent 21eb5f6154
commit 84538e16e2
11 changed files with 84 additions and 172 deletions

View File

@@ -40,38 +40,24 @@
<ItemGroup>
<Reference Include="MelonLoader">
<HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Stationeers\MelonLoader\MelonLoader.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.TestPlatform.CoreUtilities, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.TestPlatform.ObjectModel.17.12.0\lib\net462\Microsoft.TestPlatform.CoreUtilities.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.TestPlatform.PlatformAbstractions, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.TestPlatform.ObjectModel.17.12.0\lib\net462\Microsoft.TestPlatform.PlatformAbstractions.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.ObjectModel, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.TestPlatform.ObjectModel.17.12.0\lib\net462\Microsoft.VisualStudio.TestPlatform.ObjectModel.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.3.8.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.3.8.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.2.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Reflection.Metadata, Version=1.4.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reflection.Metadata.1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Runtime" />
<Reference Include="System.Runtime.Serialization" />
@@ -81,24 +67,16 @@
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\.nuget\packages\xunit.abstractions\2.0.3\lib\net35\xunit.abstractions.dll</HintPath>
<Private>False</Private>
<HintPath>..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll</HintPath>
</Reference>
<Reference Include="xunit.assert, Version=2.9.3.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\.nuget\packages\xunit.assert\2.9.3\lib\netstandard1.1\xunit.assert.dll</HintPath>
<Private>False</Private>
<HintPath>..\packages\xunit.assert.2.9.3\lib\netstandard1.1\xunit.assert.dll</HintPath>
</Reference>
<Reference Include="xunit.core, Version=2.9.3.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\.nuget\packages\xunit.extensibility.core\2.9.3\lib\net452\xunit.core.dll</HintPath>
<Private>False</Private>
<HintPath>..\packages\xunit.extensibility.core.2.9.3\lib\net452\xunit.core.dll</HintPath>
</Reference>
<Reference Include="xunit.execution.desktop, Version=2.9.3.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\.nuget\packages\xunit.extensibility.execution\2.9.3\lib\net452\xunit.execution.desktop.dll</HintPath>
<Private>False</Private>
<HintPath>..\packages\xunit.extensibility.execution.2.9.3\lib\net452\xunit.execution.desktop.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -114,17 +92,19 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Networking\ByteEncoder.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<WCFMetadata Include="Connected Services\" />
<ProjectReference Include="Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj">
<Project>{0289f09e-d594-46a9-96a7-b0f31f5d97b0}</Project>
<Name>Facepunch.Steamworks.Win64</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\packages\MSTest.Analyzers.3.8.2\analyzers\dotnet\cs\MSTest.Analyzers.CodeFixes.dll" />
<Analyzer Include="..\packages\MSTest.Analyzers.3.8.2\analyzers\dotnet\cs\MSTest.Analyzers.dll" />
<Analyzer Include="..\packages\xunit.analyzers.1.20.0\analyzers\dotnet\cs\xunit.analyzers.dll" />
<Analyzer Include="..\packages\xunit.analyzers.1.20.0\analyzers\dotnet\cs\xunit.analyzers.fixes.dll" />
<Analyzer Include="..\packages\xunit.analyzers.1.18.0\analyzers\dotnet\cs\xunit.analyzers.dll" />
<Analyzer Include="..\packages\xunit.analyzers.1.18.0\analyzers\dotnet\cs\xunit.analyzers.fixes.dll" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>

View File

@@ -25,7 +25,8 @@ namespace BoneSync
SteamLobbyManager steamLobbyManager = new SteamLobbyManager();
lobby = steamLobbyManager;
transport = new SteamTransport();
transport = new SteamTransport(steamLobbyManager);
}

View File

@@ -11,11 +11,15 @@ namespace BoneSync.Networking.LobbyManager
{
public abstract class LobbyManager
{
public abstract ulong[] GetPeers();
public abstract ulong GetLobbyId();
public abstract ulong GetHostId();
public abstract ulong GetLocalId();
public virtual void CreateLobby()
{
}
public virtual void Initialize()
{

View File

@@ -10,52 +10,36 @@ namespace BoneSync.Networking.LobbyManager
{
internal class SteamLobbyManager : LobbyManager
{
private Lobby _lobbyInstance;
public Friend[] LobbyMembers
public SteamId[] Peers;
private Lobby lobbyInstance;
public override ulong GetLocalId()
{
get;
private set;
return SteamClient.SteamId.Value;
}
public SteamId[] steamIds
public override ulong GetHostId()
{
get;
private set;
return lobbyInstance.Owner.Id;
}
public override ulong GetLobbyId()
{
return lobbyInstance.Id;
}
public override void CreateLobby()
{
}
public override ulong[] GetPeers() => steamIds.Select(x => x.Value).ToArray();
public override ulong GetLocalId() => SteamClient.SteamId.Value;
public override ulong GetHostId() => _lobbyInstance.Owner.Id.Value;
public override ulong GetLobbyId() => _lobbyInstance.Id.Value;
private void UpdateLobbyData()
public SteamId? getPeerFromId(ulong id)
{
LobbyMembers = _lobbyInstance.Members.ToArray();
steamIds = LobbyMembers.Select(x => x.Id).ToArray();
}
public override void Initialize()
{
SteamMatchmaking.OnLobbyCreated += (Result result, Lobby lobby) =>
foreach (SteamId peer in Peers)
{
_lobbyInstance = lobby;
UpdateLobbyData();
};
SteamMatchmaking.OnLobbyEntered += (Lobby lobby) =>
{
_lobbyInstance = lobby;
UpdateLobbyData();
};
SteamMatchmaking.OnLobbyMemberLeave += (Lobby lobby, Friend friend) =>
{
if (friend.Id == SteamClient.SteamId)
if (peer.Value == id)
{
_lobbyInstance = new Lobby();
return peer;
}
UpdateLobbyData();
};
SteamMatchmaking.OnLobbyMemberJoined += (Lobby lobby, Friend friend) =>
{
UpdateLobbyData();
};
}
return null;
}
}

View File

@@ -22,7 +22,7 @@ namespace BoneSync.Networking.Messages
public abstract class NetworkMessage
{
private static bool PacketTypesRegistered => PacketTypeMap.Count > 0;
private static bool _packetTypesRegistered = false;
internal static Dictionary<PacketType, Type> PacketTypeMap = new Dictionary<PacketType, Type>();
@@ -34,26 +34,25 @@ namespace BoneSync.Networking.Messages
public PacketType GetPacketType()
{
RegisterPacketTypes();
if (_packetType == PacketType.Unknown)
{
string typeName = GetType().Name;
KeyValuePair<PacketType, Type> found = PacketTypeMap.FirstOrDefault(x => x.Value.Name == typeName);
if (found.Value == null)
Type type = GetType();
_packetType = PacketTypeMap.FirstOrDefault(x => x.Value == type).Key;
if (_packetType == PacketType.Unknown)
{
throw new Exception("Cannot find packetType for " + typeName);
throw new Exception("Cannot find packetType for " + type.Name);
}
_packetType = found.Key;
}
return _packetType;
}
public static void RegisterPacketTypes()
{
if (PacketTypesRegistered)
if (_packetTypesRegistered)
{
return;
}
_packetTypesRegistered = true;
Assembly assembly = Assembly.GetExecutingAssembly();
Type[] types = assembly.GetTypes();
foreach (Type type in types)
@@ -62,7 +61,7 @@ namespace BoneSync.Networking.Messages
if (type.IsSubclassOf(typeof(NetworkMessage)))
{
PacketType? packetType = type.GetCustomAttributesData().Where(x => x.AttributeType == typeof(PacketTypeAttribute)).Select(x => (PacketType)x.ConstructorArguments[0].Value).FirstOrDefault();
PacketTypeMap[packetType.Value] = type;
PacketTypeMap.Add((PacketType)packetType, type);
}
}
}
@@ -76,7 +75,12 @@ namespace BoneSync.Networking.Messages
}
Type type = PacketTypeMap[packet.Info.packetType];
// get the constructor that takes a Packet
ConstructorInfo constructor = type.GetConstructor(new Type[] { typeof(Packet) }) ?? throw new Exception("No constructor found for type " + type.Name);
ConstructorInfo constructor = type.GetConstructor(new Type[] { typeof(Packet) });
// create an instance of the class
if (constructor == null)
{
throw new Exception("No constructor found for type " + type.Name);
}
NetworkMessage networkMessage = (NetworkMessage)constructor.Invoke(new object[] { packet });
return networkMessage;
}
@@ -91,7 +95,7 @@ namespace BoneSync.Networking.Messages
}
public void Broadcast()
{
Send(TransportBase.BORADCAST_ID);
Send(0);
}
public void Send(ulong receiverId)
{

View File

@@ -1,5 +1,4 @@
using BoneSync.Networking.Messages;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -34,6 +33,7 @@ namespace BoneSync.Networking
private PacketInfo _packetInfo;
private byte[] _dataBytes;
private PacketInfo packetInfo;
public Packet(PacketInfo packetInfo, byte[] data)
{
@@ -45,34 +45,21 @@ namespace BoneSync.Networking
{
ByteEncoder byteEncoder = new ByteEncoder();
byteEncoder.WriteBytes(bytes);
int packetType = byteEncoder.ReadInt();
int id = byteEncoder.ReadInt();
ulong senderId = byteEncoder.ReadUlong();
ulong receiverId = byteEncoder.ReadUlong();
PacketInfo packetInfo = new PacketInfo(id, senderId, receiverId, (PacketType)packetType);
PacketInfo packetInfo = new PacketInfo(byteEncoder.ReadInt(), byteEncoder.ReadUlong(), byteEncoder.ReadUlong(), (PacketType)byteEncoder.ReadInt());
return new Packet(packetInfo, byteEncoder.ToArray());
}
public byte[] ToBytes()
{
ByteEncoder byteEncoder = new ByteEncoder();
byteEncoder.WriteInt((int)_packetInfo.packetType);
byteEncoder.WriteInt(_packetInfo.id);
byteEncoder.WriteUlong(_packetInfo.senderId);
byteEncoder.WriteUlong(_packetInfo.receiverId);
byteEncoder.WriteInt(packetInfo.id);
byteEncoder.WriteUlong(packetInfo.senderId);
byteEncoder.WriteUlong(packetInfo.receiverId);
byteEncoder.WriteInt((int)packetInfo.packetType);
byteEncoder.WriteBytes(_dataBytes);
return byteEncoder.ToArray();
}
public static bool OnPacketReceived(Packet packet)
{
NetworkMessage networkMessage = NetworkMessage.ParsePacket(packet);
networkMessage.Execute();
return true;
}
public byte[] Data => _dataBytes;
public static int GenerateId()
@@ -90,21 +77,15 @@ namespace BoneSync.Networking
byte[] randomDataBytes = new byte[1024];
random.NextBytes(randomDataBytes);
PacketInfo originalPacketInfo = new PacketInfo(Packet.GenerateId(), 1, 2, PacketType.LobbyInfo);
PacketInfo originalPacketInfo = new PacketInfo(1, 2, 3, PacketType.LobbyInfo);
Packet originalPacket = new Packet(originalPacketInfo, randomDataBytes);
byte[] bytes = originalPacket.ToBytes();
Packet parsedPacket = Packet.FromBytes(bytes);
Assert.Equal(originalPacket.Info.id, parsedPacket.Info.id);
Assert.Equal(originalPacket.Info.senderId, parsedPacket.Info.senderId);
Assert.Equal(originalPacket.Info.receiverId, parsedPacket.Info.receiverId);
Assert.Equal(originalPacket.Info.packetType, parsedPacket.Info.packetType);
Assert.Equal(originalPacket.Info, parsedPacket.Info);
Assert.Equal(originalPacket.Data, parsedPacket.Data);
Assert.Equal(randomDataBytes, parsedPacket.Data);
Assert.NotEqual(bytes, randomDataBytes);
}

View File

@@ -1,82 +1,62 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using BoneSync.Networking.LobbyManager;
using Facepunch.Steamworks;
using Facepunch.Steamworks.Data;
using MelonLoader;
namespace BoneSync.Networking.Transport
{
internal class SteamTransport : TransportBase
{
SteamLobbyManager _instance;
public override event Action<Packet> OnReceive;
public SteamTransport()
public SteamTransport(SteamLobbyManager lobbyManager)
{
SteamNetworking.OnP2PSessionRequest += OnP2PSessionRequest;
}
private void OnP2PSessionRequest(SteamId steamId)
{
MelonLogger.Msg("P2P Request from " + steamId);
if (BoneSync.lobby.GetPeers().Contains(steamId))
SteamNetworking.AcceptP2PSessionWithUser(steamId);
SteamNetworking.AcceptP2PSessionWithUser(steamId);
}
private void ProcessPacket(P2Packet steamPacket)
{
Packet packet = Packet.FromBytes(steamPacket.Data);
bool isTarget = packet.Info.receiverId == BORADCAST_ID || packet.Info.receiverId == BoneSync.lobby.GetLocalId();
bool isTarget = packet.Info.receiverId == 0 || packet.Info.receiverId == _instance.GetLocalId();
if (isTarget)
{
Packet.OnPacketReceived(packet);
OnReceive?.Invoke(packet);
}
}
public override bool Tick()
{
int processed = 0;
while (SteamNetworking.IsP2PPacketAvailable())
{
P2Packet? packet = SteamNetworking.ReadP2PPacket();
if (!packet.HasValue) continue;
ProcessPacket(packet.Value);
processed++;
P2Packet packet = (P2Packet)SteamNetworking.ReadP2PPacket();
ProcessPacket(packet);
}
return processed > 0;
}
public void SendP2P(SteamId peer, byte[] data)
{
if (peer == BoneSync.lobby.GetLocalId())
{
//MelonLogger.Msg("Trying to send packet to self");
return;
}
SteamNetworking.SendP2PPacket(peer, data, data.Length, 0, P2PSend.Reliable);
return true;
}
public override void Send(Packet packet)
{
LobbyManager.LobbyManager _instance = BoneSync.lobby;
if (_instance == null)
if (packet.Info.receiverId == 0)
{
MelonLogger.Msg("Lobby instance is null");
return;
}
if (packet.Info.receiverId == BORADCAST_ID)
{
foreach (SteamId peer in _instance.GetPeers())
foreach (SteamId peer in _instance.Peers)
{
SendP2P(peer, packet.ToBytes());
byte[] packetBytes = packet.ToBytes();
SteamNetworking.SendP2PPacket(peer, packetBytes, packetBytes.Length, 0, P2PSend.Reliable);
}
return;
}
else
{
SendP2P(packet.Info.receiverId, packet.ToBytes());
SteamId peer = (SteamId)_instance.getPeerFromId(packet.Info.receiverId);
SteamNetworking.SendP2PPacket(peer, packet.ToBytes(), packet.ToBytes().Length, 0, P2PSend.Reliable);
}
}

View File

@@ -8,8 +8,9 @@ namespace BoneSync.Networking.Transport
{
public abstract class TransportBase
{
public const int BORADCAST_ID = 0;
public abstract void Send(Packet packet);
public abstract bool Tick();
public abstract event Action<Packet> OnReceive;
}
}

View File

@@ -1,13 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.TestPlatform.ObjectModel" version="17.12.0" targetFramework="net472" />
<package id="MSTest.Analyzers" version="3.8.2" targetFramework="net472" developmentDependency="true" />
<package id="MSTest.TestFramework" version="3.8.2" targetFramework="net472" />
<package id="System.Collections.Immutable" version="1.5.0" targetFramework="net472" />
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net472" />
<package id="xunit" version="2.9.3" targetFramework="net472" />
<package id="xunit.abstractions" version="2.0.3" targetFramework="net472" />
<package id="xunit.analyzers" version="1.20.0" targetFramework="net472" developmentDependency="true" />
<package id="xunit.analyzers" version="1.18.0" targetFramework="net472" developmentDependency="true" />
<package id="xunit.assert" version="2.9.3" targetFramework="net472" />
<package id="xunit.core" version="2.9.3" targetFramework="net472" />
<package id="xunit.extensibility.core" version="2.9.3" targetFramework="net472" />

View File

@@ -24,15 +24,11 @@
<RepositoryUrl>https://github.com/Facepunch/Facepunch.Steamworks.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
</PropertyGroup>
<ItemGroup>
<None Remove="steam_api.dll" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="steam_api64.dll" PackagePath="\content\" Pack="true" PackageCopyToOutput="true">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
<Content Include="steam_api64.dll" PackagePath="\content\" Pack="true" PackageCopyToOutput="true">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<None Include="Facepunch.Steamworks.jpg" Pack="true" PackagePath="\" />
</ItemGroup>

View File

@@ -1,17 +0,0 @@
{
"version": "1",
"environments": [
// See https://aka.ms/remotetesting for more details
// about how to configure remote environments.
//{
// "name": "WSL Ubuntu",
// "type": "wsl",
// "wslDistribution": "Ubuntu"
//},
//{
// "name": "Docker dotnet/sdk",
// "type": "docker",
// "dockerImage": "mcr.microsoft.com/dotnet/sdk"
//}
]
}