From 2d365a530c0055f5515af4b3622c1159e64c2512 Mon Sep 17 00:00:00 2001 From: cubic Date: Sat, 15 Apr 2023 23:37:50 +0100 Subject: [PATCH 001/120] Bumped LiteNetLib dependency --- .../Configuration/InstanceConfiguration.cs | 2 -- BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs | 3 ++- .../BeatTogether.DedicatedServer.Messaging.csproj | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs index dd9c69ff..9cdd28b6 100644 --- a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs +++ b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs @@ -24,8 +24,6 @@ public sealed class InstanceConfiguration public bool AllowMappingExtensions { get; set; } public bool AllowNoodleExtensions { get; set; } public float KickPlayersWithoutEntitlementTimeout { get; set; } = 30f; - public bool DisablePlayerMovement { get; set; } = false; - public bool DisableNotes { get; set; } = false; } public sealed class CountdownConfig diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index e835f9c6..3c501aca 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -2,7 +2,6 @@ using System.Collections.Concurrent; using System.Linq; using System.Net; -using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; using BeatTogether.DedicatedServer.Kernel.Abstractions; @@ -73,6 +72,8 @@ public DedicatedInstance( liteNetConfiguration, registry, serviceProvider, + false, + 0, packetLayer) { _configuration = configuration; diff --git a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj index d8bbda19..d69e38d7 100644 --- a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj +++ b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj @@ -7,9 +7,9 @@ - + - + From c1ea2904654d54d7354abc6d35f8147be312ae5d Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 17 Apr 2023 16:51:12 +0100 Subject: [PATCH 002/120] First set of changes --- .../DedicatedInstance.cs | 5 +- .../Encryption/PacketEncryptionLayer.cs | 108 ++++++++++- .../Handshake/UnconnectedDispatcher.cs | 2 +- .../Handshake/UnconnectedSource.cs | 8 +- .../PacketDispatcher.cs | 35 ++-- .../PacketSource.cs | 15 +- .../Abstractions/BaseRpcPacket.cs | 15 +- .../Abstractions/BaseRpcWithValuesPacket.cs | 17 +- ...tTogether.DedicatedServer.Messaging.csproj | 2 +- .../Extensions/MemoryBufferExtensions.cs | 176 +++++++++++++++++ .../Extensions/SpanBufferExtensions.cs | 177 ++++++++++++++++++ .../Extensions/SpanBufferReaderExtensions.cs | 23 --- .../Extensions/SpanBufferWriterExtensions.cs | 13 -- .../AuthenticateGameLiftUserRequest.cs | 2 +- .../Models/AvatarData.cs | 46 ++++- .../Models/BeatmapIdentifier.cs | 18 +- .../Models/BitMask128.cs | 16 +- .../Models/ByteArray.cs | 16 +- .../Models/ColorNoAlpha.cs | 18 +- .../Models/ColorScheme.cs | 26 ++- .../Models/ConnectionRequestData.cs | 57 +++++- .../Models/GameplayModifiers.cs | 50 ++++- .../Models/LevelCompletionResults.cs | 61 +++++- .../MultiplayerLevelCompletionResults.cs | 23 ++- .../Models/NodePoseSyncState.cs | 19 +- .../Models/NoteCutInfo.cs | 43 ++++- .../Models/NoteMissInfo.cs | 21 ++- .../Models/PlayerPermissionConfiguration.cs | 23 ++- .../Models/PlayerSpecificSettings.cs | 27 ++- .../Models/PlayerSpecificSettingsAtStart.cs | 24 ++- .../Models/PlayersPermissionConfiguration.cs | 24 ++- .../Models/Pose.cs | 16 +- .../Models/ProcessingPacketInfo.cs | 2 +- .../Models/Quaternion.cs | 19 +- .../Models/StandardScoreSyncState.cs | 23 ++- .../Models/Vector3.cs | 19 +- .../Packets/KickPlayerPacket.cs | 15 +- .../GameplayRpc/LevelFinishedPacket.cs | 18 +- .../GameplayRpc/NoteCutPacket.cs | 21 ++- .../GameplayRpc/NoteMissPacket.cs | 21 ++- .../SetGameplaySceneReadyPacket.cs | 18 +- .../SetGameplaySceneSyncFinishedPacket.cs | 21 ++- .../SetPlayerDidConnectLatePacket.cs | 24 ++- .../GameplayRpc/SetSongStartTimePacket.cs | 18 +- .../MenuRpc/GetIsEntitledToLevelPacket.cs | 18 +- .../MenuRpc/RequestKickPlayerPacket.cs | 18 +- .../MenuRpc/SetCountdownEndTimePacket.cs | 18 +- .../MenuRpc/SetIsEntitledToLevelPacket.cs | 21 ++- .../MenuRpc/SetIsInLobbyPacket.cs | 18 +- .../MenuRpc/SetIsReadyPacket.cs | 18 +- .../MenuRpc/SetIsStartButtonEnabledPacket.cs | 18 +- .../MenuRpc/SetMultiplayerGameStatePacket.cs | 18 +- .../MenuRpc/SetOwnedSongPacksPacket.cs | 18 +- ...PlayersMissingEntitlementsToLevelPacket.cs | 30 ++- ...SetPlayersPermissionConfigurationPacket.cs | 18 +- .../MenuRpc/SetRecommendedBeatmapPacket.cs | 18 +- .../MenuRpc/SetRecommendedModifiersPacket.cs | 18 +- .../MenuRpc/SetSelectedBeatmap.cs | 18 +- .../MenuRpc/SetSelectedGameplayModifiers.cs | 18 +- .../MenuRpc/SetStartGameTimePacket.cs | 18 +- .../MenuRpc/StartLevelPacket.cs | 24 ++- .../MpCorePackets/DediPacketSetNewManager.cs | 15 +- .../MpCorePackets/MpBeatmapPacket.cs | 49 ++++- .../NodePoseSyncStateDeltaPacket.cs | 21 ++- .../NodePoseSyncStatePacket.cs | 20 +- .../ScoreSyncStateDeltaPacket.cs | 20 +- .../ScoreSyncStatePacket.cs | 19 +- .../Packets/PingPacket.cs | 15 +- .../Packets/PlayerConnectedPacket.cs | 21 ++- .../Packets/PlayerDisconnectedPacket.cs | 15 +- .../Packets/PlayerIdentityPacket.cs | 21 ++- .../Packets/PlayerLatencyPacket.cs | 15 +- .../Packets/PlayerSortOrderPacket.cs | 17 +- .../Packets/PlayerStatePacket.cs | 15 +- .../Packets/PongPacket.cs | 15 +- .../Packets/SyncTimePacket.cs | 15 +- .../BeatTogether.DedicatedServer.Node.csproj | 2 +- 77 files changed, 1713 insertions(+), 254 deletions(-) create mode 100644 BeatTogether.DedicatedServer.Messaging/Extensions/MemoryBufferExtensions.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferReaderExtensions.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferWriterExtensions.cs diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 3c501aca..73aaea85 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -16,6 +16,7 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Configuration; using BeatTogether.LiteNetLib.Enums; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; using Microsoft.Extensions.DependencyInjection; using Serilog; @@ -233,7 +234,7 @@ public void SetState(MultiplayerGameState state) object AcceptConnectionLock = new(); - public override bool ShouldAcceptConnection(EndPoint endPoint, ref SpanBufferReader additionalData) + public override bool ShouldAcceptConnection(EndPoint endPoint, ref MemoryBuffer additionalData) { if (ShouldDenyConnection(endPoint, ref additionalData)) @@ -243,7 +244,7 @@ public override bool ShouldAcceptConnection(EndPoint endPoint, ref SpanBufferRea } return true; } - public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBufferReader additionalData) + public bool ShouldDenyConnection(EndPoint endPoint, ref MemoryBuffer additionalData) { var connectionRequestData = new ConnectionRequestData(); try diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs index d97753df..2af830f7 100644 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs @@ -110,6 +110,7 @@ public void RemoveEncryptedEndPoint(IPEndPoint endPoint) public void ProcessInboundPacket(EndPoint endPoint, ref Span data) { + _logger.Information("Inbound Before decryption: " + BitConverter.ToString(data.ToArray())); var address = ((IPEndPoint) endPoint).Address; if (data.Length == 0) @@ -122,6 +123,7 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Span data) // Received an unencrypted packet - this is valid if the client is still negotiating // Slice out the encryption flag and continue data = data[1..]; + _logger.Information("Inbound After decryption(Unencrypted): " + BitConverter.ToString(data.ToArray())); // TODO Reject unencrypted inbound packets for regular clients past the negotiation stage? return; } @@ -134,6 +136,8 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Span data) data = decryptedData; else data = Array.Empty(); + + _logger.Information("Inbound After decryption: " + BitConverter.ToString(data.ToArray())); return; } @@ -147,13 +151,13 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Span data) } else data = Array.Empty(); - + _logger.Information("Inbound After decryption: " + BitConverter.ToString(data.ToArray())); return; } // Cannot decrypt incoming packet // This can happen briefly when the handshake process switches to encrypted mode - _logger.Verbose( + _logger.Information( "Failed to retrieve decryption parameters " + $"(RemoteEndPoint='{endPoint}')." ); @@ -162,6 +166,8 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Span data) public void ProcessOutBoundPacket(EndPoint endPoint, ref Span data) { + + _logger.Information("Before encryption: " + BitConverter.ToString(data.ToArray())); if (!_encryptionParameters.TryGetValue(endPoint, out var encryptionParameters)) { if (_potentialEncryptionParameters.TryGetValue(((IPEndPoint) endPoint).Address, @@ -195,9 +201,107 @@ public void ProcessOutBoundPacket(EndPoint endPoint, ref Span data) bufferWriter.WriteBool(false); // NotEncrypted bufferWriter.WriteBytes(data); } + _logger.Information("After encryption: " + BitConverter.ToString(bufferWriter.Data.ToArray())); data = bufferWriter.Data.ToArray(); } + public void ProcessInboundPacket(EndPoint endPoint, ref Memory data) + { + _logger.Information("Inbound Before decryption: " + BitConverter.ToString(data.ToArray())); + var address = ((IPEndPoint)endPoint).Address; + + if (data.Length == 0) + return; + + var bufferReader = new SpanBufferReader(data.Span); + + if (!bufferReader.ReadBool()) // NotEncrypted + { + // Received an unencrypted packet - this is valid if the client is still negotiating + // Slice out the encryption flag and continue + data = data[1..]; + _logger.Information("Inbound After decryption(Unencrypted): " + BitConverter.ToString(data.ToArray())); + // TODO Reject unencrypted inbound packets for regular clients past the negotiation stage? + return; + } + + byte[]? decryptedData; + + if (_encryptionParameters.TryGetValue(endPoint, out var encryptionParameters)) + { + if (TryDecrypt(ref bufferReader, encryptionParameters, out decryptedData)) + data = decryptedData; + else + data = Array.Empty(); + _logger.Information("Inbound After decryption: " + BitConverter.ToString(data.ToArray())); + return; + } + + if (_potentialEncryptionParameters.TryGetValue(address, out encryptionParameters)) + { + if (TryDecrypt(ref bufferReader, encryptionParameters, out decryptedData)) + { + _encryptionParameters[endPoint] = encryptionParameters; + _potentialEncryptionParameters.TryRemove(address, out _); + data = decryptedData; + } + else + data = Array.Empty(); + _logger.Information("Inbound After decryption(Unencrypted): " + BitConverter.ToString(data.ToArray())); + return; + } + + // Cannot decrypt incoming packet + // This can happen briefly when the handshake process switches to encrypted mode + _logger.Information( + "Failed to retrieve decryption parameters " + + $"(RemoteEndPoint='{endPoint}')." + ); + data = Array.Empty(); + } + + public void ProcessOutBoundPacket(EndPoint endPoint, ref Memory data) + { + _logger.Information("Before encryption: " + BitConverter.ToString(data.Span.ToArray())); + if (!_encryptionParameters.TryGetValue(endPoint, out var encryptionParameters)) + { + if (_potentialEncryptionParameters.TryGetValue(((IPEndPoint)endPoint).Address, + out var encryptionParametersOld)) + { + _logger.Warning( + $"Re-assigning encryption parameters as old parameters (RemoteEndPoint='{endPoint}')."); + encryptionParameters = _encryptionParameters.GetOrAdd(endPoint, encryptionParametersOld); + } + } + + var bufferWriter = new SpanBufferWriter(stackalloc byte[412]); + + if (encryptionParameters != null) + { + bufferWriter.WriteBool(true); // isEncrypted + + using (var hmac = new HMACSHA256(encryptionParameters.SendMac)) + { + _encryptedPacketWriter.WriteTo( + ref bufferWriter, data.Span, + encryptionParameters.GetNextSequenceId(), + encryptionParameters.SendKey, hmac); + } + } + else + { + // Failed to retrieve encryption parameters for send + // During early handshake, this is legitimate + + bufferWriter.WriteBool(false); // NotEncrypted + bufferWriter.WriteBytes(data.Span); + } + _logger.Information("After encryption: " + BitConverter.ToString(bufferWriter.Data.ToArray())); + data = new Memory(bufferWriter.Data.ToArray()); + _logger.Information("After encryption & convertBack: " + BitConverter.ToString(data.Span.ToArray())); + } + + #endregion #region Private Methods diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs index f81d2c27..99d0efc4 100644 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs @@ -51,7 +51,7 @@ public void Dispose() public void Send(HandshakeSession session, IMessage message, bool retry = false) { - _logger.Verbose("Sending handshake message of type {MessageType} (EndPoint={EndPoint})", + _logger.Information("Sending handshake message of type {MessageType} (EndPoint={EndPoint})", message.GetType().Name, session.EndPoint.ToString()); // Assign request ID to outgoing requests diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedSource.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedSource.cs index c70797c8..5918dcf2 100644 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedSource.cs @@ -10,6 +10,7 @@ using BeatTogether.DedicatedServer.Messaging.Messages.Handshake; using BeatTogether.LiteNetLib.Enums; using BeatTogether.LiteNetLib.Sources; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; using Serilog; @@ -62,13 +63,16 @@ public void Dispose() #region Receive - public override void OnReceive(EndPoint remoteEndPoint, ref SpanBufferReader reader, + public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, UnconnectedMessageType type) { + + SpanBufferReader spanBufferReader = new(reader.RemainingData.Span.ToArray()); var session = _handshakeSessionRegistry.GetOrAdd(remoteEndPoint); - var message = _messageReader.ReadFrom(ref reader); + var message = _messageReader.ReadFrom(ref spanBufferReader); Task.Run(() => HandleMessage(session, message)); + } public async Task HandleMessage(HandshakeSession session, IMessage message) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index d7d36723..a35fb5de 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -5,6 +5,7 @@ using BeatTogether.LiteNetLib.Configuration; using BeatTogether.LiteNetLib.Dispatchers; using BeatTogether.LiteNetLib.Enums; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; using Serilog; using System; @@ -42,7 +43,7 @@ public void SendToNearbyPlayers(INetSerializable packet, DeliveryMethod delivery $"(SenderId={ServerId})" ); - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(412, true)); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); _logger.Verbose("Packet: " + packet.GetType().Name + " Was entered into the spanbuffer correctly, now sending once to each player"); @@ -56,7 +57,7 @@ public void SendToNearbyPlayers(INetSerializable[] packets, DeliveryMethod deliv $"(SenderId={ServerId})" ); - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(412, true)); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); _logger.Verbose("Packets were entered into the spanbuffer correctly, now sending once to each player"); @@ -71,7 +72,7 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, $"(ExcludedId={excludedPlayer.ConnectionId})" ); - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(412, true)); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); @@ -86,7 +87,7 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packe $"(ExcludedId={excludedPlayer.ConnectionId})" ); - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(412, true)); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); @@ -102,7 +103,7 @@ public void SendToEndpoint(EndPoint endpoint, INetSerializable packet, DeliveryM $"(To endpoint ={endpoint})" ); - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(412, true)); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); @@ -115,7 +116,7 @@ public void SendToEndpoint(EndPoint endpoint, INetSerializable[] packets, Delive $"(To endpoint ={endpoint})" ); - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(412, true)); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); @@ -129,7 +130,7 @@ public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, Delivery $"(SenderId={fromPlayer.ConnectionId})" ); - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(412, true)); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteOne(ref writer, packet); @@ -143,7 +144,7 @@ public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, Deliv $"(SenderId={fromPlayer.ConnectionId})" ); - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(412, true)); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteMany(ref writer, packets); @@ -158,7 +159,7 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer $"(SenderId={fromPlayer.ConnectionId}, ReceiverId={LocalConnectionId})." ); - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(412, true)); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteOne(ref writer, packet); Send(toPlayer.Endpoint, writer.Data, deliveryMethod); @@ -171,7 +172,7 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer $"(SenderId={fromPlayer.ConnectionId}, ReceiverId={LocalConnectionId})." ); - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(412, true)); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteMany(ref writer, packets); Send(toPlayer.Endpoint, writer.Data, deliveryMethod); @@ -184,10 +185,10 @@ public void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod $"(SenderId={ServerId}, ReceiverId={LocalConnectionId})." ); - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(412, true)); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); - Send(player.Endpoint, writer, deliveryMethod); + Send(player.Endpoint, writer.Data, deliveryMethod); } public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMethod deliveryMethod) @@ -197,18 +198,18 @@ public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMet $"(SenderId={ServerId}, ReceiverId={LocalConnectionId})." ); - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(412, true)); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); - Send(player.Endpoint, writer, deliveryMethod); + Send(player.Endpoint, writer.Data, deliveryMethod); } - public void WriteOne(ref SpanBufferWriter writer, INetSerializable packet) + public void WriteOne(ref MemoryBuffer writer, INetSerializable packet) { var type = packet.GetType(); if (!_packetRegistry.TryGetPacketIds(type, out var packetIds)) throw new Exception($"Failed to retrieve identifier for packet of type '{type.Name}'"); - var packetWriter = new SpanBufferWriter(stackalloc byte[412]); + var packetWriter = new SpanBuffer(stackalloc byte[412]); foreach (byte packetId in packetIds) packetWriter.WriteUInt8(packetId); packet.WriteTo(ref packetWriter); @@ -216,7 +217,7 @@ public void WriteOne(ref SpanBufferWriter writer, INetSerializable packet) writer.WriteBytes(packetWriter.Data.ToArray()); } - public void WriteMany(ref SpanBufferWriter writer, INetSerializable[] packets) + public void WriteMany(ref MemoryBuffer writer, INetSerializable[] packets) { for (int i = 0; i < packets.Length; i++) WriteOne(ref writer, packets[i]); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index ab121685..5bbf743f 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -9,6 +9,7 @@ using BeatTogether.LiteNetLib.Configuration; using BeatTogether.LiteNetLib.Enums; using BeatTogether.LiteNetLib.Sources; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; using Serilog; @@ -45,7 +46,7 @@ public PacketSource( _configuration = instconfiguration; } - public override void OnReceive(EndPoint remoteEndPoint, ref SpanBufferReader reader, DeliveryMethod method) + public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, DeliveryMethod method) { if (!reader.TryReadRoutingHeader(out var routingHeader)) { @@ -155,14 +156,14 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBufferReader rea private void RoutePacket(IPlayer sender, (byte SenderId, byte ReceiverId) routingHeader, - ref SpanBufferReader reader, DeliveryMethod deliveryMethod) + ref MemoryBuffer reader, DeliveryMethod deliveryMethod) { routingHeader.SenderId = sender.ConnectionId; - var writer = new SpanBufferWriter(stackalloc byte[412]); + var writer = new MemoryBuffer(GC.AllocateArray(2048)); if (routingHeader.ReceiverId == AllConnectionIds) { writer.WriteRoutingHeader(routingHeader.SenderId, routingHeader.ReceiverId); - writer.WriteBytes(reader.RemainingData); + writer.WriteBytes(reader.RemainingData.Span); _logger.Verbose( $"Routing packet from {routingHeader.SenderId} -> all players " + @@ -170,12 +171,12 @@ private void RoutePacket(IPlayer sender, ); foreach (var player in _playerRegistry.Players) if (player != sender) - _packetDispatcher.Send(player.Endpoint, writer, deliveryMethod); + _packetDispatcher.Send(player.Endpoint, writer.Data, deliveryMethod); } else { writer.WriteRoutingHeader(routingHeader.SenderId, LocalConnectionId); - writer.WriteBytes(reader.RemainingData); + writer.WriteBytes(reader.RemainingData.Span); if (!_playerRegistry.TryGetPlayer(routingHeader.ReceiverId, out var receiver)) { @@ -189,7 +190,7 @@ private void RoutePacket(IPlayer sender, $"Routing packet from {routingHeader.SenderId} -> {routingHeader.ReceiverId} " + $"(Secret='{sender.Secret}', DeliveryMethod={deliveryMethod})." ); - _packetDispatcher.Send(receiver.Endpoint, writer, deliveryMethod); + _packetDispatcher.Send(receiver.Endpoint, writer.Data, deliveryMethod); } } diff --git a/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcPacket.cs b/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcPacket.cs index 7d0f5964..11f848ef 100644 --- a/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcPacket.cs @@ -1,5 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Abstractions { @@ -7,12 +7,21 @@ public abstract class BaseRpcPacket : INetSerializable { public float SyncTime { get; set; } - public virtual void ReadFrom(ref SpanBufferReader reader) + public virtual void ReadFrom(ref SpanBuffer reader) { SyncTime = reader.ReadFloat32(); } - public virtual void WriteTo(ref SpanBufferWriter writer) + public virtual void WriteTo(ref SpanBuffer writer) + { + writer.WriteFloat32(SyncTime); + } + public virtual void ReadFrom(ref MemoryBuffer reader) + { + SyncTime = reader.ReadFloat32(); + } + + public virtual void WriteTo(ref MemoryBuffer writer) { writer.WriteFloat32(SyncTime); } diff --git a/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcWithValuesPacket.cs b/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcWithValuesPacket.cs index cbfcefff..3ec3364c 100644 --- a/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcWithValuesPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcWithValuesPacket.cs @@ -1,4 +1,4 @@ -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Abstractions { @@ -30,13 +30,24 @@ public bool HasValue3 set => HasValues |= (byte) (value ? 8 : 0); } - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); HasValues = reader.ReadUInt8(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteUInt8(HasValues); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + HasValues = reader.ReadUInt8(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteUInt8(HasValues); diff --git a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj index d69e38d7..80ff09bf 100644 --- a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj +++ b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj @@ -9,7 +9,7 @@ - + diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/MemoryBufferExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/MemoryBufferExtensions.cs new file mode 100644 index 00000000..65843dc4 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Extensions/MemoryBufferExtensions.cs @@ -0,0 +1,176 @@ +using BeatTogether.LiteNetLib.Util; +using System; +using System.Diagnostics.CodeAnalysis; +using System.Net; +using System.Text; + +namespace BeatTogether.Extensions +{ + public static class MemoryBufferExtensions + { + public static (byte SenderId, byte ReceiverId) ReadRoutingHeader(this MemoryBuffer reader) => + (reader.ReadUInt8(), reader.ReadUInt8()); + + public static bool TryReadRoutingHeader(this MemoryBuffer reader, [MaybeNullWhen(false)] out (byte SenderId, byte ReceiverId) routingHeader) + { + if (reader.RemainingSize < 2) + { + routingHeader = default; + return false; + } + + routingHeader = (reader.ReadUInt8(), reader.ReadUInt8()); + return true; + } + + public static void WriteRoutingHeader(this MemoryBuffer writer, byte senderId, byte receiverId) + { + writer.WriteUInt8(senderId); + writer.WriteUInt8(receiverId); + } + + public static ulong ReadVarULong(this MemoryBuffer bufferReader) + { + ulong num = 0uL; + int num2 = 0; + byte b = bufferReader.ReadByte(); + while (((ulong)b & 0x80uL) != 0L) + { + num |= ((ulong)b & 0x7FuL) << num2; + num2 += 7; + b = bufferReader.ReadByte(); + } + + return num | ((ulong)b << num2); + } + + public static long ReadVarLong(this MemoryBuffer bufferReader) + { + long num = (long)bufferReader.ReadVarULong(); + if ((num & 1) != 1) + { + return num >> 1; + } + + return -(num >> 1) + 1; + } + + public static uint ReadVarUInt(this MemoryBuffer bufferReader) + { + return (uint)bufferReader.ReadVarULong(); + } + + public static int ReadVarInt(this MemoryBuffer bufferReader) + { + return (int)bufferReader.ReadVarLong(); + } + + public static bool TryReadVarULong(this MemoryBuffer bufferReader, out ulong value) + { + value = 0uL; + int num = 0; + while (num <= 63 && bufferReader.RemainingSize >= 1) + { + byte b = bufferReader.ReadByte(); + value |= (ulong)((long)(b & 0x7F) << num); + num += 7; + if ((b & 0x80) == 0) + { + return true; + } + } + + value = 0uL; + return false; + } + + public static bool TryReadVarUInt(this MemoryBuffer bufferReader, out uint value) + { + if (bufferReader.TryReadVarULong(out var value2) && value2 >> 32 == 0L) + { + value = (uint)value2; + return true; + } + + value = 0u; + return false; + } + + public static ReadOnlySpan ReadVarBytes(this MemoryBuffer bufferReader) + { + uint count = bufferReader.ReadVarUInt(); + return bufferReader.ReadBytes((int)count).Span; + } + + public static string ReadString(this MemoryBuffer bufferReader, int maxLength = 65535) + { + int num = bufferReader.ReadInt32(); + if (num <= 0 || num > maxLength) + { + return string.Empty; + } + + ReadOnlySpan bytes = bufferReader.ReadBytes(num).Span; + return Encoding.UTF8.GetString(bytes); + } + + public static IPEndPoint ReadIPEndPoint(this MemoryBuffer bufferReader) + { + if (!IPAddress.TryParse(bufferReader.ReadString(512), out var address)) + { + throw new ArgumentException("Failed to parse IP address"); + } + + int port = bufferReader.ReadInt32(); + return new IPEndPoint(address, port); + } + public static void WriteVarULong(this MemoryBuffer bufferWriter, ulong value) + { + do + { + byte b = (byte)(value & 0x7F); + value >>= 7; + if (value != 0L) + { + b = (byte)(b | 0x80u); + } + + bufferWriter.WriteUInt8(b); + } + while (value != 0L); + } + + public static void WriteVarLong(this MemoryBuffer bufferWriter, long value) + { + bufferWriter.WriteVarULong((ulong)((value < 0) ? ((-value << 1) - 1) : (value << 1))); + } + + public static void WriteVarUInt(this MemoryBuffer buffer, uint value) + { + buffer.WriteVarULong(value); + } + + public static void WriteVarInt(this MemoryBuffer bufferWriter, int value) + { + bufferWriter.WriteVarLong(value); + } + + public static void WriteVarBytes(this MemoryBuffer bufferWriter, ReadOnlySpan bytes) + { + bufferWriter.WriteVarUInt((uint)bytes.Length); + bufferWriter.WriteBytes(bytes); + } + + public static void WriteString(this MemoryBuffer bufferWriter, string value) + { + bufferWriter.WriteInt32(Encoding.UTF8.GetByteCount(value)); + bufferWriter.WriteBytes(Encoding.UTF8.GetBytes(value)); + } + + public static void WriteIPEndPoint(this MemoryBuffer bufferWriter, IPEndPoint ipEndPoint) + { + bufferWriter.WriteString(ipEndPoint.Address.ToString()); + bufferWriter.WriteInt32(ipEndPoint.Port); + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs new file mode 100644 index 00000000..a8cb591f --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs @@ -0,0 +1,177 @@ +using BeatTogether.LiteNetLib.Util; +using Krypton.Buffers; +using System; +using System.Diagnostics.CodeAnalysis; +using System.Net; +using System.Text; + +namespace BeatTogether.Extensions +{ + public static class SpanBufferExtensions + { + public static (byte SenderId, byte ReceiverId) ReadRoutingHeader(this ref SpanBuffer reader) => + (reader.ReadUInt8(), reader.ReadUInt8()); + + public static bool TryReadRoutingHeader(this ref SpanBuffer reader, [MaybeNullWhen(false)] out (byte SenderId, byte ReceiverId) routingHeader) + { + if (reader.RemainingSize < 2) + { + routingHeader = default; + return false; + } + + routingHeader = (reader.ReadUInt8(), reader.ReadUInt8()); + return true; + } + + public static void WriteRoutingHeader(this ref SpanBuffer writer, byte senderId, byte receiverId) + { + writer.WriteUInt8(senderId); + writer.WriteUInt8(receiverId); + } + + public static ulong ReadVarULong(this ref SpanBuffer bufferReader) + { + ulong num = 0uL; + int num2 = 0; + byte b = bufferReader.ReadByte(); + while (((ulong)b & 0x80uL) != 0L) + { + num |= ((ulong)b & 0x7FuL) << num2; + num2 += 7; + b = bufferReader.ReadByte(); + } + + return num | ((ulong)b << num2); + } + + public static long ReadVarLong(this ref SpanBuffer bufferReader) + { + long num = (long)bufferReader.ReadVarULong(); + if ((num & 1) != 1) + { + return num >> 1; + } + + return -(num >> 1) + 1; + } + + public static uint ReadVarUInt(this ref SpanBuffer bufferReader) + { + return (uint)bufferReader.ReadVarULong(); + } + + public static int ReadVarInt(this ref SpanBuffer bufferReader) + { + return (int)bufferReader.ReadVarLong(); + } + + public static bool TryReadVarULong(this ref SpanBuffer bufferReader, out ulong value) + { + value = 0uL; + int num = 0; + while (num <= 63 && bufferReader.RemainingSize >= 1) + { + byte b = bufferReader.ReadByte(); + value |= (ulong)((long)(b & 0x7F) << num); + num += 7; + if ((b & 0x80) == 0) + { + return true; + } + } + + value = 0uL; + return false; + } + + public static bool TryReadVarUInt(this ref SpanBuffer bufferReader, out uint value) + { + if (bufferReader.TryReadVarULong(out var value2) && value2 >> 32 == 0L) + { + value = (uint)value2; + return true; + } + + value = 0u; + return false; + } + + public static ReadOnlySpan ReadVarBytes(this ref SpanBuffer bufferReader) + { + uint count = bufferReader.ReadVarUInt(); + return bufferReader.ReadBytes((int)count); + } + + public static string ReadString(this ref SpanBuffer bufferReader, int maxLength = 65535) + { + int num = bufferReader.ReadInt32(); + if (num <= 0 || num > maxLength) + { + return string.Empty; + } + + ReadOnlySpan bytes = bufferReader.ReadBytes(num); + return Encoding.UTF8.GetString(bytes); + } + + public static IPEndPoint ReadIPEndPoint(this ref SpanBuffer bufferReader) + { + if (!IPAddress.TryParse(bufferReader.ReadString(512), out var address)) + { + throw new ArgumentException("Failed to parse IP address"); + } + + int port = bufferReader.ReadInt32(); + return new IPEndPoint(address, port); + } + public static void WriteVarULong(this ref SpanBuffer bufferWriter, ulong value) + { + do + { + byte b = (byte)(value & 0x7F); + value >>= 7; + if (value != 0L) + { + b = (byte)(b | 0x80u); + } + + bufferWriter.WriteUInt8(b); + } + while (value != 0L); + } + + public static void WriteVarLong(this ref SpanBuffer bufferWriter, long value) + { + bufferWriter.WriteVarULong((ulong)((value < 0) ? ((-value << 1) - 1) : (value << 1))); + } + + public static void WriteVarUInt(this ref SpanBuffer buffer, uint value) + { + buffer.WriteVarULong(value); + } + + public static void WriteVarInt(this ref SpanBuffer bufferWriter, int value) + { + bufferWriter.WriteVarLong(value); + } + + public static void WriteVarBytes(this ref SpanBuffer bufferWriter, ReadOnlySpan bytes) + { + bufferWriter.WriteVarUInt((uint)bytes.Length); + bufferWriter.WriteBytes(bytes); + } + + public static void WriteString(this ref SpanBuffer bufferWriter, string value) + { + bufferWriter.WriteInt32(Encoding.UTF8.GetByteCount(value)); + bufferWriter.WriteBytes(Encoding.UTF8.GetBytes(value)); + } + + public static void WriteIPEndPoint(this ref SpanBuffer bufferWriter, IPEndPoint ipEndPoint) + { + bufferWriter.WriteString(ipEndPoint.Address.ToString()); + bufferWriter.WriteInt32(ipEndPoint.Port); + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferReaderExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferReaderExtensions.cs deleted file mode 100644 index e3dc07ad..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferReaderExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Krypton.Buffers; -using System.Diagnostics.CodeAnalysis; - -namespace BeatTogether.Extensions -{ - public static class SpanBufferReaderExtensions - { - public static (byte SenderId, byte ReceiverId) ReadRoutingHeader(this ref SpanBufferReader reader) => - (reader.ReadUInt8(), reader.ReadUInt8()); - - public static bool TryReadRoutingHeader(this ref SpanBufferReader reader, [MaybeNullWhen(false)] out (byte SenderId, byte ReceiverId) routingHeader) - { - if (reader.RemainingSize < 2) - { - routingHeader = default; - return false; - } - - routingHeader = (reader.ReadUInt8(), reader.ReadUInt8()); - return true; - } - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferWriterExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferWriterExtensions.cs deleted file mode 100644 index 7edf1f30..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferWriterExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Krypton.Buffers; - -namespace BeatTogether.Extensions -{ - public static class SpanBufferWriterExtensions - { - public static void WriteRoutingHeader(this ref SpanBufferWriter writer, byte senderId, byte receiverId) - { - writer.WriteUInt8(senderId); - writer.WriteUInt8(receiverId); - } - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserRequest.cs b/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserRequest.cs index d5936156..3bc09ba5 100644 --- a/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserRequest.cs +++ b/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserRequest.cs @@ -1,5 +1,5 @@ using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.Extensions; using BeatTogether.LiteNetLib.Extensions; using Krypton.Buffers; diff --git a/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs b/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs index 3ea5a80e..c8d7bc1f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs @@ -1,5 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; using System.Drawing; @@ -24,7 +25,7 @@ public sealed class AvatarData : INetSerializable public string EyesId { get; set; } = "Eyes1"; public string MouthId { get; set; } = "Mouth8"; - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { HeadTopId = reader.ReadString(); HeadTopPrimaryColor = reader.ReadColor(); @@ -45,7 +46,48 @@ public void ReadFrom(ref SpanBufferReader reader) SkinColorId = GlassesId; // Don't ask } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteString(HeadTopId); + writer.WriteColor(HeadTopPrimaryColor); + writer.WriteColor(HandsColor); + writer.WriteString(ClothesId); + writer.WriteColor(ClothesPrimaryColor); + writer.WriteColor(ClothesSecondaryColor); + writer.WriteColor(ClothesDetailColor); + writer.WriteColor(new Color()); + writer.WriteColor(new Color()); + writer.WriteString(EyesId); + writer.WriteString(MouthId); + writer.WriteColor(GlassesColor); + writer.WriteColor(FacialHairColor); + writer.WriteColor(HeadTopSecondaryColor); + writer.WriteString(GlassesId); + writer.WriteString(FacialHairId); + writer.WriteString(HandsId); + } + public void ReadFrom(ref MemoryBuffer reader) + { + HeadTopId = reader.ReadString(); + HeadTopPrimaryColor = reader.ReadColor(); + HandsColor = reader.ReadColor(); + ClothesId = reader.ReadString(); + ClothesPrimaryColor = reader.ReadColor(); + ClothesSecondaryColor = reader.ReadColor(); + ClothesDetailColor = reader.ReadColor(); + reader.SkipBytes(8); + EyesId = reader.ReadString(); + MouthId = reader.ReadString(); + GlassesColor = reader.ReadColor(); + FacialHairColor = reader.ReadColor(); + HeadTopSecondaryColor = reader.ReadColor(); + GlassesId = reader.ReadString(); + FacialHairId = reader.ReadString(); + HandsId = reader.ReadString(); + SkinColorId = GlassesId; // Don't ask + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteString(HeadTopId); writer.WriteColor(HeadTopPrimaryColor); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/BeatmapIdentifier.cs b/BeatTogether.DedicatedServer.Messaging/Models/BeatmapIdentifier.cs index a0911673..6613eaae 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/BeatmapIdentifier.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/BeatmapIdentifier.cs @@ -1,5 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; namespace BeatTogether.DedicatedServer.Messaging.Models @@ -10,14 +11,27 @@ public sealed class BeatmapIdentifier : INetSerializable public string Characteristic { get; set; } = null!; public BeatmapDifficulty Difficulty { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { LevelId = reader.ReadString(); Characteristic = reader.ReadString(); Difficulty = (BeatmapDifficulty)reader.ReadVarUInt(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteString(LevelId); + writer.WriteString(Characteristic); + writer.WriteVarUInt((uint)Difficulty); + } + public void ReadFrom(ref MemoryBuffer reader) + { + LevelId = reader.ReadString(); + Characteristic = reader.ReadString(); + Difficulty = (BeatmapDifficulty)reader.ReadVarUInt(); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteString(LevelId); writer.WriteString(Characteristic); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs index 4d22c22b..46b6b8db 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs @@ -1,4 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; namespace BeatTogether.DedicatedServer.Messaging.Models @@ -31,13 +32,24 @@ public ulong GetBits(int offset, int count) return (ShiftRight(Top, num2) | ShiftRight(Bottom, offset)) & num; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { Top = reader.ReadUInt64(); Bottom = reader.ReadUInt64(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteUInt64(Top); + writer.WriteUInt64(Bottom); + } + public void ReadFrom(ref MemoryBuffer reader) + { + Top = reader.ReadUInt64(); + Bottom = reader.ReadUInt64(); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteUInt64(Top); writer.WriteUInt64(Bottom); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ByteArray.cs b/BeatTogether.DedicatedServer.Messaging/Models/ByteArray.cs index 11bbdc4c..0aa53e26 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ByteArray.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ByteArray.cs @@ -1,5 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; using System; @@ -9,13 +10,24 @@ public sealed class ByteArray : INetSerializable { public byte[]? Data { get; set; } = null; - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { int length = (int)reader.ReadVarUInt(); Data = reader.ReadBytes(length).ToArray(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteVarUInt((Data != null) ? (uint)Data.Length : 0); + writer.WriteBytes(Data); + } + public void ReadFrom(ref MemoryBuffer reader) + { + int length = (int)reader.ReadVarUInt(); + Data = reader.ReadBytes(length).ToArray(); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteVarUInt((Data != null) ? (uint)Data.Length : 0); writer.WriteBytes(Data); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ColorNoAlpha.cs b/BeatTogether.DedicatedServer.Messaging/Models/ColorNoAlpha.cs index a1721669..2086c677 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ColorNoAlpha.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ColorNoAlpha.cs @@ -1,4 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; namespace BeatTogether.DedicatedServer.Messaging.Models @@ -9,14 +10,27 @@ public sealed class ColorNoAlpha : INetSerializable public float g { get; set; } public float b { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { r = reader.ReadFloat32(); g = reader.ReadFloat32(); b = reader.ReadFloat32(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteFloat32(r); + writer.WriteFloat32(g); + writer.WriteFloat32(b); + } + public void ReadFrom(ref MemoryBuffer reader) + { + r = reader.ReadFloat32(); + g = reader.ReadFloat32(); + b = reader.ReadFloat32(); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteFloat32(r); writer.WriteFloat32(g); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ColorScheme.cs b/BeatTogether.DedicatedServer.Messaging/Models/ColorScheme.cs index 3415ab4c..962c040e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ColorScheme.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ColorScheme.cs @@ -1,4 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; namespace BeatTogether.DedicatedServer.Messaging.Models @@ -13,7 +14,7 @@ public sealed class ColorScheme : INetSerializable public ColorNoAlpha EnvironmentColor0Boost { get; set; } = new(); public ColorNoAlpha EnvironmentColor1Boost { get; set; } = new(); - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { SaberAColor.ReadFrom(ref reader); SaberBColor.ReadFrom(ref reader); @@ -24,7 +25,28 @@ public void ReadFrom(ref SpanBufferReader reader) EnvironmentColor1Boost.ReadFrom(ref reader); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + SaberAColor.WriteTo(ref writer); + SaberBColor.WriteTo(ref writer); + ObstaclesColor.WriteTo(ref writer); + EnvironmentColor0.WriteTo(ref writer); + EnvironmentColor1.WriteTo(ref writer); + EnvironmentColor0Boost.WriteTo(ref writer); + EnvironmentColor1Boost.WriteTo(ref writer); + } + public void ReadFrom(ref MemoryBuffer reader) + { + SaberAColor.ReadFrom(ref reader); + SaberBColor.ReadFrom(ref reader); + ObstaclesColor.ReadFrom(ref reader); + EnvironmentColor0.ReadFrom(ref reader); + EnvironmentColor1.ReadFrom(ref reader); + EnvironmentColor0Boost.ReadFrom(ref reader); + EnvironmentColor1Boost.ReadFrom(ref reader); + } + + public void WriteTo(ref MemoryBuffer writer) { SaberAColor.WriteTo(ref writer); SaberBColor.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs index 08dfc565..832880ab 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs @@ -1,7 +1,7 @@ using System; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -20,7 +20,7 @@ public sealed class ConnectionRequestData : INetSerializable // GameLiftClientConnectionRequestHandler public string? PlayerSessionId { get; set; } = null!; - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { Secret = null; PlayerSessionId = null; @@ -51,7 +51,58 @@ public void ReadFrom(ref SpanBufferReader reader) PlayerSessionId = null; } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + if (!string.IsNullOrEmpty(PlayerSessionId)) + { + // GameLift + writer.WriteString(UserId); + writer.WriteString(UserName); + writer.WriteBool(IsConnectionOwner); + writer.WriteString(PlayerSessionId); + } + else + { + // Basic + writer.WriteString(Secret ?? ""); + writer.WriteString(UserId); + writer.WriteString(UserName); + writer.WriteBool(IsConnectionOwner); + } + } + + public void ReadFrom(ref MemoryBuffer reader) + { + Secret = null; + PlayerSessionId = null; + + var initialOffset = reader.Offset; + + // Try to read as a GameLift connection request + try + { + UserId = reader.ReadString(); + UserName = reader.ReadString(); + IsConnectionOwner = reader.ReadBool(); + PlayerSessionId = reader.ReadString(); + } + catch (Exception ex) { } + + if (PlayerSessionId != null && PlayerSessionId.StartsWith(SessionIdPrefix)) + // Read OK, valid session identifier + return; + + // Rewind, try to read as basic request + reader.SkipBytes(initialOffset - reader.Offset); + + Secret = reader.ReadString(); + UserId = reader.ReadString(); + UserName = reader.ReadString(); + IsConnectionOwner = reader.ReadBool(); + PlayerSessionId = null; + } + + public void WriteTo(ref MemoryBuffer writer) { if (!string.IsNullOrEmpty(PlayerSessionId)) { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/GameplayModifiers.cs b/BeatTogether.DedicatedServer.Messaging/Models/GameplayModifiers.cs index 3a195bf4..d8842132 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/GameplayModifiers.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/GameplayModifiers.cs @@ -1,5 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -23,7 +23,7 @@ public sealed class GameplayModifiers : INetSerializable public bool ZenMode { get; set; } public bool SmallCubes { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { int @int = reader.ReadInt32(); Energy = (EnergyType)(@int & 15); @@ -45,7 +45,51 @@ public void ReadFrom(ref SpanBufferReader reader) SmallCubes = (@int & 67108864) != 0; } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + int num = 0; + num |= (int)(Energy & (EnergyType)15); + num |= (DemoNoFail ? 32 : 0); + num |= (InstaFail ? 64 : 0); + num |= (FailOnSaberClash ? 128 : 0); + num |= (int)((int)(EnabledObstacle & (EnabledObstacleType)15) << 8); + num |= (DemoNoObstacles ? 4096 : 0); + num |= (NoBombs ? 8192 : 0); + num |= (FastNotes ? 16384 : 0); + num |= (StrictAngles ? 32768 : 0); + num |= (DisappearingArrows ? 65536 : 0); + num |= (GhostNotes ? 131072 : 0); + num |= (int)((int)(Speed & (SongSpeed)15) << 18); + num |= (NoArrows ? 4194304 : 0); + num |= (NoFailOn0Energy ? 8388608 : 0); + num |= (ProMode ? 16777216 : 0); + num |= (ZenMode ? 33554432 : 0); + num |= (SmallCubes ? 67108864 : 0); + writer.WriteInt32(num); + } + public void ReadFrom(ref MemoryBuffer reader) + { + int @int = reader.ReadInt32(); + Energy = (EnergyType)(@int & 15); + DemoNoFail = (@int & 32) != 0; + InstaFail = (@int & 64) != 0; + FailOnSaberClash = (@int & 128) != 0; + EnabledObstacle = (EnabledObstacleType)(@int >> 8 & 15); + DemoNoObstacles = (@int & 4096) != 0; + NoBombs = (@int & 8192) != 0; + FastNotes = (@int & 16384) != 0; + StrictAngles = (@int & 32768) != 0; + DisappearingArrows = (@int & 65536) != 0; + GhostNotes = (@int & 131072) != 0; + Speed = (GameplayModifiers.SongSpeed)(@int >> 18 & 15); + NoArrows = (@int & 4194304) != 0; + NoFailOn0Energy = (@int & 8388608) != 0; + ProMode = (@int & 16777216) != 0; + ZenMode = (@int & 33554432) != 0; + SmallCubes = (@int & 67108864) != 0; + } + + public void WriteTo(ref MemoryBuffer writer) { int num = 0; num |= (int)(Energy & (EnergyType)15); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs b/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs index b44e79ed..bca5daf7 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -32,7 +32,7 @@ public sealed class LevelCompletionResults : INetSerializable public int MaxCombo { get; set; } public float EndSongTime { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { GameplayModifiers.ReadFrom(ref reader); ModifiedScore = reader.ReadVarInt(); @@ -60,7 +60,62 @@ public void ReadFrom(ref SpanBufferReader reader) EndSongTime = reader.ReadFloat32(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + GameplayModifiers.WriteTo(ref writer); + writer.WriteVarInt(ModifiedScore); + writer.WriteVarInt(MultipliedScore); + writer.WriteVarInt((int)Rank); + writer.WriteBool(FullCombo); + writer.WriteFloat32(LeftSaberMovementDistance); + writer.WriteFloat32(RightSaberMovementDistance); + writer.WriteFloat32(LeftHandMovementDistance); + writer.WriteFloat32(RightHandMovementDistance); + writer.WriteVarInt((int)LevelEndStateType); + writer.WriteVarInt((int)LevelEndAction); + writer.WriteFloat32(Energy); + writer.WriteVarInt(GoodCutsCount); + writer.WriteVarInt(BadCutsCount); + writer.WriteVarInt(MissedCount); + writer.WriteVarInt(NotGoodCount); + writer.WriteVarInt(OkCount); + writer.WriteVarInt(MaxCutScore); + writer.WriteVarInt(TotalCutScore); + writer.WriteVarInt(GoodCutsCountForNotesWithFullScoreScoringType); + writer.WriteFloat32(AverageCenterDistanceCutScoreForNotesWithFullScoreScoringType); + writer.WriteFloat32(AverageCutScoreForNotesWithFullScoreScoringType); + writer.WriteVarInt(MaxCombo); + writer.WriteFloat32(EndSongTime); + } + public void ReadFrom(ref MemoryBuffer reader) + { + GameplayModifiers.ReadFrom(ref reader); + ModifiedScore = reader.ReadVarInt(); + MultipliedScore = reader.ReadVarInt(); + Rank = (Rank)reader.ReadVarInt(); + FullCombo = reader.ReadBool(); + LeftSaberMovementDistance = reader.ReadFloat32(); + RightSaberMovementDistance = reader.ReadFloat32(); + LeftHandMovementDistance = reader.ReadFloat32(); + RightHandMovementDistance = reader.ReadFloat32(); + LevelEndStateType = (LevelEndStateType)reader.ReadVarInt(); + LevelEndAction = (LevelEndAction)reader.ReadVarInt(); + Energy = reader.ReadFloat32(); + GoodCutsCount = reader.ReadVarInt(); + BadCutsCount = reader.ReadVarInt(); + MissedCount = reader.ReadVarInt(); + NotGoodCount = reader.ReadVarInt(); + OkCount = reader.ReadVarInt(); + MaxCutScore = reader.ReadVarInt(); + TotalCutScore = reader.ReadVarInt(); + GoodCutsCountForNotesWithFullScoreScoringType = reader.ReadVarInt(); + AverageCenterDistanceCutScoreForNotesWithFullScoreScoringType = reader.ReadFloat32(); + AverageCutScoreForNotesWithFullScoreScoringType = reader.ReadFloat32(); + MaxCombo = reader.ReadVarInt(); + EndSongTime = reader.ReadFloat32(); + } + + public void WriteTo(ref MemoryBuffer writer) { GameplayModifiers.WriteTo(ref writer); writer.WriteVarInt(ModifiedScore); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerLevelCompletionResults.cs b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerLevelCompletionResults.cs index 8ff648c5..c8aa8dcd 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerLevelCompletionResults.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerLevelCompletionResults.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -11,7 +11,7 @@ public sealed class MultiplayerLevelCompletionResults : INetSerializable public MultiplayerPlayerLevelEndReason PlayerLevelEndReason { get; set; } public LevelCompletionResults LevelCompletionResults { get; set; } = new(); - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { PlayerLevelEndState = (MultiplayerPlayerLevelEndState) reader.ReadVarInt(); PlayerLevelEndReason = (MultiplayerPlayerLevelEndReason) reader.ReadVarInt(); @@ -20,7 +20,24 @@ public void ReadFrom(ref SpanBufferReader reader) LevelCompletionResults.ReadFrom(ref reader); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteVarInt((int) PlayerLevelEndState); + writer.WriteVarInt((int) PlayerLevelEndReason); + + if (HasAnyResult()) + LevelCompletionResults.WriteTo(ref writer); + } + public void ReadFrom(ref MemoryBuffer reader) + { + PlayerLevelEndState = (MultiplayerPlayerLevelEndState) reader.ReadVarInt(); + PlayerLevelEndReason = (MultiplayerPlayerLevelEndReason) reader.ReadVarInt(); + + if (HasAnyResult()) + LevelCompletionResults.ReadFrom(ref reader); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteVarInt((int) PlayerLevelEndState); writer.WriteVarInt((int) PlayerLevelEndReason); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/NodePoseSyncState.cs b/BeatTogether.DedicatedServer.Messaging/Models/NodePoseSyncState.cs index 4f147893..f382059f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/NodePoseSyncState.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/NodePoseSyncState.cs @@ -1,5 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -9,14 +9,27 @@ public sealed class NodePoseSyncState : INetSerializable public Pose LeftController { get; set; } public Pose RightController { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { Head.ReadFrom(ref reader); LeftController.ReadFrom(ref reader); RightController.ReadFrom(ref reader); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + Head.WriteTo(ref writer); + LeftController.WriteTo(ref writer); + RightController.WriteTo(ref writer); + } + public void ReadFrom(ref MemoryBuffer reader) + { + Head.ReadFrom(ref reader); + LeftController.ReadFrom(ref reader); + RightController.ReadFrom(ref reader); + } + + public void WriteTo(ref MemoryBuffer writer) { Head.WriteTo(ref writer); LeftController.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/NoteCutInfo.cs b/BeatTogether.DedicatedServer.Messaging/Models/NoteCutInfo.cs index 0ac8954a..45fd5fff 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/NoteCutInfo.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/NoteCutInfo.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -23,7 +23,7 @@ public sealed class NoteCutInfo : INetSerializable public float TimeToNextNote { get; set; } public Vector3 MoveVec { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { CutWasOk = reader.ReadUInt8(); SaberSpeed = reader.ReadFloat32(); @@ -42,7 +42,44 @@ public void ReadFrom(ref SpanBufferReader reader) MoveVec.ReadFrom(ref reader); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteUInt8(CutWasOk); + writer.WriteFloat32(SaberSpeed); + SaberDir.WriteTo(ref writer); + CutPoint.WriteTo(ref writer); + CutNormal.WriteTo(ref writer); + NotePosition.WriteTo(ref writer); + NoteScale.WriteTo(ref writer); + NoteRotation.WriteTo(ref writer); + writer.WriteVarInt((int)GameplayType); + writer.WriteVarInt(ColorType); + writer.WriteVarInt(LineLayer); + writer.WriteVarInt(NoteLineIndex); + writer.WriteFloat32(NoteTime); + writer.WriteFloat32(TimeToNextNote); + MoveVec.WriteTo(ref writer); + } + public void ReadFrom(ref MemoryBuffer reader) + { + CutWasOk = reader.ReadUInt8(); + SaberSpeed = reader.ReadFloat32(); + SaberDir.ReadFrom(ref reader); + CutPoint.ReadFrom(ref reader); + CutNormal.ReadFrom(ref reader); + NotePosition.ReadFrom(ref reader); + NoteScale.ReadFrom(ref reader); + NoteRotation.ReadFrom(ref reader); + GameplayType = (NoteGameplayType) reader.ReadVarInt(); + ColorType = reader.ReadVarInt(); + LineLayer = reader.ReadVarInt(); + NoteLineIndex = reader.ReadVarInt(); + NoteTime = reader.ReadFloat32(); + TimeToNextNote = reader.ReadFloat32(); + MoveVec.ReadFrom(ref reader); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteUInt8(CutWasOk); writer.WriteFloat32(SaberSpeed); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/NoteMissInfo.cs b/BeatTogether.DedicatedServer.Messaging/Models/NoteMissInfo.cs index 0588997a..81ef67c1 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/NoteMissInfo.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/NoteMissInfo.cs @@ -1,6 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -11,7 +11,7 @@ public sealed class NoteMissInfo : INetSerializable public int NoteLineIndex { get; set; } public float NoteTime { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { ColorType = reader.ReadVarInt(); NoteLineLayer = reader.ReadVarInt(); @@ -19,7 +19,22 @@ public void ReadFrom(ref SpanBufferReader reader) NoteTime = reader.ReadFloat32(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteVarInt(ColorType); + writer.WriteVarInt(NoteLineLayer); + writer.WriteVarInt(NoteLineIndex); + writer.WriteFloat32(NoteTime); + } + public void ReadFrom(ref MemoryBuffer reader) + { + ColorType = reader.ReadVarInt(); + NoteLineLayer = reader.ReadVarInt(); + NoteLineIndex = reader.ReadVarInt(); + NoteTime = reader.ReadFloat32(); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteVarInt(ColorType); writer.WriteVarInt(NoteLineLayer); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/PlayerPermissionConfiguration.cs b/BeatTogether.DedicatedServer.Messaging/Models/PlayerPermissionConfiguration.cs index 35184bc5..0f01fa4e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/PlayerPermissionConfiguration.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/PlayerPermissionConfiguration.cs @@ -1,6 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -13,7 +13,7 @@ public sealed class PlayerPermissionConfiguration : INetSerializable public bool HasKickVotePermission { get; set; } public bool HasInvitePermission { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { UserId = reader.ReadString(); byte num = reader.ReadUInt8(); @@ -24,7 +24,24 @@ public void ReadFrom(ref SpanBufferReader reader) HasInvitePermission = (num & 16) > 0; } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteString(UserId); + int num = (IsServerOwner ? 1 : 0) | (HasRecommendBeatmapsPermission ? 2 : 0) | (HasRecommendGameplayModifiersPermission ? 4 : 0) | (HasKickVotePermission ? 8 : 0) | (HasInvitePermission ? 16 : 0); + writer.WriteUInt8((byte)num); + } + public void ReadFrom(ref MemoryBuffer reader) + { + UserId = reader.ReadString(); + byte num = reader.ReadUInt8(); + IsServerOwner = (num & 1) > 0; + HasRecommendBeatmapsPermission = (num & 2) > 0; + HasRecommendGameplayModifiersPermission = (num & 4) > 0; + HasKickVotePermission = (num & 8) > 0; + HasInvitePermission = (num & 16) > 0; + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteString(UserId); int num = (IsServerOwner ? 1 : 0) | (HasRecommendBeatmapsPermission ? 2 : 0) | (HasRecommendGameplayModifiersPermission ? 4 : 0) | (HasKickVotePermission ? 8 : 0) | (HasInvitePermission ? 16 : 0); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettings.cs b/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettings.cs index 1899e6e4..a7efdcf4 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettings.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettings.cs @@ -1,6 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -14,7 +14,7 @@ public sealed class PlayerSpecificSettings : INetSerializable public float HeadPosToPlayerHeightOffset { get; set; } public ColorScheme ColorScheme { get; set; } = new(); - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { UserId = reader.ReadString(); UserName = reader.ReadString(); @@ -25,7 +25,28 @@ public void ReadFrom(ref SpanBufferReader reader) ColorScheme.ReadFrom(ref reader); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteString(UserId); + writer.WriteString(UserName); + writer.WriteBool(LeftHanded); + writer.WriteBool(AutomaticPlayerHeight); + writer.WriteFloat32(PlayerHeight); + writer.WriteFloat32(HeadPosToPlayerHeightOffset); + ColorScheme.WriteTo(ref writer); + } + public void ReadFrom(ref MemoryBuffer reader) + { + UserId = reader.ReadString(); + UserName = reader.ReadString(); + LeftHanded = reader.ReadBool(); + AutomaticPlayerHeight = reader.ReadBool(); + PlayerHeight = reader.ReadFloat32(); + HeadPosToPlayerHeightOffset = reader.ReadFloat32(); + ColorScheme.ReadFrom(ref reader); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteString(UserId); writer.WriteString(UserName); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettingsAtStart.cs b/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettingsAtStart.cs index 965cb2a4..c97694a7 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettingsAtStart.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettingsAtStart.cs @@ -1,5 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -7,7 +7,7 @@ public sealed class PlayerSpecificSettingsAtStart : INetSerializable { public PlayerSpecificSettings[] ActivePlayerSpecificSettingsAtStart { get; set; } = null!; - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { int count = reader.ReadInt32(); ActivePlayerSpecificSettingsAtStart = new PlayerSpecificSettings[count]; @@ -17,7 +17,25 @@ public void ReadFrom(ref SpanBufferReader reader) } } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteInt32(ActivePlayerSpecificSettingsAtStart.Length); + foreach(PlayerSpecificSettings playerSpecificSettings in ActivePlayerSpecificSettingsAtStart) + { + playerSpecificSettings.WriteTo(ref writer); + } + } + public void ReadFrom(ref MemoryBuffer reader) + { + int count = reader.ReadInt32(); + ActivePlayerSpecificSettingsAtStart = new PlayerSpecificSettings[count]; + for (int i = 0; i < count; i++) + { + ActivePlayerSpecificSettingsAtStart[i].ReadFrom(ref reader); + } + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteInt32(ActivePlayerSpecificSettingsAtStart.Length); foreach(PlayerSpecificSettings playerSpecificSettings in ActivePlayerSpecificSettingsAtStart) diff --git a/BeatTogether.DedicatedServer.Messaging/Models/PlayersPermissionConfiguration.cs b/BeatTogether.DedicatedServer.Messaging/Models/PlayersPermissionConfiguration.cs index bd510d05..bde47daf 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/PlayersPermissionConfiguration.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/PlayersPermissionConfiguration.cs @@ -1,6 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; -using System; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -8,7 +7,7 @@ public sealed class PlayersPermissionConfiguration : INetSerializable { public PlayerPermissionConfiguration[] PlayersPermission = null!; - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { PlayersPermission = new PlayerPermissionConfiguration[reader.ReadInt32()]; for (int i = 0; i < PlayersPermission.Length; i++) @@ -17,7 +16,24 @@ public void ReadFrom(ref SpanBufferReader reader) } } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteInt32(PlayersPermission.Length); + for (int i = 0; i < PlayersPermission.Length; i++) + { + PlayersPermission[i].WriteTo(ref writer); + } + } + public void ReadFrom(ref MemoryBuffer reader) + { + PlayersPermission = new PlayerPermissionConfiguration[reader.ReadInt32()]; + for (int i = 0; i < PlayersPermission.Length; i++) + { + PlayersPermission[i].ReadFrom(ref reader); + } + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteInt32(PlayersPermission.Length); for (int i = 0; i < PlayersPermission.Length; i++) diff --git a/BeatTogether.DedicatedServer.Messaging/Models/Pose.cs b/BeatTogether.DedicatedServer.Messaging/Models/Pose.cs index 4c50a0f5..5212b4a2 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/Pose.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/Pose.cs @@ -1,4 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; namespace BeatTogether.DedicatedServer.Messaging.Models @@ -8,13 +9,24 @@ public struct Pose : INetSerializable public Vector3 Position { get; set; } public Quaternion Rotation { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { Position.ReadFrom(ref reader); Rotation.ReadFrom(ref reader); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + Position.WriteTo(ref writer); + Rotation.WriteTo(ref writer); + } + public void ReadFrom(ref MemoryBuffer reader) + { + Position.ReadFrom(ref reader); + Rotation.ReadFrom(ref reader); + } + + public void WriteTo(ref MemoryBuffer writer) { Position.WriteTo(ref writer); Rotation.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ProcessingPacketInfo.cs b/BeatTogether.DedicatedServer.Messaging/Models/ProcessingPacketInfo.cs index b3e4ce8e..0a7cbae6 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ProcessingPacketInfo.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ProcessingPacketInfo.cs @@ -2,7 +2,7 @@ namespace BeatTogether.DedicatedServer.Messaging.Models { - public struct ProcessingPacketInfo + public struct ProcessingPacketInfo //TODO this isnt used? { public uint length; public int startPosition; diff --git a/BeatTogether.DedicatedServer.Messaging/Models/Quaternion.cs b/BeatTogether.DedicatedServer.Messaging/Models/Quaternion.cs index 4f08c9fd..ca18d99b 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/Quaternion.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/Quaternion.cs @@ -1,6 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -10,14 +10,27 @@ public struct Quaternion : INetSerializable public int b; public int c; - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { a = reader.ReadVarInt(); b = reader.ReadVarInt(); c = reader.ReadVarInt(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteVarInt(a); + writer.WriteVarInt(b); + writer.WriteVarInt(c); + } + public void ReadFrom(ref MemoryBuffer reader) + { + a = reader.ReadVarInt(); + b = reader.ReadVarInt(); + c = reader.ReadVarInt(); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteVarInt(a); writer.WriteVarInt(b); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/StandardScoreSyncState.cs b/BeatTogether.DedicatedServer.Messaging/Models/StandardScoreSyncState.cs index d5a16e70..5236b564 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/StandardScoreSyncState.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/StandardScoreSyncState.cs @@ -1,6 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -12,7 +12,7 @@ public sealed class StandardScoreSyncState : INetSerializable public int Combo { get; set; } public int Multiplier { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { ModifiedScore = reader.ReadVarInt(); RawScore = reader.ReadVarInt(); @@ -21,7 +21,24 @@ public void ReadFrom(ref SpanBufferReader reader) Multiplier = reader.ReadVarInt(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteVarInt(ModifiedScore); + writer.WriteVarInt(RawScore); + writer.WriteVarInt(ImmediateMaxPossibleScore); + writer.WriteVarInt(Combo); + writer.WriteVarInt(Multiplier); + } + public void ReadFrom(ref MemoryBuffer reader) + { + ModifiedScore = reader.ReadVarInt(); + RawScore = reader.ReadVarInt(); + ImmediateMaxPossibleScore = reader.ReadVarInt(); + Combo = reader.ReadVarInt(); + Multiplier = reader.ReadVarInt(); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteVarInt(ModifiedScore); writer.WriteVarInt(RawScore); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/Vector3.cs b/BeatTogether.DedicatedServer.Messaging/Models/Vector3.cs index 44aa1659..eb997594 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/Vector3.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/Vector3.cs @@ -1,6 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -10,14 +10,27 @@ public struct Vector3 : INetSerializable public int y; public int z; - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { x = reader.ReadVarInt(); y = reader.ReadVarInt(); z = reader.ReadVarInt(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteVarInt(x); + writer.WriteVarInt(y); + writer.WriteVarInt(z); + } + public void ReadFrom(ref MemoryBuffer reader) + { + x = reader.ReadVarInt(); + y = reader.ReadVarInt(); + z = reader.ReadVarInt(); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteVarInt(x); writer.WriteVarInt(y); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/KickPlayerPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/KickPlayerPacket.cs index fa3af2dc..f4fbd0b0 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/KickPlayerPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/KickPlayerPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { @@ -9,12 +9,21 @@ public sealed class KickPlayerPacket : INetSerializable { public DisconnectedReason DisconnectedReason { get; set; } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) { writer.WriteVarInt((int)DisconnectedReason); } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) + { + DisconnectedReason = (DisconnectedReason)reader.ReadVarInt(); + } + public void WriteTo(ref MemoryBuffer writer) + { + writer.WriteVarInt((int)DisconnectedReason); + } + + public void ReadFrom(ref MemoryBuffer reader) { DisconnectedReason = (DisconnectedReason)reader.ReadVarInt(); } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/LevelFinishedPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/LevelFinishedPacket.cs index d7247584..8b42ea85 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/LevelFinishedPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/LevelFinishedPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { @@ -8,14 +8,26 @@ public sealed class LevelFinishedPacket : BaseRpcWithValuesPacket { public MultiplayerLevelCompletionResults Results { get; set; } = new(); - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) Results.ReadFrom(ref reader); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + Results.WriteTo(ref writer); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + Results.ReadFrom(ref reader); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); Results.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteCutPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteCutPacket.cs index ddb5344f..64179377 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteCutPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteCutPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { @@ -9,7 +9,7 @@ public sealed class NoteCutPacket : BaseRpcWithValuesPacket public float SongTime { get; set; } public NoteCutInfo Info { get; set; } = new(); - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) @@ -18,7 +18,22 @@ public override void ReadFrom(ref SpanBufferReader reader) Info.ReadFrom(ref reader); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteFloat32(SongTime); + Info.WriteTo(ref writer); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + SongTime = reader.ReadFloat32(); + if (HasValue1) + Info.ReadFrom(ref reader); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteFloat32(SongTime); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteMissPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteMissPacket.cs index ec9a0c6e..226caded 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteMissPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteMissPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { @@ -9,7 +9,7 @@ public sealed class NoteMissPacket : BaseRpcWithValuesPacket public float SongTime { get; set; } public NoteMissInfo Info { get; set; } = new(); - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) @@ -18,7 +18,22 @@ public override void ReadFrom(ref SpanBufferReader reader) Info.ReadFrom(ref reader); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteFloat32(SongTime); + Info.WriteTo(ref writer); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + SongTime = reader.ReadFloat32(); + if (HasValue1) + Info.ReadFrom(ref reader); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteFloat32(SongTime); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacket.cs index 123053c9..f0ba48dd 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { @@ -8,14 +8,26 @@ public sealed class SetGameplaySceneReadyPacket : BaseRpcWithValuesPacket { public PlayerSpecificSettings PlayerSpecificSettings { get; set; } = new(); - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) PlayerSpecificSettings.ReadFrom(ref reader); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + PlayerSpecificSettings.WriteTo(ref writer); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + PlayerSpecificSettings.ReadFrom(ref reader); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); PlayerSpecificSettings.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneSyncFinishedPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneSyncFinishedPacket.cs index 2ad436b2..4ec0c206 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneSyncFinishedPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneSyncFinishedPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { @@ -10,7 +10,7 @@ public sealed class SetGameplaySceneSyncFinishedPacket : BaseRpcWithValuesPacket public PlayerSpecificSettingsAtStart PlayersAtStart { get; set; } = null!; public string SessionGameId { get; set; } = null!; - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) @@ -19,7 +19,22 @@ public override void ReadFrom(ref SpanBufferReader reader) SessionGameId = reader.ReadString(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + PlayersAtStart.WriteTo(ref writer); + writer.WriteString(SessionGameId); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + PlayersAtStart.ReadFrom(ref reader); + if (HasValue1) + SessionGameId = reader.ReadString(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); PlayersAtStart.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetPlayerDidConnectLatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetPlayerDidConnectLatePacket.cs index 1e3fbb9b..49c03055 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetPlayerDidConnectLatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetPlayerDidConnectLatePacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { @@ -11,7 +11,7 @@ public sealed class SetPlayerDidConnectLatePacket : BaseRpcWithValuesPacket public PlayerSpecificSettingsAtStart PlayersAtStart { get; set; } = new(); public string SessionGameId { get; set; } = null!; - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) @@ -22,7 +22,25 @@ public override void ReadFrom(ref SpanBufferReader reader) SessionGameId = reader.ReadString(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteString(UserId); + PlayersAtStart.WriteTo(ref writer); + writer.WriteString(SessionGameId); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + UserId = reader.ReadString(); + if (HasValue1) + PlayersAtStart.ReadFrom(ref reader); + if (HasValue2) + SessionGameId = reader.ReadString(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteString(UserId); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs index fd76aacd..a713293f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs @@ -1,5 +1,5 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { @@ -7,14 +7,26 @@ public sealed class SetSongStartTimePacket : BaseRpcWithValuesPacket { public float StartTime { get; set; } - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) StartTime = reader.ReadFloat32(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteFloat32(StartTime); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + StartTime = reader.ReadFloat32(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteFloat32(StartTime); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/GetIsEntitledToLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/GetIsEntitledToLevelPacket.cs index 3360ffe0..1ac09535 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/GetIsEntitledToLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/GetIsEntitledToLevelPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -8,14 +8,26 @@ public sealed class GetIsEntitledToLevelPacket : BaseRpcWithValuesPacket { public string LevelId { get; set; } = null!; - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) LevelId = reader.ReadString(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteString(LevelId); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + LevelId = reader.ReadString(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteString(LevelId); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/RequestKickPlayerPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/RequestKickPlayerPacket.cs index 0bb874fd..d8aa404b 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/RequestKickPlayerPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/RequestKickPlayerPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -8,14 +8,26 @@ public sealed class RequestKickPlayerPacket : BaseRpcWithValuesPacket { public string KickedPlayerId { get; set; } = null!; - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) KickedPlayerId = reader.ReadString(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteString(KickedPlayerId); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + KickedPlayerId = reader.ReadString(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteString(KickedPlayerId); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs index 666c460e..36ca72ab 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs @@ -1,5 +1,5 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -7,14 +7,26 @@ public sealed class SetCountdownEndTimePacket : BaseRpcWithValuesPacket { public float CountdownTime { get; set; } - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) CountdownTime = reader.ReadFloat32(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteFloat32(CountdownTime); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + CountdownTime = reader.ReadFloat32(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteFloat32(CountdownTime); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacket.cs index 051d0d11..2d2a4c5c 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -10,7 +10,7 @@ public sealed class SetIsEntitledToLevelPacket : BaseRpcWithValuesPacket public string LevelId { get; set; } = null!; public EntitlementStatus Entitlement { get; set; } - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) @@ -19,7 +19,22 @@ public override void ReadFrom(ref SpanBufferReader reader) Entitlement = (EntitlementStatus)reader.ReadVarInt(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteString(LevelId); + writer.WriteVarInt((int)Entitlement); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + LevelId = reader.ReadString(); + if (HasValue1) + Entitlement = (EntitlementStatus)reader.ReadVarInt(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteString(LevelId); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsInLobbyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsInLobbyPacket.cs index 5f732c73..28b5c79b 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsInLobbyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsInLobbyPacket.cs @@ -1,5 +1,5 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -7,14 +7,26 @@ public sealed class SetIsInLobbyPacket : BaseRpcWithValuesPacket { public bool IsInLobby { get; set; } - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) IsInLobby = reader.ReadBool(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteBool(IsInLobby); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + IsInLobby = reader.ReadBool(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteBool(IsInLobby); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsReadyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsReadyPacket.cs index 1022f621..41340279 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsReadyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsReadyPacket.cs @@ -1,5 +1,5 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -7,14 +7,26 @@ public sealed class SetIsReadyPacket : BaseRpcWithValuesPacket { public bool IsReady { get; set; } - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) IsReady = reader.ReadBool(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteBool(IsReady); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + IsReady = reader.ReadBool(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteBool(IsReady); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsStartButtonEnabledPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsStartButtonEnabledPacket.cs index bc2cdcba..0bc8d8d6 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsStartButtonEnabledPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsStartButtonEnabledPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -9,14 +9,26 @@ public sealed class SetIsStartButtonEnabledPacket : BaseRpcWithValuesPacket { public CannotStartGameReason Reason { get; set; } - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) Reason = (CannotStartGameReason)reader.ReadVarInt(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteVarInt((int)Reason); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + Reason = (CannotStartGameReason)reader.ReadVarInt(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteVarInt((int)Reason); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs index bc3d6bda..82766326 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -9,14 +9,26 @@ public sealed class SetMultiplayerGameStatePacket : BaseRpcWithValuesPacket { public MultiplayerGameState State { get; set; } - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) State = (MultiplayerGameState)reader.ReadVarInt(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteVarInt((int)State); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + State = (MultiplayerGameState)reader.ReadVarInt(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteVarInt((int)State); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetOwnedSongPacksPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetOwnedSongPacksPacket.cs index 53d18136..e6d93e10 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetOwnedSongPacksPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetOwnedSongPacksPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -8,14 +8,26 @@ public sealed class SetOwnedSongPacksPacket : BaseRpcWithValuesPacket { public SongPackMask SongPackMask { get; set; } = new(); - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) SongPackMask.ReadFrom(ref reader); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + SongPackMask?.WriteTo(ref writer); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + SongPackMask.ReadFrom(ref reader); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); SongPackMask?.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersMissingEntitlementsToLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersMissingEntitlementsToLevelPacket.cs index 69ec767d..fc1e9f2e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersMissingEntitlementsToLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersMissingEntitlementsToLevelPacket.cs @@ -1,7 +1,7 @@ using System; using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -9,7 +9,7 @@ public sealed class SetPlayersMissingEntitlementsToLevelPacket : BaseRpcWithValu { public string[] PlayersWithoutEntitlements { get; set; } = Array.Empty(); - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); @@ -23,7 +23,31 @@ public override void ReadFrom(ref SpanBufferReader reader) } } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + + writer.WriteInt32(PlayersWithoutEntitlements.Length); + foreach (string player in PlayersWithoutEntitlements) + { + writer.WriteString(player); + } + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + + if (HasValue0) + { + PlayersWithoutEntitlements = new string[reader.ReadInt32()]; + for (int i = 0; i < PlayersWithoutEntitlements.Length; i++) + { + PlayersWithoutEntitlements[i] = reader.ReadString(); + } + } + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersPermissionConfigurationPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersPermissionConfigurationPacket.cs index afab76f8..5ad619cd 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersPermissionConfigurationPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersPermissionConfigurationPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -8,14 +8,26 @@ public sealed class SetPlayersPermissionConfigurationPacket : BaseRpcWithValuesP { public PlayersPermissionConfiguration PermissionConfiguration { get; set; } = new(); - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) PermissionConfiguration.ReadFrom(ref reader); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + PermissionConfiguration.WriteTo(ref writer); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + PermissionConfiguration.ReadFrom(ref reader); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); PermissionConfiguration.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacket.cs index 1bfc8fd9..c9f3b018 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -8,14 +8,26 @@ public sealed class SetRecommendedBeatmapPacket : BaseRpcWithValuesPacket { public BeatmapIdentifier BeatmapIdentifier { get; set; } = new(); - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) BeatmapIdentifier.ReadFrom(ref reader); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + BeatmapIdentifier.WriteTo(ref writer); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + BeatmapIdentifier.ReadFrom(ref reader); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); BeatmapIdentifier.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacket.cs index 9efbe120..9c197187 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -8,14 +8,26 @@ public sealed class SetRecommendedModifiersPacket : BaseRpcWithValuesPacket { public GameplayModifiers Modifiers { get; set; } = new(); - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) Modifiers.ReadFrom(ref reader); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + Modifiers.WriteTo(ref writer); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + Modifiers.ReadFrom(ref reader); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); Modifiers.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedBeatmap.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedBeatmap.cs index a99d5761..042ba5ea 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedBeatmap.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedBeatmap.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -8,14 +8,26 @@ public sealed class SetSelectedBeatmap : BaseRpcWithValuesPacket { public BeatmapIdentifier Beatmap { get; set; } = new(); - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) Beatmap.ReadFrom(ref reader); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + Beatmap.WriteTo(ref writer); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + Beatmap.ReadFrom(ref reader); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); Beatmap.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedGameplayModifiers.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedGameplayModifiers.cs index 4105932b..7b4ac002 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedGameplayModifiers.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedGameplayModifiers.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -8,14 +8,26 @@ public sealed class SetSelectedGameplayModifiers : BaseRpcWithValuesPacket { public GameplayModifiers Modifiers { get; set; } = new(); - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) Modifiers.ReadFrom(ref reader); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + Modifiers.WriteTo(ref writer); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + Modifiers.ReadFrom(ref reader); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); Modifiers.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs index 7fde4a41..1d0b90cd 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs @@ -1,5 +1,5 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -7,14 +7,26 @@ public sealed class SetStartGameTimePacket : BaseRpcWithValuesPacket { public float StartTime { get; set; } - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) StartTime = reader.ReadFloat32(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteFloat32(StartTime); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + StartTime = reader.ReadFloat32(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteFloat32(StartTime); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs index 731e6d3b..da876d0c 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { @@ -10,7 +10,7 @@ public sealed class StartLevelPacket : BaseRpcWithValuesPacket public GameplayModifiers Modifiers { get; set; } = new(); public float StartTime { get; set; } - public override void ReadFrom(ref SpanBufferReader reader) + public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) @@ -21,7 +21,25 @@ public override void ReadFrom(ref SpanBufferReader reader) StartTime = reader.ReadFloat32(); } - public override void WriteTo(ref SpanBufferWriter writer) + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + Beatmap.WriteTo(ref writer); + Modifiers.WriteTo(ref writer); + writer.WriteFloat32(StartTime); + } + public override void ReadFrom(ref MemoryBuffer reader) + { + base.ReadFrom(ref reader); + if (HasValue0) + Beatmap.ReadFrom(ref reader); + if (HasValue1) + Modifiers.ReadFrom(ref reader); + if (HasValue2) + StartTime = reader.ReadFloat32(); + } + + public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); Beatmap.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/DediPacketSetNewManager.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/DediPacketSetNewManager.cs index 145b4e7a..9abfecec 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/DediPacketSetNewManager.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/DediPacketSetNewManager.cs @@ -1,6 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets { @@ -8,12 +8,21 @@ public sealed class DediPacketSetNewManagerPacket : INetSerializable { public string NewManagerID { get; set; } = null!; - public void WriteTo(ref SpanBufferWriter bufferWriter) + public void WriteTo(ref SpanBuffer bufferWriter) { bufferWriter.WriteString(NewManagerID); } - public void ReadFrom(ref SpanBufferReader bufferReader) + public void ReadFrom(ref SpanBuffer bufferReader) + { + NewManagerID = bufferReader.ReadString(); + } + public void WriteTo(ref MemoryBuffer bufferWriter) + { + bufferWriter.WriteString(NewManagerID); + } + + public void ReadFrom(ref MemoryBuffer bufferReader) { NewManagerID = bufferReader.ReadString(); } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs index 58d5c935..31000e1c 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; using System.Collections.Generic; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets @@ -20,13 +20,56 @@ public sealed class MpBeatmapPacket : INetSerializable public Dictionary requirements = new(); - public void WriteTo(ref SpanBufferWriter bufferWriter) + public void WriteTo(ref SpanBuffer bufferWriter) { throw new System.NotImplementedException(); } + public void WriteTo(ref MemoryBuffer bufferWriter) + { + throw new System.NotImplementedException(); + } + public void ReadFrom(ref SpanBuffer bufferReader) + { + levelHash = bufferReader.ReadString(); + songName = bufferReader.ReadString(); + songSubName = bufferReader.ReadString(); + songAuthorName = bufferReader.ReadString(); + levelAuthorName = bufferReader.ReadString(); + beatsPerMinute = bufferReader.ReadFloat32(); + songDuration = bufferReader.ReadFloat32(); + + characteristic = bufferReader.ReadString(); + difficulty = bufferReader.ReadUInt32(); + + var difficultyCount = bufferReader.ReadByte(); + for (int i = 0; i < difficultyCount; i++) + { + byte difficulty = bufferReader.ReadByte(); + var requirementCount = bufferReader.ReadByte(); + string[] reqsForDifficulty = new string[requirementCount]; + for (int j = 0; j < requirementCount; j++) + reqsForDifficulty[j] = bufferReader.ReadString(); + requirements[difficulty] = reqsForDifficulty; + } + + byte count = bufferReader.ReadByte(); + for (int i = 0; i < count; i++) + { + bufferReader.ReadString(); + bufferReader.ReadString(); + bufferReader.ReadString(); + } + + byte count2 = bufferReader.ReadByte(); + for (int i = 0; i < count2; i++) + { + bufferReader.ReadByte(); + bufferReader.ReadColor(); + } + } - public void ReadFrom(ref SpanBufferReader bufferReader) + public void ReadFrom(ref MemoryBuffer bufferReader) { levelHash = bufferReader.ReadString(); songName = bufferReader.ReadString(); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStateDeltaPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStateDeltaPacket.cs index 4d066fa3..982f7253 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStateDeltaPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStateDeltaPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession { @@ -11,7 +11,7 @@ public sealed class NodePoseSyncStateDeltaPacket : INetSerializable public int TimeOffsetMs { get; set; } public NodePoseSyncState Delta { get; set; } = new(); - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { SyncStateId = reader.ReadUInt8(); TimeOffsetMs = reader.ReadVarInt(); @@ -20,7 +20,22 @@ public void ReadFrom(ref SpanBufferReader reader) Delta.ReadFrom(ref reader); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteUInt8(SyncStateId); + writer.WriteVarInt(TimeOffsetMs); + Delta.WriteTo(ref writer); + } + public void ReadFrom(ref MemoryBuffer reader) + { + SyncStateId = reader.ReadUInt8(); + TimeOffsetMs = reader.ReadVarInt(); + + if (!((SyncStateId & 128) > 0)) + Delta.ReadFrom(ref reader); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteUInt8(SyncStateId); writer.WriteVarInt(TimeOffsetMs); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs index c3aefe4c..68c3debc 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs @@ -1,6 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Extensions; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession { @@ -10,14 +11,27 @@ public sealed class NodePoseSyncStatePacket : INetSerializable public float Time { get; set; } public NodePoseSyncState State { get; set; } = new(); - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { SyncStateId = reader.ReadUInt8(); Time = reader.ReadFloat32(); State.ReadFrom(ref reader); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteUInt8(SyncStateId); + writer.WriteFloat32(Time); + State.WriteTo(ref writer); + } + public void ReadFrom(ref MemoryBuffer reader) + { + SyncStateId = reader.ReadUInt8(); + Time = reader.ReadFloat32(); + State.ReadFrom(ref reader); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteUInt8(SyncStateId); writer.WriteFloat32(Time); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStateDeltaPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStateDeltaPacket.cs index 17cb1827..4da7c9b7 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStateDeltaPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStateDeltaPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession { @@ -11,7 +11,7 @@ public sealed class ScoreSyncStateDeltaPacket : INetSerializable public int TimeOffsetMs { get; set; } public StandardScoreSyncState Delta { get; set; } = new(); - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { SyncStateId = reader.ReadUInt8(); TimeOffsetMs = reader.ReadVarInt(); @@ -19,7 +19,21 @@ public void ReadFrom(ref SpanBufferReader reader) Delta.ReadFrom(ref reader); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteUInt8(SyncStateId); + writer.WriteVarInt(TimeOffsetMs); + Delta.WriteTo(ref writer); + } + public void ReadFrom(ref MemoryBuffer reader) + { + SyncStateId = reader.ReadUInt8(); + TimeOffsetMs = reader.ReadVarInt(); + if (!((SyncStateId & 128) > 0)) + Delta.ReadFrom(ref reader); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteUInt8(SyncStateId); writer.WriteVarInt(TimeOffsetMs); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs index c06b6c5b..4ea635ff 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession { @@ -10,14 +10,27 @@ public sealed class ScoreSyncStatePacket : INetSerializable public float Time { get; set; } public StandardScoreSyncState State { get; set; } = new(); - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { SyncStateId = reader.ReadUInt8(); Time = reader.ReadFloat32(); State.ReadFrom(ref reader); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteUInt8(SyncStateId); + writer.WriteFloat32(Time); + State.WriteTo(ref writer); + } + public void ReadFrom(ref MemoryBuffer reader) + { + SyncStateId = reader.ReadUInt8(); + Time = reader.ReadFloat32(); + State.ReadFrom(ref reader); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteUInt8(SyncStateId); writer.WriteFloat32(Time); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs index 83ddc396..facd8850 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs @@ -1,5 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { @@ -7,12 +7,21 @@ public sealed class PingPacket : INetSerializable { public float PingTime { get; set; } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) { writer.WriteFloat32(PingTime); } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) + { + PingTime = reader.ReadFloat32(); + } + public void WriteTo(ref MemoryBuffer writer) + { + writer.WriteFloat32(PingTime); + } + + public void ReadFrom(ref MemoryBuffer reader) { PingTime = reader.ReadFloat32(); } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerConnectedPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerConnectedPacket.cs index be966fba..4ebf8eca 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerConnectedPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerConnectedPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { @@ -11,7 +11,7 @@ public sealed class PlayerConnectedPacket : INetSerializable public string UserName { get; set; } = null!; public bool IsConnectionOwner { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { RemoteConnectionId = reader.ReadUInt8(); UserId = reader.ReadString(); @@ -19,7 +19,22 @@ public void ReadFrom(ref SpanBufferReader reader) IsConnectionOwner = reader.ReadBool(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteUInt8(RemoteConnectionId); + writer.WriteString(UserId); + writer.WriteString(UserName); + writer.WriteBool(IsConnectionOwner); + } + public void ReadFrom(ref MemoryBuffer reader) + { + RemoteConnectionId = reader.ReadUInt8(); + UserId = reader.ReadString(); + UserName = reader.ReadString(); + IsConnectionOwner = reader.ReadBool(); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteUInt8(RemoteConnectionId); writer.WriteString(UserId); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerDisconnectedPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerDisconnectedPacket.cs index 4cd677d3..eb702a95 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerDisconnectedPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerDisconnectedPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { @@ -9,12 +9,21 @@ public sealed class PlayerDisconnectedPacket : INetSerializable { public DisconnectedReason DisconnectedReason { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { DisconnectedReason = (DisconnectedReason)reader.ReadVarInt(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteVarInt((int)DisconnectedReason); + } + public void ReadFrom(ref MemoryBuffer reader) + { + DisconnectedReason = (DisconnectedReason)reader.ReadVarInt(); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteVarInt((int)DisconnectedReason); } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs index 7ec7763e..6706582f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { @@ -11,7 +11,7 @@ public sealed class PlayerIdentityPacket : INetSerializable public ByteArray Random { get; set; } = new(); public ByteArray PublicEncryptionKey { get; set; } = new(); - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { PlayerState.ReadFrom(ref reader); PlayerAvatar.ReadFrom(ref reader); @@ -19,7 +19,22 @@ public void ReadFrom(ref SpanBufferReader reader) PublicEncryptionKey.ReadFrom(ref reader); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + PlayerState.WriteTo(ref writer); + PlayerAvatar.WriteTo(ref writer); + Random.WriteTo(ref writer); + PublicEncryptionKey.WriteTo(ref writer); + } + public void ReadFrom(ref MemoryBuffer reader) + { + PlayerState.ReadFrom(ref reader); + PlayerAvatar.ReadFrom(ref reader); + Random.ReadFrom(ref reader); + PublicEncryptionKey.ReadFrom(ref reader); + } + + public void WriteTo(ref MemoryBuffer writer) { PlayerState.WriteTo(ref writer); PlayerAvatar.WriteTo(ref writer); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs index 9d9ea872..dc33ee2b 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs @@ -1,5 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { @@ -7,12 +7,21 @@ public sealed class PlayerLatencyPacket : INetSerializable { public float Latency { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { Latency = reader.ReadFloat32(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteFloat32(Latency); + } + public void ReadFrom(ref MemoryBuffer reader) + { + Latency = reader.ReadFloat32(); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteFloat32(Latency); } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerSortOrderPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerSortOrderPacket.cs index 5f2d50ac..41ff307f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerSortOrderPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerSortOrderPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { @@ -9,13 +9,24 @@ public sealed class PlayerSortOrderPacket : INetSerializable public string UserId { get; set; } = null!; public int SortIndex { get; set; } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { UserId = reader.ReadString(); SortIndex = reader.ReadVarInt(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + writer.WriteString(UserId); + writer.WriteVarInt(SortIndex); + } + public void ReadFrom(ref MemoryBuffer reader) + { + UserId = reader.ReadString(); + SortIndex = reader.ReadVarInt(); + } + + public void WriteTo(ref MemoryBuffer writer) { writer.WriteString(UserId); writer.WriteVarInt(SortIndex); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerStatePacket.cs index ac182094..1cc98118 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerStatePacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { @@ -8,12 +8,21 @@ public sealed class PlayerStatePacket : INetSerializable { public PlayerStateHash PlayerState { get; set; } = new(); - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { PlayerState.ReadFrom(ref reader); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) + { + PlayerState.WriteTo(ref writer); + } + public void ReadFrom(ref MemoryBuffer reader) + { + PlayerState.ReadFrom(ref reader); + } + + public void WriteTo(ref MemoryBuffer writer) { PlayerState.WriteTo(ref writer); } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs index 9e15a1f5..0680afb5 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs @@ -1,5 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { @@ -7,12 +7,21 @@ public sealed class PongPacket : INetSerializable { public float PingTime { get; set; } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) { writer.WriteFloat32(PingTime); } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) + { + PingTime = reader.ReadFloat32(); + } + public void WriteTo(ref MemoryBuffer writer) + { + writer.WriteFloat32(PingTime); + } + + public void ReadFrom(ref MemoryBuffer reader) { PingTime = reader.ReadFloat32(); } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs index 7ed76d1c..ac714cd5 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs @@ -1,5 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { @@ -7,12 +7,21 @@ public sealed class SyncTimePacket : INetSerializable { public float SyncTime { get; set; } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) { writer.WriteFloat32(SyncTime); } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) + { + SyncTime = reader.ReadFloat32(); + } + public void WriteTo(ref MemoryBuffer writer) + { + writer.WriteFloat32(SyncTime); + } + + public void ReadFrom(ref MemoryBuffer reader) { SyncTime = reader.ReadFloat32(); } diff --git a/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj b/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj index b2cbd542..947d96f1 100644 --- a/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj +++ b/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj @@ -13,7 +13,7 @@ - + From 5d8242b90e6d47a2282d046f24886866bea6443c Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 17 Apr 2023 19:02:35 +0100 Subject: [PATCH 003/120] Fixed packet reading and sending issues --- .../DedicatedInstance.cs | 3 +- .../Encryption/PacketEncryptionLayer.cs | 14 --------- .../Handshake/UnconnectedDispatcher.cs | 2 +- .../PacketDispatcher.cs | 29 +++++++++-------- .../PacketSource.cs | 31 ++++++++++--------- ...tTogether.DedicatedServer.Messaging.csproj | 2 +- 6 files changed, 34 insertions(+), 47 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 73aaea85..77a516e6 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -246,10 +246,11 @@ public override bool ShouldAcceptConnection(EndPoint endPoint, ref MemoryBuffer } public bool ShouldDenyConnection(EndPoint endPoint, ref MemoryBuffer additionalData) { + SpanBuffer spanBuffer = new(additionalData.RemainingData.Span); var connectionRequestData = new ConnectionRequestData(); try { - connectionRequestData.ReadFrom(ref additionalData); + connectionRequestData.ReadFrom(ref spanBuffer); } catch (Exception e) { diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs index 2af830f7..701ffcec 100644 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs @@ -110,7 +110,6 @@ public void RemoveEncryptedEndPoint(IPEndPoint endPoint) public void ProcessInboundPacket(EndPoint endPoint, ref Span data) { - _logger.Information("Inbound Before decryption: " + BitConverter.ToString(data.ToArray())); var address = ((IPEndPoint) endPoint).Address; if (data.Length == 0) @@ -123,7 +122,6 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Span data) // Received an unencrypted packet - this is valid if the client is still negotiating // Slice out the encryption flag and continue data = data[1..]; - _logger.Information("Inbound After decryption(Unencrypted): " + BitConverter.ToString(data.ToArray())); // TODO Reject unencrypted inbound packets for regular clients past the negotiation stage? return; } @@ -136,8 +134,6 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Span data) data = decryptedData; else data = Array.Empty(); - - _logger.Information("Inbound After decryption: " + BitConverter.ToString(data.ToArray())); return; } @@ -151,7 +147,6 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Span data) } else data = Array.Empty(); - _logger.Information("Inbound After decryption: " + BitConverter.ToString(data.ToArray())); return; } @@ -167,7 +162,6 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Span data) public void ProcessOutBoundPacket(EndPoint endPoint, ref Span data) { - _logger.Information("Before encryption: " + BitConverter.ToString(data.ToArray())); if (!_encryptionParameters.TryGetValue(endPoint, out var encryptionParameters)) { if (_potentialEncryptionParameters.TryGetValue(((IPEndPoint) endPoint).Address, @@ -201,13 +195,11 @@ public void ProcessOutBoundPacket(EndPoint endPoint, ref Span data) bufferWriter.WriteBool(false); // NotEncrypted bufferWriter.WriteBytes(data); } - _logger.Information("After encryption: " + BitConverter.ToString(bufferWriter.Data.ToArray())); data = bufferWriter.Data.ToArray(); } public void ProcessInboundPacket(EndPoint endPoint, ref Memory data) { - _logger.Information("Inbound Before decryption: " + BitConverter.ToString(data.ToArray())); var address = ((IPEndPoint)endPoint).Address; if (data.Length == 0) @@ -220,7 +212,6 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Memory data) // Received an unencrypted packet - this is valid if the client is still negotiating // Slice out the encryption flag and continue data = data[1..]; - _logger.Information("Inbound After decryption(Unencrypted): " + BitConverter.ToString(data.ToArray())); // TODO Reject unencrypted inbound packets for regular clients past the negotiation stage? return; } @@ -233,7 +224,6 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Memory data) data = decryptedData; else data = Array.Empty(); - _logger.Information("Inbound After decryption: " + BitConverter.ToString(data.ToArray())); return; } @@ -247,7 +237,6 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Memory data) } else data = Array.Empty(); - _logger.Information("Inbound After decryption(Unencrypted): " + BitConverter.ToString(data.ToArray())); return; } @@ -262,7 +251,6 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Memory data) public void ProcessOutBoundPacket(EndPoint endPoint, ref Memory data) { - _logger.Information("Before encryption: " + BitConverter.ToString(data.Span.ToArray())); if (!_encryptionParameters.TryGetValue(endPoint, out var encryptionParameters)) { if (_potentialEncryptionParameters.TryGetValue(((IPEndPoint)endPoint).Address, @@ -296,9 +284,7 @@ public void ProcessOutBoundPacket(EndPoint endPoint, ref Memory data) bufferWriter.WriteBool(false); // NotEncrypted bufferWriter.WriteBytes(data.Span); } - _logger.Information("After encryption: " + BitConverter.ToString(bufferWriter.Data.ToArray())); data = new Memory(bufferWriter.Data.ToArray()); - _logger.Information("After encryption & convertBack: " + BitConverter.ToString(data.Span.ToArray())); } diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs index 99d0efc4..f81d2c27 100644 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs @@ -51,7 +51,7 @@ public void Dispose() public void Send(HandshakeSession session, IMessage message, bool retry = false) { - _logger.Information("Sending handshake message of type {MessageType} (EndPoint={EndPoint})", + _logger.Verbose("Sending handshake message of type {MessageType} (EndPoint={EndPoint})", message.GetType().Name, session.EndPoint.ToString()); // Assign request ID to outgoing requests diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index a35fb5de..ecba569e 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -6,7 +6,6 @@ using BeatTogether.LiteNetLib.Dispatchers; using BeatTogether.LiteNetLib.Enums; using BeatTogether.LiteNetLib.Util; -using Krypton.Buffers; using Serilog; using System; using System.Net; @@ -43,7 +42,7 @@ public void SendToNearbyPlayers(INetSerializable packet, DeliveryMethod delivery $"(SenderId={ServerId})" ); - var writer = new MemoryBuffer(GC.AllocateArray(412, true)); + var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); _logger.Verbose("Packet: " + packet.GetType().Name + " Was entered into the spanbuffer correctly, now sending once to each player"); @@ -57,7 +56,7 @@ public void SendToNearbyPlayers(INetSerializable[] packets, DeliveryMethod deliv $"(SenderId={ServerId})" ); - var writer = new MemoryBuffer(GC.AllocateArray(412, true)); + var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); _logger.Verbose("Packets were entered into the spanbuffer correctly, now sending once to each player"); @@ -72,7 +71,7 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, $"(ExcludedId={excludedPlayer.ConnectionId})" ); - var writer = new MemoryBuffer(GC.AllocateArray(412, true)); + var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); @@ -87,7 +86,7 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packe $"(ExcludedId={excludedPlayer.ConnectionId})" ); - var writer = new MemoryBuffer(GC.AllocateArray(412, true)); + var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); @@ -103,7 +102,7 @@ public void SendToEndpoint(EndPoint endpoint, INetSerializable packet, DeliveryM $"(To endpoint ={endpoint})" ); - var writer = new MemoryBuffer(GC.AllocateArray(412, true)); + var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); @@ -116,7 +115,7 @@ public void SendToEndpoint(EndPoint endpoint, INetSerializable[] packets, Delive $"(To endpoint ={endpoint})" ); - var writer = new MemoryBuffer(GC.AllocateArray(412, true)); + var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); @@ -130,7 +129,7 @@ public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, Delivery $"(SenderId={fromPlayer.ConnectionId})" ); - var writer = new MemoryBuffer(GC.AllocateArray(412, true)); + var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteOne(ref writer, packet); @@ -144,7 +143,7 @@ public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, Deliv $"(SenderId={fromPlayer.ConnectionId})" ); - var writer = new MemoryBuffer(GC.AllocateArray(412, true)); + var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteMany(ref writer, packets); @@ -159,7 +158,7 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer $"(SenderId={fromPlayer.ConnectionId}, ReceiverId={LocalConnectionId})." ); - var writer = new MemoryBuffer(GC.AllocateArray(412, true)); + var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteOne(ref writer, packet); Send(toPlayer.Endpoint, writer.Data, deliveryMethod); @@ -172,7 +171,7 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer $"(SenderId={fromPlayer.ConnectionId}, ReceiverId={LocalConnectionId})." ); - var writer = new MemoryBuffer(GC.AllocateArray(412, true)); + var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteMany(ref writer, packets); Send(toPlayer.Endpoint, writer.Data, deliveryMethod); @@ -185,7 +184,7 @@ public void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod $"(SenderId={ServerId}, ReceiverId={LocalConnectionId})." ); - var writer = new MemoryBuffer(GC.AllocateArray(412, true)); + var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); Send(player.Endpoint, writer.Data, deliveryMethod); @@ -198,13 +197,13 @@ public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMet $"(SenderId={ServerId}, ReceiverId={LocalConnectionId})." ); - var writer = new MemoryBuffer(GC.AllocateArray(412, true)); + var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); Send(player.Endpoint, writer.Data, deliveryMethod); } - public void WriteOne(ref MemoryBuffer writer, INetSerializable packet) + public void WriteOne(ref SpanBuffer writer, INetSerializable packet) { var type = packet.GetType(); if (!_packetRegistry.TryGetPacketIds(type, out var packetIds)) @@ -217,7 +216,7 @@ public void WriteOne(ref MemoryBuffer writer, INetSerializable packet) writer.WriteBytes(packetWriter.Data.ToArray()); } - public void WriteMany(ref MemoryBuffer writer, INetSerializable[] packets) + public void WriteMany(ref SpanBuffer writer, INetSerializable[] packets) { for (int i = 0; i < packets.Length; i++) WriteOne(ref writer, packets[i]); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index 5bbf743f..fcc9c68f 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -65,23 +65,24 @@ public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, ); return; } - + SpanBuffer HandleRead = new(reader.RemainingData.ToArray()); + //Is this packet meant to be routed? if (routingHeader.ReceiverId != 0) RoutePacket(sender, routingHeader, ref reader, method); - while (reader.RemainingSize > 0) + while (HandleRead.RemainingSize > 0) { uint length; - try { length = reader.ReadVarUInt(); } + try { length = HandleRead.ReadVarUInt(); } catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); return; } - if (reader.RemainingSize < length) + if (HandleRead.RemainingSize < length) { - _logger.Warning($"Packet fragmented (RemainingSize={reader.RemainingSize}, Expected={length})."); + _logger.Warning($"Packet fragmented (RemainingSize={HandleRead.RemainingSize}, Expected={length})."); return; } - int prevPosition = reader.Offset; + int prevPosition = HandleRead.Offset; INetSerializable? packet; IPacketRegistry packetRegistry = _packetRegistry; while (true) @@ -90,7 +91,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, { byte packetId; try - { packetId = reader.ReadByte(); } + { packetId = HandleRead.ReadByte(); } catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); return; } if (packetRegistry.TryCreatePacket(packetId, out packet)) break; @@ -104,7 +105,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, { string MPCpacketId; try - { MPCpacketId = reader.ReadString(); } + { MPCpacketId = HandleRead.ReadString(); } catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); return; } if (MPCoreRegistry.TryCreatePacket(MPCpacketId, out packet)) break; @@ -115,8 +116,8 @@ public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, if (packet == null) { // skip any unprocessed bytes - var processedBytes = reader.Offset - prevPosition; - try { reader.SkipBytes((int)length - processedBytes); } + var processedBytes = HandleRead.Offset - prevPosition; + try { HandleRead.SkipBytes((int)length - processedBytes); } catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); return; } continue; } @@ -130,21 +131,21 @@ public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, _logger.Verbose($"No handler exists for packet of type '{packetType.Name}'."); // skip any unprocessed bytes - var processedBytes = reader.Offset - prevPosition; - try { reader.SkipBytes((int)length - processedBytes); } + var processedBytes = HandleRead.Offset - prevPosition; + try { HandleRead.SkipBytes((int)length - processedBytes); } catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); return; } continue; } try { - packet.ReadFrom(ref reader); + packet.ReadFrom(ref HandleRead); } catch { // skip any unprocessed bytes - var processedBytes = reader.Offset - prevPosition; - reader.SkipBytes((int)length - processedBytes); + var processedBytes = HandleRead.Offset - prevPosition; + HandleRead.SkipBytes((int)length - processedBytes); continue; } diff --git a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj index 80ff09bf..1c9a0ce3 100644 --- a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj +++ b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj @@ -9,7 +9,7 @@ - + From d186f759b2ebc1e0711528dac23836b1413b3597 Mon Sep 17 00:00:00 2001 From: cubic <79692655+cubicgraphics@users.noreply.github.com> Date: Mon, 17 Apr 2023 19:11:20 +0100 Subject: [PATCH 004/120] Update nuget.yml --- .github/workflows/nuget.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index ce8f7c53..3ed3b839 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -6,6 +6,7 @@ on: - dev - dev-1.29 - dev-1.29-Net6.0 + - dev-1.29-Net6.0-Faster jobs: nuget-1: From 39bc574a1bfd228b81397b98192080f63db74b78 Mon Sep 17 00:00:00 2001 From: cubic Date: Fri, 5 May 2023 12:11:05 +0100 Subject: [PATCH 005/120] Added commands, fixed issues --- ...tTogether.DedicatedServer.Interface.csproj | 2 +- .../Events/LevelCompletionResultsEvent.cs | 10 -- .../Events/PlayerJoinEvent.cs | 7 +- .../Events/PlayerLeaveServerEvent.cs | 2 +- .../Events/SelectedbeatmapEvent.cs | 15 --- .../Events/ServerInGameplayEvent.cs | 3 +- .../Events/UpdateInstanceConfigEvent.cs | 1 - .../Events/UpdatePlayersEvent.cs | 4 + .../Events/UpdateServerEvent.cs | 6 - .../Events/UpdateStatusEvent.cs | 11 -- .../IMatchmakingService.cs | 11 +- .../Abstractions/IDedicatedInstance.cs | 17 +-- .../Abstractions/IPlayer.cs | 10 +- .../Abstractions/ITextCommand.cs | 10 ++ .../Abstractions/ITextCommandRepository.cs | 11 ++ .../AllowChromaCommandHandler.cs | 28 +++++ .../AllowMappingExtensionsHandler.cs | 28 +++++ .../AllowNoodleExtensionsHandler.cs | 28 +++++ .../AllowPerPlayerDiffHandler.cs | 28 +++++ .../AllowPerPlayerModHandler.cs | 28 +++++ .../CommandHandlers/BaseCommandHandler.cs | 23 ++++ .../DisableBeatmapNotesHandler.cs | 28 +++++ .../CommandHandlers/HelpCommandHandler.cs | 49 ++++++++ .../SetCountdownTimeHandler.cs | 28 +++++ .../CommandHandlers/SetResultsTimeHandler.cs | 28 +++++ .../CommandHandlers/SetServerNameHandler.cs | 31 +++++ .../SetWelcomeMessageHandler.cs | 30 +++++ .../StartBeatmapTimeHandler.cs | 28 +++++ .../Commands/AllowChroma.cs | 19 +++ .../Commands/AllowMappingExtensions.cs | 19 +++ .../Commands/AllowNoodle.cs | 19 +++ .../Commands/AllowPerPlayerDifficulties.cs | 19 +++ .../Commands/AllowPerPlayerModifiers.cs | 19 +++ .../Commands/DisableBeatmapNotes.cs | 19 +++ .../Commands/HelpCommand.cs | 19 +++ .../Commands/SetBeatmapStartTime.cs | 19 +++ .../Commands/SetCountdown.cs | 19 +++ .../Commands/SetResultsTime.cs | 19 +++ .../Commands/SetServerName.cs | 19 +++ .../Commands/SetWelcomeMessage.cs | 19 +++ .../Configuration/InstanceConfiguration.cs | 4 + .../DedicatedInstance.cs | 47 +++++--- .../Encryption/PacketEncryptionLayer.cs | 14 +-- .../Enums/AccessLevel.cs | 13 ++ .../Extensions/HostBuilderExtensions.cs | 6 + .../Extensions/ServiceCollectionExtensions.cs | 17 ++- .../Handshake/UnconnectedDispatcher.cs | 2 +- .../Handshake/UnconnectedSource.cs | 7 +- .../Managers/Abstractions/IGameplayManager.cs | 2 +- .../Managers/GameplayManager.cs | 2 +- .../Managers/LobbyManager.cs | 64 ++++++++-- .../PacketDispatcher.cs | 33 ++++-- .../MPChat/MpcCapabilitiesPacketHandler.cs | 48 ++++++++ .../MPChat/MpcTextChatPacketHandler.cs | 54 +++++++++ .../PacketSource.cs | 27 +++-- BeatTogether.DedicatedServer.Kernel/Player.cs | 25 +++- .../TextCommandRepository.cs | 111 ++++++++++++++++++ ...tTogether.DedicatedServer.Messaging.csproj | 2 +- .../AuthenticateGameLiftUserRequest.cs | 1 - .../Models/AvatarData.cs | 41 ------- .../Models/BeatmapIdentifier.cs | 13 -- .../Models/BitMask128.cs | 11 -- .../Models/ByteArray.cs | 11 -- .../Models/ColorNoAlpha.cs | 13 -- .../Models/ColorScheme.cs | 21 ---- .../Models/ConnectionRequestData.cs | 51 -------- .../Models/GameplayModifiers.cs | 44 ------- .../Models/LevelCompletionResults.cs | 55 --------- .../MultiplayerLevelCompletionResults.cs | 17 --- .../Models/NodePoseSyncState.cs | 13 -- .../Models/NoteCutInfo.cs | 37 ------ .../Models/NoteMissInfo.cs | 15 --- .../Models/PlayerPermissionConfiguration.cs | 17 --- .../Models/PlayerSpecificSettings.cs | 21 ---- .../Models/PlayerSpecificSettingsAtStart.cs | 18 --- .../Models/PlayersPermissionConfiguration.cs | 17 --- .../Models/Pose.cs | 11 -- .../Models/ProcessingPacketInfo.cs | 11 -- .../Models/Quaternion.cs | 13 -- .../Models/StandardScoreSyncState.cs | 17 --- .../Models/Vector3.cs | 13 -- .../Packets/KickPlayerPacket.cs | 9 -- .../GameplayRpc/LevelFinishedPacket.cs | 12 -- .../GameplayRpc/NoteCutPacket.cs | 15 --- .../GameplayRpc/NoteMissPacket.cs | 15 --- .../GameplayRpc/NoteSpawn.cs | 17 +++ .../GameplayRpc/ObstacleSpawnPacket.cs | 17 +++ .../SetGameplaySceneReadyPacket.cs | 12 -- .../SetGameplaySceneSyncFinishedPacket.cs | 15 --- .../SetPlayerDidConnectLatePacket.cs | 18 --- .../GameplayRpc/SetSongStartTimePacket.cs | 12 -- .../GameplayRpc/SliderSpawnPacket.cs | 17 +++ .../MPChatPackets/MpcBasePacket.cs | 26 ++++ .../MPChatPackets/MpcCapabilitiesPacket.cs | 30 +++++ .../MPChatPackets/MpcTextChatPacket.cs | 25 ++++ .../MenuRpc/GetIsEntitledToLevelPacket.cs | 12 -- .../MenuRpc/RequestKickPlayerPacket.cs | 12 -- .../MenuRpc/SetCountdownEndTimePacket.cs | 12 -- .../MenuRpc/SetIsEntitledToLevelPacket.cs | 15 --- .../MenuRpc/SetIsInLobbyPacket.cs | 12 -- .../MenuRpc/SetIsReadyPacket.cs | 12 -- .../MenuRpc/SetIsStartButtonEnabledPacket.cs | 12 -- .../MenuRpc/SetMultiplayerGameStatePacket.cs | 12 -- .../MenuRpc/SetOwnedSongPacksPacket.cs | 12 -- ...PlayersMissingEntitlementsToLevelPacket.cs | 24 ---- ...SetPlayersPermissionConfigurationPacket.cs | 12 -- .../MenuRpc/SetRecommendedBeatmapPacket.cs | 12 -- .../MenuRpc/SetRecommendedModifiersPacket.cs | 12 -- .../MenuRpc/SetSelectedBeatmap.cs | 12 -- .../MenuRpc/SetSelectedGameplayModifiers.cs | 12 -- .../MenuRpc/SetStartGameTimePacket.cs | 12 -- .../MenuRpc/StartLevelPacket.cs | 18 --- .../MpCorePackets/DediPacketSetNewManager.cs | 9 -- .../MpCorePackets/MpBeatmapPacket.cs | 46 -------- .../NodePoseSyncStateDeltaPacket.cs | 15 --- .../NodePoseSyncStatePacket.cs | 13 -- .../ScoreSyncStateDeltaPacket.cs | 14 --- .../ScoreSyncStatePacket.cs | 13 -- .../Packets/PingPacket.cs | 9 -- .../Packets/PlayerConnectedPacket.cs | 15 --- .../Packets/PlayerDisconnectedPacket.cs | 9 -- .../Packets/PlayerIdentityPacket.cs | 15 --- .../Packets/PlayerLatencyPacket.cs | 9 -- .../Packets/PlayerSortOrderPacket.cs | 11 -- .../Packets/PlayerStatePacket.cs | 9 -- .../Packets/PongPacket.cs | 9 -- .../Packets/SyncTimePacket.cs | 9 -- .../Registries/GameplayRpcPacketRegistry.cs | 3 + .../MultiplayerCorePacketRegistry.cs | 10 +- .../Configuration/NodeConfiguration.cs | 2 +- .../MasterServerEventHandler.cs | 6 +- .../NodeService.cs | 79 +++---------- 132 files changed, 1235 insertions(+), 1227 deletions(-) delete mode 100644 BeatTogether.DedicatedServer.Interface/Events/LevelCompletionResultsEvent.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Events/SelectedbeatmapEvent.cs create mode 100644 BeatTogether.DedicatedServer.Interface/Events/UpdatePlayersEvent.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Events/UpdateServerEvent.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Events/UpdateStatusEvent.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Abstractions/ITextCommand.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Abstractions/ITextCommandRepository.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowChromaCommandHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowMappingExtensionsHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowNoodleExtensionsHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerDiffHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerModHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/BaseCommandHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/DisableBeatmapNotesHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/HelpCommandHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetCountdownTimeHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetResultsTimeHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetServerNameHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetWelcomeMessageHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/StartBeatmapTimeHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/AllowChroma.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/AllowMappingExtensions.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/AllowNoodle.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerDifficulties.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerModifiers.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/DisableBeatmapNotes.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/HelpCommand.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/SetBeatmapStartTime.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/SetCountdown.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/SetResultsTime.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/SetServerName.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/SetWelcomeMessage.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Enums/AccessLevel.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Models/ProcessingPacketInfo.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteSpawn.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/ObstacleSpawnPacket.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SliderSpawnPacket.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcBasePacket.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcCapabilitiesPacket.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcTextChatPacket.cs diff --git a/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj b/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj index ec8bfa1c..2bb0eb53 100644 --- a/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj +++ b/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj @@ -7,7 +7,7 @@ BeatTogether Team BeatTogether https://github.com/beattogether/BeatTogether.DedicatedServer - 1.6.0 + 1.6.2 enable diff --git a/BeatTogether.DedicatedServer.Interface/Events/LevelCompletionResultsEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/LevelCompletionResultsEvent.cs deleted file mode 100644 index 8c9b7e64..00000000 --- a/BeatTogether.DedicatedServer.Interface/Events/LevelCompletionResultsEvent.cs +++ /dev/null @@ -1,10 +0,0 @@ -using BeatTogether.DedicatedServer.Interface.Models; -using System.Collections.Generic; - -namespace BeatTogether.DedicatedServer.Interface.Events -{ - public sealed record LevelCompletionResultsEvent( - string Secret, - BeatmapIdentifier Beatmap, - List<(string, BeatmapDifficulty, LevelCompletionResults)> Results); -} diff --git a/BeatTogether.DedicatedServer.Interface/Events/PlayerJoinEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/PlayerJoinEvent.cs index c27619c0..9d687e13 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/PlayerJoinEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/PlayerJoinEvent.cs @@ -1,7 +1,4 @@ -using BeatTogether.DedicatedServer.Interface.Models; -using System.Net; - -namespace BeatTogether.DedicatedServer.Interface.Events +namespace BeatTogether.DedicatedServer.Interface.Events { - public sealed record PlayerJoinEvent(string Secret, string EndPoint, string UserId, string UserName, byte ConnectionId, int SortId, AvatarData AvatarData); + public sealed record PlayerJoinEvent(string Secret, string EndPoint, string UserId); } diff --git a/BeatTogether.DedicatedServer.Interface/Events/PlayerLeaveServerEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/PlayerLeaveServerEvent.cs index 44dbe155..d60b78a2 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/PlayerLeaveServerEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/PlayerLeaveServerEvent.cs @@ -2,5 +2,5 @@ namespace BeatTogether.DedicatedServer.Interface.Events { - public sealed record PlayerLeaveServerEvent(string Secret, string UserId, string endPoint, int NewPlayerCount); + public sealed record PlayerLeaveServerEvent(string Secret, string UserId, string endPoint); } diff --git a/BeatTogether.DedicatedServer.Interface/Events/SelectedbeatmapEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/SelectedbeatmapEvent.cs deleted file mode 100644 index d4320dd6..00000000 --- a/BeatTogether.DedicatedServer.Interface/Events/SelectedbeatmapEvent.cs +++ /dev/null @@ -1,15 +0,0 @@ -using BeatTogether.DedicatedServer.Interface.Models; -using System; - -namespace BeatTogether.DedicatedServer.Interface.Events -{ - public sealed record SelectedBeatmapEvent( - string Secret, - string LevelId, - string Characteristic, - uint Difficulty, - bool Gameplay, - GameplayModifiers GameplayModifiers, - DateTime CountdownEnd //If in gameplay then this is when the beatmap started - ); -} diff --git a/BeatTogether.DedicatedServer.Interface/Events/ServerInGameplayEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/ServerInGameplayEvent.cs index c618bf7c..e314e29c 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/ServerInGameplayEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/ServerInGameplayEvent.cs @@ -3,6 +3,7 @@ namespace BeatTogether.DedicatedServer.Interface.Events { public sealed record ServerInGameplayEvent( string Secret, - bool InGame + bool InGame, + string LevelID ); } diff --git a/BeatTogether.DedicatedServer.Interface/Events/UpdateInstanceConfigEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/UpdateInstanceConfigEvent.cs index 74a92be0..a30a95e2 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/UpdateInstanceConfigEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/UpdateInstanceConfigEvent.cs @@ -4,7 +4,6 @@ namespace BeatTogether.DedicatedServer.Interface.Events { public sealed record UpdateInstanceConfigEvent( string Secret, //Cannot change the secret - string Code, //Use special mod to change this (patreon only or something) string ServerName, GameplayServerConfiguration Configuration); } diff --git a/BeatTogether.DedicatedServer.Interface/Events/UpdatePlayersEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/UpdatePlayersEvent.cs new file mode 100644 index 00000000..a84d13aa --- /dev/null +++ b/BeatTogether.DedicatedServer.Interface/Events/UpdatePlayersEvent.cs @@ -0,0 +1,4 @@ +namespace BeatTogether.DedicatedServer.Interface.Events +{ + public sealed record UpdatePlayersEvent(string Secret, string[] Users); +} diff --git a/BeatTogether.DedicatedServer.Interface/Events/UpdateServerEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/UpdateServerEvent.cs deleted file mode 100644 index 4e786a0d..00000000 --- a/BeatTogether.DedicatedServer.Interface/Events/UpdateServerEvent.cs +++ /dev/null @@ -1,6 +0,0 @@ -using BeatTogether.DedicatedServer.Interface.Models; - -namespace BeatTogether.DedicatedServer.Interface.Events -{ - public sealed record UpdateServerEvent(string Secret, GameplayServerConfiguration Configuration, int Port, string ManagerId, string ServerId, string ServerName, float DestroyInstanceTimeout, string ConstantManager, bool PerPlayerDifficulties, bool PerPlayerModifiers, bool Chroma, bool MappingExtensions, bool NoodleExtensions, float KickBeforeEntitlementTimeout, float ReadyCountdownTime, float MapStartCountdownTime, float ResultsTime); -} diff --git a/BeatTogether.DedicatedServer.Interface/Events/UpdateStatusEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/UpdateStatusEvent.cs deleted file mode 100644 index c70b0264..00000000 --- a/BeatTogether.DedicatedServer.Interface/Events/UpdateStatusEvent.cs +++ /dev/null @@ -1,11 +0,0 @@ -using BeatTogether.DedicatedServer.Interface.Enums; - -namespace BeatTogether.DedicatedServer.Interface.Events -{ - public sealed record UpdateStatusEvent( - string Secret, - CountdownState CountdownState, - MultiplayerGameState GameState, - GameplayState GameplayState - ); -} diff --git a/BeatTogether.DedicatedServer.Interface/IMatchmakingService.cs b/BeatTogether.DedicatedServer.Interface/IMatchmakingService.cs index 3af5f399..d5950f39 100644 --- a/BeatTogether.DedicatedServer.Interface/IMatchmakingService.cs +++ b/BeatTogether.DedicatedServer.Interface/IMatchmakingService.cs @@ -17,17 +17,14 @@ public override void Build(IServiceContractBuilder builder) => .UseName("DedicatedServer") .AddInterface() .AddEvent() + .AddEvent() + .AddEvent() .AddEvent() .AddEvent() .AddEvent() .AddEvent() - //.AddEvent() - .AddEvent() - //.AddEvent() - //.AddEvent() - //.AddEvent() - .AddEvent() - .AddEvent(); + .AddEvent() + .AddEvent(); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs index 0c7c2386..8db9f94f 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs @@ -11,20 +11,13 @@ public interface IDedicatedInstance { //event Action StartEvent; event Action StopEvent; - event Action PlayerConnectedEvent; - event Action PlayerDisconnectedEvent; - event Action PlayerDisconnectBeforeJoining; + event Action PlayerConnectedEvent; + event Action PlayerDisconnectedEvent; + event Action PlayerDisconnectBeforeJoining; event Action GameIsInLobby; - //event Action StateChangedEvent; - //event Action UpdateInstanceEvent; - //event Action UpdateBeatmapEvent; - //event Action> LevelFinishedEvent; + event Action UpdateInstanceEvent; - //void PlayerUpdated(IPlayer player); - //void InstanceStateChanged(CountdownState countdown, GameplayManagerState gameplay); - //void BeatmapChanged(BeatmapIdentifier? map, GameplayModifiers modifiers, bool IsGameplay, DateTime CountdownEnd); - //void LevelFinished(BeatmapIdentifier beatmap, List<(string, BeatmapDifficulty, LevelCompletionResults)> Results); - //void InstanceChanged(); + void InstanceConfigUpdated(); InstanceConfiguration _configuration { get; } bool IsRunning { get; } float RunTime { get; } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index a89c49f1..7ae79bde 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Types; +using BeatTogether.DedicatedServer.Kernel.Enums; +using BeatTogether.DedicatedServer.Kernel.Types; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; using System.Net; @@ -53,6 +54,13 @@ public interface IPlayer object InLobbyLock { get; set; } bool InLobby { get; set; } object EntitlementLock { get; set; } + bool IsPatreon { get; set; } + object MPChatLock { get; set; } + bool CanTextChat { get; set; } + public bool CanReceiveVoiceChat { get; set; } + public bool CanTransmitVoiceChat { get; set; } + public AccessLevel GetAccessLevel(); + public void SetAccessLevel(AccessLevel newAccessLevel); EntitlementStatus GetEntitlement(string levelId); void SetEntitlement(string levelId, EntitlementStatus entitlement); bool UpdateEntitlement { get; set; } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/ITextCommand.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/ITextCommand.cs new file mode 100644 index 00000000..dc8bd381 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/ITextCommand.cs @@ -0,0 +1,10 @@ +namespace BeatTogether.DedicatedServer.Kernel.Abstractions +{ + public interface ITextCommand + { + string CommandName { get; } + string ShortHandName { get; } + string Description { get; } + public void ReadValues(string[] Values); + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/ITextCommandRepository.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/ITextCommandRepository.cs new file mode 100644 index 00000000..0ce12844 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/ITextCommandRepository.cs @@ -0,0 +1,11 @@ +using BeatTogether.DedicatedServer.Kernel.Enums; + +namespace BeatTogether.DedicatedServer.Kernel.Abstractions +{ + public interface ITextCommandRepository + { + bool GetCommand(string[] commandValues, AccessLevel accessLevel, out ITextCommand Command); + void RegisterCommand(AccessLevel accessLevel) where T : class, ITextCommand, new(); + string[] GetTextCommandNames(AccessLevel accessLevel); + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowChromaCommandHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowChromaCommandHandler.cs new file mode 100644 index 00000000..f16cccfc --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowChromaCommandHandler.cs @@ -0,0 +1,28 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class AllowChromaHandler : BaseCommandHandler + { + private readonly IPacketDispatcher _packetDisapatcher; + private readonly InstanceConfiguration _Configuration; + + public AllowChromaHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + { + _packetDisapatcher = packetDisapatcher; + _Configuration = instanceConfiguration; + } + + public override void Handle(IPlayer player, AllowChroma command) + { + _Configuration.AllowChroma = command.Enabled; + _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket + { + Text = "Allow Chroma is: " + command.Enabled + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowMappingExtensionsHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowMappingExtensionsHandler.cs new file mode 100644 index 00000000..d5b502ef --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowMappingExtensionsHandler.cs @@ -0,0 +1,28 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class AllowMappingExtensionsHandler : BaseCommandHandler + { + private readonly IPacketDispatcher _packetDisapatcher; + private readonly InstanceConfiguration _Configuration; + + public AllowMappingExtensionsHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + { + _packetDisapatcher = packetDisapatcher; + _Configuration = instanceConfiguration; + } + + public override void Handle(IPlayer player, AllowMappingExtensions command) + { + _Configuration.AllowMappingExtensions = command.Enabled; + _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket + { + Text = "Allow Mapping Extensions is: " + command.Enabled + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowNoodleExtensionsHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowNoodleExtensionsHandler.cs new file mode 100644 index 00000000..37b216db --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowNoodleExtensionsHandler.cs @@ -0,0 +1,28 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class AllowNoodleExtensionsHandler : BaseCommandHandler + { + private readonly IPacketDispatcher _packetDisapatcher; + private readonly InstanceConfiguration _Configuration; + + public AllowNoodleExtensionsHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + { + _packetDisapatcher = packetDisapatcher; + _Configuration = instanceConfiguration; + } + + public override void Handle(IPlayer player, AllowNoodle command) + { + _Configuration.AllowNoodleExtensions = command.Enabled; + _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket + { + Text = "Allow Noodle is: " + command.Enabled + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerDiffHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerDiffHandler.cs new file mode 100644 index 00000000..ec5f4ef1 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerDiffHandler.cs @@ -0,0 +1,28 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class AllowPerPlayerDiffHandler : BaseCommandHandler + { + private readonly IPacketDispatcher _packetDisapatcher; + private readonly InstanceConfiguration _Configuration; + + public AllowPerPlayerDiffHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + { + _packetDisapatcher = packetDisapatcher; + _Configuration = instanceConfiguration; + } + + public override void Handle(IPlayer player, AllowPerPlayerDifficulties command) + { + _Configuration.AllowPerPlayerDifficulties = command.Enabled; + _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket + { + Text = "Allow per player difficulties is: " + command.Enabled + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerModHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerModHandler.cs new file mode 100644 index 00000000..cdd033d0 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerModHandler.cs @@ -0,0 +1,28 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class AllowPerPlayerModHandler : BaseCommandHandler + { + private readonly IPacketDispatcher _packetDisapatcher; + private readonly InstanceConfiguration _Configuration; + + public AllowPerPlayerModHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + { + _packetDisapatcher = packetDisapatcher; + _Configuration = instanceConfiguration; + } + + public override void Handle(IPlayer player, AllowPerPlayerModifiers command) + { + _Configuration.AllowPerPlayerModifiers = command.Enabled; + _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket + { + Text = "Allow per player modifiers is: " + command.Enabled + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/BaseCommandHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/BaseCommandHandler.cs new file mode 100644 index 00000000..65d57ac5 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/BaseCommandHandler.cs @@ -0,0 +1,23 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.CommandHandlers +{ + public interface ICommandHandler + { + void Handle(IPlayer sender, ITextCommand command); + } + + public interface ICommandHandler : ICommandHandler + where TCommand : class, ITextCommand + { + void Handle(IPlayer sender, TCommand command); + } + + public abstract class BaseCommandHandler : ICommandHandler where Tcommand : class, ITextCommand + { + public abstract void Handle(IPlayer sender, Tcommand command); + + public void Handle(IPlayer sender, ITextCommand command) + => Handle(sender, (Tcommand)command); + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/DisableBeatmapNotesHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/DisableBeatmapNotesHandler.cs new file mode 100644 index 00000000..022de726 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/DisableBeatmapNotesHandler.cs @@ -0,0 +1,28 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class DisableBeatmapNotesHandler : BaseCommandHandler + { + private readonly IPacketDispatcher _packetDisapatcher; + private readonly InstanceConfiguration _Configuration; + + public DisableBeatmapNotesHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + { + _packetDisapatcher = packetDisapatcher; + _Configuration = instanceConfiguration; + } + + public override void Handle(IPlayer player, DisableBeatmapNotes command) + { + _Configuration.DisableNotes = command.Disabled; + _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket + { + Text = "Disabled beatmap notes is: " + command.Disabled + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/HelpCommandHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/HelpCommandHandler.cs new file mode 100644 index 00000000..ca5007ab --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/HelpCommandHandler.cs @@ -0,0 +1,49 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; +using System.Text; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class HelpCommandHandler : BaseCommandHandler + { + private readonly ITextCommandRepository _commandRepository; + private readonly IPacketDispatcher _packetDisapatcher; + + public HelpCommandHandler(ITextCommandRepository commandRepository, IPacketDispatcher packetDisapatcher) + { + _commandRepository = commandRepository; + _packetDisapatcher = packetDisapatcher; + } + + public override void Handle(IPlayer player, HelpCommand command) + { + if (command.SpecificCommandName != null) + { + if (!_commandRepository.GetCommand(command.SpecificCommandName, player.GetAccessLevel(), out var textCommand)) + { + _packetDisapatcher.SendToPlayer(player, new MpcTextChatPacket + { + Text = "Command you searched help for does not exist or is above your access level" + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + _packetDisapatcher.SendToPlayer(player, new MpcTextChatPacket + { + Text = textCommand.CommandName + " : " + textCommand.Description + " : ShortHand: " + textCommand.ShortHandName + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + return; + } + string[] CommandList = _commandRepository.GetTextCommandNames(player.GetAccessLevel()); + StringBuilder Response = new(); + Response.Append("Command List: "); + for (int i = 0; i < CommandList.Length; i++) + { + Response.Append("/" + CommandList[i] + " : "); + } + _packetDisapatcher.SendToPlayer(player, new MpcTextChatPacket + { + Text = Response.ToString() + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetCountdownTimeHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetCountdownTimeHandler.cs new file mode 100644 index 00000000..4d7152c0 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetCountdownTimeHandler.cs @@ -0,0 +1,28 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class SetCountdownTimeHandler : BaseCommandHandler + { + private readonly IPacketDispatcher _packetDisapatcher; + private readonly InstanceConfiguration _Configuration; + + public SetCountdownTimeHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + { + _packetDisapatcher = packetDisapatcher; + _Configuration = instanceConfiguration; + } + + public override void Handle(IPlayer player, SetCountdown command) + { + _Configuration.CountdownConfig.CountdownTimePlayersReady = command.Countdown; + _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket + { + Text = "Countdown time is now: " + command.Countdown + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetResultsTimeHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetResultsTimeHandler.cs new file mode 100644 index 00000000..4ca980cb --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetResultsTimeHandler.cs @@ -0,0 +1,28 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class SetResultsTimeHandler : BaseCommandHandler + { + private readonly IPacketDispatcher _packetDisapatcher; + private readonly InstanceConfiguration _Configuration; + + public SetResultsTimeHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + { + _packetDisapatcher = packetDisapatcher; + _Configuration = instanceConfiguration; + } + + public override void Handle(IPlayer player, SetResultsTime command) + { + _Configuration.CountdownConfig.ResultsScreenTime = command.Countdown; + _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket + { + Text = "Results screen time is now: " + command.Countdown + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetServerNameHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetServerNameHandler.cs new file mode 100644 index 00000000..3585aa7e --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetServerNameHandler.cs @@ -0,0 +1,31 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class SetServerNameHandler : BaseCommandHandler + { + private readonly IPacketDispatcher _packetDisapatcher; + private readonly InstanceConfiguration _Configuration; + private readonly IDedicatedInstance _instance; + + public SetServerNameHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration, IDedicatedInstance instance) + { + _packetDisapatcher = packetDisapatcher; + _Configuration = instanceConfiguration; + _instance = instance; + } + + public override void Handle(IPlayer player, SetServerName command) + { + _Configuration.ServerName = command.Name; + _instance.InstanceConfigUpdated(); + _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket + { + Text = "Server name is now: " + command.Name + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetWelcomeMessageHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetWelcomeMessageHandler.cs new file mode 100644 index 00000000..98a99edb --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetWelcomeMessageHandler.cs @@ -0,0 +1,30 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class SetWelcomeMessageHandler : BaseCommandHandler + { + private readonly IPacketDispatcher _packetDisapatcher; + private readonly InstanceConfiguration _Configuration; + private readonly IDedicatedInstance _instance; + + public SetWelcomeMessageHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration, IDedicatedInstance instance) + { + _packetDisapatcher = packetDisapatcher; + _Configuration = instanceConfiguration; + _instance = instance; + } + + public override void Handle(IPlayer player, SetWelcomeMessage command) + { + _Configuration.WelcomeMessage = command.Text; + _packetDisapatcher.SendToPlayer(player, new MpcTextChatPacket + { + Text = "Server name is now: " + command.Text + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/StartBeatmapTimeHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/StartBeatmapTimeHandler.cs new file mode 100644 index 00000000..856610b8 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/StartBeatmapTimeHandler.cs @@ -0,0 +1,28 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class StartBeatmapTimeHandler : BaseCommandHandler + { + private readonly IPacketDispatcher _packetDisapatcher; + private readonly InstanceConfiguration _Configuration; + + public StartBeatmapTimeHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + { + _packetDisapatcher = packetDisapatcher; + _Configuration = instanceConfiguration; + } + + public override void Handle(IPlayer player, SetBeatmapStartTime command) + { + _Configuration.CountdownConfig.BeatMapStartCountdownTime = command.Countdown; + _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket + { + Text = "Beatmap start time is now: " + command.Countdown + }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/AllowChroma.cs b/BeatTogether.DedicatedServer.Kernel/Commands/AllowChroma.cs new file mode 100644 index 00000000..2762b0a3 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/AllowChroma.cs @@ -0,0 +1,19 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class AllowChroma : ITextCommand + { + public string CommandName => "allowchroma"; + public string ShortHandName => "ch"; + public string Description => "if set to false, then chroma maps will be unplayable, default true"; + + public bool Enabled = true; + + public void ReadValues(string[] Values) + { + if (Values != null) + Enabled = Values[0] == "true"; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/AllowMappingExtensions.cs b/BeatTogether.DedicatedServer.Kernel/Commands/AllowMappingExtensions.cs new file mode 100644 index 00000000..739db5d5 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/AllowMappingExtensions.cs @@ -0,0 +1,19 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class AllowMappingExtensions : ITextCommand + { + public string CommandName => "allowme"; + public string ShortHandName => "me"; + public string Description => "if set to false, then mapping extensions maps will be unplayable, default true"; + + public bool Enabled = true; + + public void ReadValues(string[] Values) + { + if (Values != null) + Enabled = Values[0] == "true"; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/AllowNoodle.cs b/BeatTogether.DedicatedServer.Kernel/Commands/AllowNoodle.cs new file mode 100644 index 00000000..3ee599bf --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/AllowNoodle.cs @@ -0,0 +1,19 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class AllowNoodle : ITextCommand + { + public string CommandName => "allownoodle"; + public string ShortHandName => "ne"; + public string Description => "if set to false, then noodle maps will be unplayable, default true"; + + public bool Enabled = true; + + public void ReadValues(string[] Values) + { + if (Values != null) + Enabled = Values[0] == "true"; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerDifficulties.cs b/BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerDifficulties.cs new file mode 100644 index 00000000..8dfcf61b --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerDifficulties.cs @@ -0,0 +1,19 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class AllowPerPlayerDifficulties : ITextCommand + { + public string CommandName => "allowperplayerdifficulties"; + public string ShortHandName => "ppd"; + public string Description => "if set to true, then players will use what ever difficulty they have selected, default false"; + + public bool Enabled = false; + + public void ReadValues(string[] Values) + { + if (Values != null) + Enabled = Values[0] == "true"; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerModifiers.cs b/BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerModifiers.cs new file mode 100644 index 00000000..cac4c1d6 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerModifiers.cs @@ -0,0 +1,19 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class AllowPerPlayerModifiers : ITextCommand + { + public string CommandName => "allowperplayermodifiers"; + public string ShortHandName => "ppm"; + public string Description => "if set to true, then players will use what ever modifiers they have selected, default false"; + + public bool Enabled = false; + + public void ReadValues(string[] Values) + { + if (Values != null) + Enabled = Values[0] == "true"; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/DisableBeatmapNotes.cs b/BeatTogether.DedicatedServer.Kernel/Commands/DisableBeatmapNotes.cs new file mode 100644 index 00000000..6c3158ff --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/DisableBeatmapNotes.cs @@ -0,0 +1,19 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class DisableBeatmapNotes : ITextCommand + { + public string CommandName => "disablenotes"; + public string ShortHandName => "dn"; + public string Description => "disables beatmap notes if set to true. Notes will be disabled automaticly if there are over 14 players, default false"; + + public bool Disabled = false; + + public void ReadValues(string[] Values) + { + if (Values != null) + Disabled = Values[0] == "true"; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/HelpCommand.cs b/BeatTogether.DedicatedServer.Kernel/Commands/HelpCommand.cs new file mode 100644 index 00000000..4ea5afeb --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/HelpCommand.cs @@ -0,0 +1,19 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class HelpCommand : ITextCommand + { + public string CommandName => "help"; + public string ShortHandName => "h"; + public string Description => "Displays a list of useable commands, Type the name of the command after to get its description"; + + public string[]? SpecificCommandName = null; + + public void ReadValues(string[] Values) + { + if (Values != null) + SpecificCommandName = Values; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/SetBeatmapStartTime.cs b/BeatTogether.DedicatedServer.Kernel/Commands/SetBeatmapStartTime.cs new file mode 100644 index 00000000..e9d00e31 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/SetBeatmapStartTime.cs @@ -0,0 +1,19 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class SetBeatmapStartTime : ITextCommand + { + public string CommandName => "setbeatmapstart"; + public string ShortHandName => "sbs"; + public string Description => "this is the countdown that triggers once everyone is ready, and when the beatmap starts downloading, default is 5 seconds"; + + public int Countdown = 5; + + public void ReadValues(string[] Values) + { + if (Values != null) + Countdown = int.Parse(Values[0]); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/SetCountdown.cs b/BeatTogether.DedicatedServer.Kernel/Commands/SetCountdown.cs new file mode 100644 index 00000000..a27c29b1 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/SetCountdown.cs @@ -0,0 +1,19 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class SetCountdown : ITextCommand + { + public string CommandName => "setcountdown"; + public string ShortHandName => "sc"; + public string Description => "enter a number to set the countdown, default is 30 seconds"; + + public int Countdown = 30; + + public void ReadValues(string[] Values) + { + if (Values != null) + Countdown = int.Parse(Values[0]); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/SetResultsTime.cs b/BeatTogether.DedicatedServer.Kernel/Commands/SetResultsTime.cs new file mode 100644 index 00000000..a44b11e5 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/SetResultsTime.cs @@ -0,0 +1,19 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class SetResultsTime : ITextCommand + { + public string CommandName => "setresultstime"; + public string ShortHandName => "srt"; + public string Description => "the length of the results screen, default is 20 seconds"; + + public int Countdown = 20; + + public void ReadValues(string[] Values) + { + if (Values != null) + Countdown = int.Parse(Values[0]); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/SetServerName.cs b/BeatTogether.DedicatedServer.Kernel/Commands/SetServerName.cs new file mode 100644 index 00000000..42de9ac2 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/SetServerName.cs @@ -0,0 +1,19 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class SetServerName : ITextCommand + { + public string CommandName => "setservername"; + public string ShortHandName => "ssn"; + public string Description => "Enter some text to set the name of the server"; + + public string Name = string.Empty; + + public void ReadValues(string[] Values) + { + if (Values != null) + Name = Values[0]; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/SetWelcomeMessage.cs b/BeatTogether.DedicatedServer.Kernel/Commands/SetWelcomeMessage.cs new file mode 100644 index 00000000..c476b1aa --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/SetWelcomeMessage.cs @@ -0,0 +1,19 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class SetWelcomeMessage : ITextCommand + { + public string CommandName => "setwelcomemessage"; + public string ShortHandName => "swm"; + public string Description => "Enter some text to set the welcome message for this server"; + + public string Text = string.Empty; + + public void ReadValues(string[] Values) + { + if (Values != null) + Text = Values[0]; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs index 9cdd28b6..124ecb43 100644 --- a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs +++ b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs @@ -8,6 +8,7 @@ public sealed class InstanceConfiguration public string Secret { get; set; } = string.Empty; public string ServerOwnerId { get; set; } = string.Empty; public string ServerId { get; set; } = "ziuMSceapEuNN7wRGQXrZg"; + public string WelcomeMessage { get; set; } = string.Empty; public string ServerName { get; set; } = string.Empty; public float DestroyInstanceTimeout { get; set; } = 10f; //set to -1 for no timeout(must close using api), 0 would be for instant close, 10 seconds is default. Less than 6 seconds can cause cfr-3 issues public string SetConstantManagerFromUserId { get; set; } = string.Empty; //If a user creates a server using the api and enteres there userId (eg uses discord bot with linked account)) @@ -23,7 +24,10 @@ public sealed class InstanceConfiguration public bool AllowChroma { get; set; } public bool AllowMappingExtensions { get; set; } public bool AllowNoodleExtensions { get; set; } + public bool DisableNotes { get; set; } public float KickPlayersWithoutEntitlementTimeout { get; set; } = 30f; + public int MaxLengthCommand { get; set; } = 200; + public bool ApplyNoFailModifier { get; set; } = true; } public sealed class CountdownConfig diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 77a516e6..832f05e0 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -17,7 +17,6 @@ using BeatTogether.LiteNetLib.Configuration; using BeatTogether.LiteNetLib.Enums; using BeatTogether.LiteNetLib.Util; -using Krypton.Buffers; using Microsoft.Extensions.DependencyInjection; using Serilog; @@ -38,10 +37,11 @@ public sealed class DedicatedInstance : LiteNetServer, IDedicatedInstance public MultiplayerGameState State { get; private set; } = MultiplayerGameState.Lobby; public event Action StopEvent = null!; - public event Action PlayerConnectedEvent = null!; - public event Action PlayerDisconnectedEvent = null!; - public event Action PlayerDisconnectBeforeJoining = null!; + public event Action PlayerConnectedEvent = null!; + public event Action PlayerDisconnectedEvent = null!; + public event Action PlayerDisconnectBeforeJoining = null!; public event Action GameIsInLobby = null!; + public event Action UpdateInstanceEvent = null!; private readonly IHandshakeSessionRegistry _handshakeSessionRegistry; private readonly IPlayerRegistry _playerRegistry; @@ -133,7 +133,6 @@ public Task Start(CancellationToken cancellationToken = default) { if (!t.IsCanceled) { - _logger.Warning("Stopping instance: " + _configuration.ServerName); _ = Stop(CancellationToken.None); } else @@ -234,23 +233,24 @@ public void SetState(MultiplayerGameState state) object AcceptConnectionLock = new(); - public override bool ShouldAcceptConnection(EndPoint endPoint, ref MemoryBuffer additionalData) + public override bool ShouldAcceptConnection(EndPoint endPoint, ref SpanBuffer additionalData) { - + if (ShouldDenyConnection(endPoint, ref additionalData)) { - PlayerDisconnectBeforeJoining?.Invoke(_configuration.Secret, endPoint, _playerRegistry.GetPlayerCount()); + string[] Players = _playerRegistry.Players.Select(p => p.UserId).ToArray(); + PlayerDisconnectBeforeJoining?.Invoke(_configuration.Secret, endPoint, Players); return false; } + _logger.Information("connection accepted"); return true; } - public bool ShouldDenyConnection(EndPoint endPoint, ref MemoryBuffer additionalData) + public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBuffer additionalData) { - SpanBuffer spanBuffer = new(additionalData.RemainingData.Span); var connectionRequestData = new ConnectionRequestData(); try { - connectionRequestData.ReadFrom(ref spanBuffer); + connectionRequestData.ReadFrom(ref additionalData); } catch (Exception e) { @@ -289,6 +289,12 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref MemoryBuffer additionalD { if (_playerRegistry.GetPlayerCount() >= _configuration.MaxPlayerCount) { + _logger.Information("Max player count"); + return true; + } + if(connectionRequestData.UserName == "IGGAMES" || connectionRequestData.UserName == "IGGGAMES") + { + _logger.Information("an IGG player just tried joining after passing master auth"); return true; } int sortIndex = GetNextSortIndex(); @@ -306,7 +312,13 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref MemoryBuffer additionalD { SortIndex = sortIndex }; - + if (_configuration.ServerName == string.Empty) + { + _logger.Information("About to update servers name" + _configuration.ServerName); + _configuration.ServerName = player.UserName + "'s server"; + InstanceConfigUpdated(); + _logger.Information("Updated servers name to: " + _configuration.ServerName); + } if (!_playerRegistry.AddPlayer(player)) { ReleaseSortIndex(player.SortIndex); @@ -444,7 +456,7 @@ public override void OnConnect(EndPoint endPoint) } // Update permissions - constant manager possibly does not work - if ((_configuration.SetConstantManagerFromUserId == player.UserId || _playerRegistry.GetPlayerCount() == 1) && _configuration.GameplayServerMode == Enums.GameplayServerMode.Managed) + if ((_configuration.SetConstantManagerFromUserId == player.UserId || _playerRegistry.GetPlayerCount() == 1) && _configuration.GameplayServerMode == GameplayServerMode.Managed) { _configuration.ServerOwnerId = player.UserId; } @@ -464,7 +476,7 @@ public override void OnConnect(EndPoint endPoint) }).ToArray() } }, DeliveryMethod.ReliableOrdered); - PlayerConnectedEvent?.Invoke(player, _playerRegistry.GetPlayerCount()); + PlayerConnectedEvent?.Invoke(player); } } @@ -515,7 +527,7 @@ public override void OnDisconnect(EndPoint endPoint, DisconnectReason reason) ReleaseSortIndex(player.SortIndex); ReleaseConnectionId(player.ConnectionId); - PlayerDisconnectedEvent?.Invoke(player, _playerRegistry.GetPlayerCount()); + PlayerDisconnectedEvent?.Invoke(player); } @@ -598,6 +610,11 @@ private async void SendSyncTime(CancellationToken cancellationToken) SendSyncTime(cancellationToken); } + public void InstanceConfigUpdated() + { + UpdateInstanceEvent?.Invoke(this); + } + #endregion } } diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs index 701ffcec..cdee445a 100644 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs @@ -125,7 +125,6 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Span data) // TODO Reject unencrypted inbound packets for regular clients past the negotiation stage? return; } - byte[]? decryptedData; if (_encryptionParameters.TryGetValue(endPoint, out var encryptionParameters)) @@ -134,6 +133,7 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Span data) data = decryptedData; else data = Array.Empty(); + return; } @@ -159,9 +159,8 @@ public void ProcessInboundPacket(EndPoint endPoint, ref Span data) data = Array.Empty(); } - public void ProcessOutBoundPacket(EndPoint endPoint, ref Span data) + public void ProcessOutBoundPacket(EndPoint endPoint, ref Span data) //Not used { - if (!_encryptionParameters.TryGetValue(endPoint, out var encryptionParameters)) { if (_potentialEncryptionParameters.TryGetValue(((IPEndPoint) endPoint).Address, @@ -196,9 +195,10 @@ public void ProcessOutBoundPacket(EndPoint endPoint, ref Span data) bufferWriter.WriteBytes(data); } data = bufferWriter.Data.ToArray(); + } - public void ProcessInboundPacket(EndPoint endPoint, ref Memory data) + public void ProcessInboundPacket(EndPoint endPoint, ref Memory data) // Not used { var address = ((IPEndPoint)endPoint).Address; @@ -262,7 +262,7 @@ public void ProcessOutBoundPacket(EndPoint endPoint, ref Memory data) } } - var bufferWriter = new SpanBufferWriter(stackalloc byte[412]); + var bufferWriter = new SpanBufferWriter(stackalloc byte[(int)((data.Length + 1)* 1.8)]); //Kinda just estimating the size the packet will be after encryption, to avoid having the span buffer get resized if (encryptionParameters != null) { @@ -284,10 +284,8 @@ public void ProcessOutBoundPacket(EndPoint endPoint, ref Memory data) bufferWriter.WriteBool(false); // NotEncrypted bufferWriter.WriteBytes(data.Span); } - data = new Memory(bufferWriter.Data.ToArray()); + data = bufferWriter.Data.ToArray(); } - - #endregion #region Private Methods diff --git a/BeatTogether.DedicatedServer.Kernel/Enums/AccessLevel.cs b/BeatTogether.DedicatedServer.Kernel/Enums/AccessLevel.cs new file mode 100644 index 00000000..36ae1b5f --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Enums/AccessLevel.cs @@ -0,0 +1,13 @@ +namespace BeatTogether.DedicatedServer.Kernel.Enums +{ + public enum AccessLevel + { + Player = 0, + PatreonPlayer = 1, + SubManager = 2, + PatreonSubManager = 3, + Manager = 4, + PatreonManager = 5, + Dev = 6 + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Extensions/HostBuilderExtensions.cs b/BeatTogether.DedicatedServer.Kernel/Extensions/HostBuilderExtensions.cs index e37e01b2..b5c5680d 100644 --- a/BeatTogether.DedicatedServer.Kernel/Extensions/HostBuilderExtensions.cs +++ b/BeatTogether.DedicatedServer.Kernel/Extensions/HostBuilderExtensions.cs @@ -1,12 +1,16 @@ using BeatTogether.Core.Messaging.Abstractions; using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Kernel.Handshake; using BeatTogether.DedicatedServer.Kernel.Managers; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; +using BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MPChat; +using BeatTogether.DedicatedServer.Messaging.Registries; using BeatTogether.DedicatedServer.Messaging.Registries.Unconnected; using BeatTogether.Extensions; using BeatTogether.LiteNetLib; +using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Configuration; using BeatTogether.LiteNetLib.Dispatchers; using BeatTogether.LiteNetLib.Extensions; @@ -45,10 +49,12 @@ public static IHostBuilder UseDedicatedInstances(this IHostBuilder hostBuilder) .AddScoped() .AddScoped() .AddCoreMessaging() + .AddSingleton() .AddSingleton() .AddSingleton() .AddAllHandshakeMessageHandlersFromAssembly(typeof(UnconnectedSource).Assembly) .AddAllPacketHandlersFromAssembly(typeof(PacketSource).Assembly) + .AddAllCommandHandlersFromAssembly(typeof(MpcTextChatPacketHandler).Assembly) ); } } diff --git a/BeatTogether.DedicatedServer.Kernel/Extensions/ServiceCollectionExtensions.cs b/BeatTogether.DedicatedServer.Kernel/Extensions/ServiceCollectionExtensions.cs index 4acf68de..20ab0b9f 100644 --- a/BeatTogether.DedicatedServer.Kernel/Extensions/ServiceCollectionExtensions.cs +++ b/BeatTogether.DedicatedServer.Kernel/Extensions/ServiceCollectionExtensions.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Reflection; using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using Microsoft.Extensions.DependencyInjection; namespace BeatTogether.Extensions @@ -25,7 +26,21 @@ public static IServiceCollection AddAllPacketHandlersFromAssembly(this IServiceC eventHandlerType); return services; } - + + public static IServiceCollection AddAllCommandHandlersFromAssembly(this IServiceCollection services, Assembly assembly) + { + var genericInterface = typeof(ICommandHandler<>); + var eventHandlerTypes = assembly + .GetTypes() + .Where(type => type.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == genericInterface)); + foreach (var eventHandlerType in eventHandlerTypes) + if (!eventHandlerType.IsAbstract) + services.AddTransient( + genericInterface.MakeGenericType(eventHandlerType.BaseType!.GetGenericArguments()), + eventHandlerType); + return services; + } + public static IServiceCollection AddAllHandshakeMessageHandlersFromAssembly(this IServiceCollection services, Assembly assembly) { var genericInterface = typeof(IHandshakeMessageHandler<>); diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs index f81d2c27..c8de1b98 100644 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs @@ -51,7 +51,7 @@ public void Dispose() public void Send(HandshakeSession session, IMessage message, bool retry = false) { - _logger.Verbose("Sending handshake message of type {MessageType} (EndPoint={EndPoint})", + _logger.Debug("Sending handshake message of type {MessageType} (EndPoint={EndPoint})", message.GetType().Name, session.EndPoint.ToString()); // Assign request ID to outgoing requests diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedSource.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedSource.cs index 5918dcf2..6279821e 100644 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedSource.cs @@ -63,11 +63,11 @@ public void Dispose() #region Receive - public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, + public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, UnconnectedMessageType type) { - SpanBufferReader spanBufferReader = new(reader.RemainingData.Span.ToArray()); + SpanBufferReader spanBufferReader = new(reader.RemainingData); var session = _handshakeSessionRegistry.GetOrAdd(remoteEndPoint); var message = _messageReader.ReadFrom(ref spanBufferReader); @@ -78,7 +78,6 @@ public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, public async Task HandleMessage(HandshakeSession session, IMessage message) { var messageType = message.GetType(); - if (message is ClientHelloRequest) { // Received client hello, first handshake message - ensure encryption is OFF for this endpoint @@ -110,7 +109,7 @@ public async Task HandleMessage(HandshakeSession session, IMessage message) } // Dispatch to handler - _logger.Verbose("Handling handshake message of type {MessageType} (EndPoint={EndPoint})", + _logger.Debug("Handling handshake message of type {MessageType} (EndPoint={EndPoint})", messageType.Name, session.EndPoint.ToString()); if (message is MultipartMessage multipartMessage) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/IGameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/IGameplayManager.cs index e3d7828a..3c2893ff 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/IGameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/IGameplayManager.cs @@ -14,7 +14,7 @@ public interface IGameplayManager GameplayModifiers CurrentModifiers { get; } public float _songStartTime { get; } - void HandlePlayerLeaveGameplay(IPlayer player, int Unused = 0); + void HandlePlayerLeaveGameplay(IPlayer player); void HandleGameSceneLoaded(IPlayer player, SetGameplaySceneReadyPacket packet); void HandleGameSongLoaded(IPlayer player); void HandleLevelFinished(IPlayer player, LevelFinishedPacket packet); diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs index 408f4ec3..1e5dd837 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs @@ -270,7 +270,7 @@ public void SignalRequestReturnToMenu() } //will set players tasks as done if they leave gameplay due to disconnect or returning to the menu - public void HandlePlayerLeaveGameplay(IPlayer player, int Unused = 0) + public void HandlePlayerLeaveGameplay(IPlayer player) { LeaveGameplay(player.UserId); } diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 074d6cca..d2bbf2ad 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -11,7 +11,6 @@ using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Enums; using Serilog; @@ -391,26 +390,41 @@ private void CancelCountdown() { return null; } - return voteDictionary.OrderByDescending(n => n.Value).First().Key; - case SongSelectionMode.RandomPlayerPicks: //TODO, Make this pick a random beatsaver map or something like that - return new BeatmapIdentifier() + BeatmapIdentifier? Selected = null; + int Votes = 0; + foreach (var item in voteDictionary) { - Characteristic = "Standard", - Difficulty = BeatmapDifficulty.ExpertPlus, - LevelId = "custom_level_103d39b43966277c5e4167ab086f404e0943891f" - }; - case SongSelectionMode.ServerPicks: + if (item.Value > Votes) + { + Selected = item.Key; + Votes = item.Value; + } + } + return Selected; + case SongSelectionMode.RandomPlayerPicks: + if (CountDownState == CountdownState.CountingDown || CountDownState == CountdownState.NotCountingDown) + { + Random rand = new(); + int selectedPlayer = rand.Next(_playerRegistry.GetPlayerCount() - 1); + RandomlyPickedPlayer = _playerRegistry.Players[selectedPlayer].UserId; + return _playerRegistry.Players[selectedPlayer].BeatmapIdentifier; + } + return SelectedBeatmap; + + case SongSelectionMode.ServerPicks: //TODO, Make this pick a random beatsaver map or something like that return SelectedBeatmap!; }; return null; } + string RandomlyPickedPlayer = string.Empty; + private GameplayModifiers GetSelectedModifiers() { switch(_configuration.SongSelectionMode) { case SongSelectionMode.ServerOwnerPicks: return _playerRegistry.GetPlayer(_configuration.ServerOwnerId).Modifiers; - case SongSelectionMode.Vote or SongSelectionMode.RandomPlayerPicks: + case SongSelectionMode.Vote: GameplayModifiers gameplayModifiers = new(); Dictionary voteDictionary = new(); foreach (IPlayer player in _playerRegistry.Players.Where(p => p.Modifiers != null)) @@ -420,9 +434,33 @@ private GameplayModifiers GetSelectedModifiers() else voteDictionary.Add(player.Modifiers!, 1); } - if (voteDictionary.Any()) - gameplayModifiers = voteDictionary.OrderByDescending(n => n.Value).First().Key; - gameplayModifiers.NoFailOn0Energy = true; + if (!voteDictionary.Any()) + { + int Votes = 0; + foreach (var item in voteDictionary) + { + if (item.Value > Votes) + { + gameplayModifiers = item.Key; + Votes = item.Value; + } + } + } + if(_configuration.ApplyNoFailModifier) + gameplayModifiers.NoFailOn0Energy = true; + return gameplayModifiers; + case SongSelectionMode.RandomPlayerPicks: + if (RandomlyPickedPlayer == string.Empty) + { + GameplayModifiers Modifiers = new() + { + NoFailOn0Energy = _configuration.ApplyNoFailModifier + }; + return Modifiers; + } + gameplayModifiers = _playerRegistry.GetPlayer(RandomlyPickedPlayer).Modifiers; + if (_configuration.ApplyNoFailModifier) + gameplayModifiers.NoFailOn0Energy = true; return gameplayModifiers; case SongSelectionMode.ServerPicks: return SelectedModifiers; diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index ecba569e..f4969458 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -1,4 +1,6 @@ using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Enums; +using BeatTogether.DedicatedServer.Messaging.Registries; using BeatTogether.Extensions; using BeatTogether.LiteNetLib; using BeatTogether.LiteNetLib.Abstractions; @@ -56,7 +58,7 @@ public void SendToNearbyPlayers(INetSerializable[] packets, DeliveryMethod deliv $"(SenderId={ServerId})" ); - var writer = new SpanBuffer(stackalloc byte[412]); + var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); _logger.Verbose("Packets were entered into the spanbuffer correctly, now sending once to each player"); @@ -86,7 +88,7 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packe $"(ExcludedId={excludedPlayer.ConnectionId})" ); - var writer = new SpanBuffer(stackalloc byte[412]); + var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); @@ -115,7 +117,7 @@ public void SendToEndpoint(EndPoint endpoint, INetSerializable[] packets, Delive $"(To endpoint ={endpoint})" ); - var writer = new SpanBuffer(stackalloc byte[412]); + var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); @@ -143,7 +145,7 @@ public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, Deliv $"(SenderId={fromPlayer.ConnectionId})" ); - var writer = new SpanBuffer(stackalloc byte[412]); + var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteMany(ref writer, packets); @@ -171,7 +173,7 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer $"(SenderId={fromPlayer.ConnectionId}, ReceiverId={LocalConnectionId})." ); - var writer = new SpanBuffer(stackalloc byte[412]); + var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteMany(ref writer, packets); Send(toPlayer.Endpoint, writer.Data, deliveryMethod); @@ -197,7 +199,7 @@ public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMet $"(SenderId={ServerId}, ReceiverId={LocalConnectionId})." ); - var writer = new SpanBuffer(stackalloc byte[412]); + var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); Send(player.Endpoint, writer.Data, deliveryMethod); @@ -206,11 +208,22 @@ public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMet public void WriteOne(ref SpanBuffer writer, INetSerializable packet) { var type = packet.GetType(); - if (!_packetRegistry.TryGetPacketIds(type, out var packetIds)) - throw new Exception($"Failed to retrieve identifier for packet of type '{type.Name}'"); var packetWriter = new SpanBuffer(stackalloc byte[412]); - foreach (byte packetId in packetIds) - packetWriter.WriteUInt8(packetId); + + if (_packetRegistry.TryGetPacketIds(type, out var packetIds)) + { + foreach (byte packetId in packetIds) + packetWriter.WriteUInt8(packetId); + } + else + { + + packetWriter.WriteUInt8(7); + packetWriter.WriteUInt8(100); + packetWriter.WriteString(type.Name); + //Presume it is a mpcore packet and use the mpcore packet ID, would thow an exeption here if not + //throw new Exception($"Failed to retrieve identifier for packet of type '{type.Name}'"); + } packet.WriteTo(ref packetWriter); writer.WriteVarUInt((uint)packetWriter.Size); writer.WriteBytes(packetWriter.Data.ToArray()); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs new file mode 100644 index 00000000..0e95089d --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs @@ -0,0 +1,48 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; +using BeatTogether.LiteNetLib.Enums; +using Serilog; +using System; +using System.Threading.Tasks; + +namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MPChat +{ + public class MpcCapabilitiesPacketHandler : BasePacketHandler + { + private readonly IPacketDispatcher _packetDispatcher; + private readonly InstanceConfiguration _instanceConfiguration; + private readonly ILogger _logger = Log.ForContext(); + public MpcCapabilitiesPacketHandler(IPacketDispatcher packetDispatcher, + InstanceConfiguration instanceConfiguration) + { + _packetDispatcher = packetDispatcher; + _instanceConfiguration = instanceConfiguration; + } + + public override Task Handle(IPlayer sender, MpcCapabilitiesPacket packet) + { + bool FirstJoin = !sender.CanTextChat && packet.CanTextChat; + lock (sender.MPChatLock) + { + sender.CanReceiveVoiceChat = packet.CanReceiveVoiceChat; + sender.CanTransmitVoiceChat = packet.CanTransmitVoiceChat; + sender.CanTextChat = packet.CanTextChat; + } + if (FirstJoin) + { + _packetDispatcher.SendToPlayer(sender, new MpcTextChatPacket + { + Text = "Welcome to " + _instanceConfiguration.ServerName + " Type /help to get a list of commands!" + }, DeliveryMethod.ReliableOrdered); + if (_instanceConfiguration.WelcomeMessage != string.Empty) + _packetDispatcher.SendToPlayer(sender, new MpcTextChatPacket + { + Text = _instanceConfiguration.WelcomeMessage + }, DeliveryMethod.ReliableOrdered); + + } + return Task.CompletedTask; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs new file mode 100644 index 00000000..12534ac0 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs @@ -0,0 +1,54 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; +using BeatTogether.LiteNetLib.Enums; +using Serilog; +using System; +using System.Threading.Tasks; + +namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MPChat +{ + public class MpcTextChatPacketHandler : BasePacketHandler + { + private readonly IPacketDispatcher _packetDispatcher; + private readonly InstanceConfiguration _instanceConfiguration; + private readonly ITextCommandRepository _CommandRepository; + private readonly IServiceProvider _serviceProvider; + private readonly ILogger _logger = Log.ForContext(); + + + public MpcTextChatPacketHandler(IPacketDispatcher packetDispatcher, + ITextCommandRepository textCommandRepository, + InstanceConfiguration instanceConfiguration, + IServiceProvider serviceProvider) + { + _packetDispatcher = packetDispatcher; + _instanceConfiguration = instanceConfiguration; + _CommandRepository = textCommandRepository; + _serviceProvider = serviceProvider; + } + + public override Task Handle(IPlayer sender, MpcTextChatPacket packet) + { + if (packet.Text.Length < _instanceConfiguration.MaxLengthCommand && packet.Text.StartsWith("/")){ + string[] CommandValues = packet.Text[1..].Split(' '); + if (_CommandRepository.GetCommand(CommandValues, sender.GetAccessLevel(), out var TextCommand)) + { + var commandType = TextCommand.GetType(); + var packetHandlerType = typeof(ICommandHandler<>) + .MakeGenericType(commandType); + var Command = _serviceProvider.GetService(packetHandlerType); + if (Command != null) + ((ICommandHandler)Command).Handle(sender, TextCommand); + return Task.CompletedTask; + } + _packetDispatcher.SendToPlayer(sender, new MpcTextChatPacket + { + Text = "Command not found or too long" + }, DeliveryMethod.ReliableOrdered); + } + return Task.CompletedTask; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index fcc9c68f..60e51a10 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -2,6 +2,7 @@ using System.Net; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; using BeatTogether.DedicatedServer.Messaging.Registries; using BeatTogether.Extensions; using BeatTogether.LiteNetLib; @@ -46,7 +47,7 @@ public PacketSource( _configuration = instconfiguration; } - public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, DeliveryMethod method) + public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, DeliveryMethod method) { if (!reader.TryReadRoutingHeader(out var routingHeader)) { @@ -67,9 +68,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, } SpanBuffer HandleRead = new(reader.RemainingData.ToArray()); - //Is this packet meant to be routed? - if (routingHeader.ReceiverId != 0) - RoutePacket(sender, routingHeader, ref reader, method); + while (HandleRead.RemainingSize > 0) { @@ -121,7 +120,13 @@ public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); return; } continue; } - + if(packet is NoteSpawnPacket || packet is ObstacleSpawnPacket || packet is SliderSpawnPacket) //Note packet logic + { + if (_configuration.DisableNotes || _playerRegistry.GetPlayerCount() > 14) + return; + method = DeliveryMethod.Unreliable; + break; + } var packetType = packet.GetType(); var packetHandlerType = typeof(Abstractions.IPacketHandler<>) .MakeGenericType(packetType); @@ -151,20 +156,24 @@ public override void OnReceive(EndPoint remoteEndPoint, ref MemoryBuffer reader, ((Abstractions.IPacketHandler)packetHandler).Handle(sender, packet); } + + //Is this packet meant to be routed? + if (routingHeader.ReceiverId != 0) + RoutePacket(sender, routingHeader, ref reader, method); } #region Private Methods private void RoutePacket(IPlayer sender, (byte SenderId, byte ReceiverId) routingHeader, - ref MemoryBuffer reader, DeliveryMethod deliveryMethod) + ref SpanBuffer reader, DeliveryMethod deliveryMethod) { routingHeader.SenderId = sender.ConnectionId; - var writer = new MemoryBuffer(GC.AllocateArray(2048)); + var writer = new SpanBuffer(stackalloc byte[412]); if (routingHeader.ReceiverId == AllConnectionIds) { writer.WriteRoutingHeader(routingHeader.SenderId, routingHeader.ReceiverId); - writer.WriteBytes(reader.RemainingData.Span); + writer.WriteBytes(reader.RemainingData); _logger.Verbose( $"Routing packet from {routingHeader.SenderId} -> all players " + @@ -177,7 +186,7 @@ private void RoutePacket(IPlayer sender, else { writer.WriteRoutingHeader(routingHeader.SenderId, LocalConnectionId); - writer.WriteBytes(reader.RemainingData.Span); + writer.WriteBytes(reader.RemainingData); if (!_playerRegistry.TryGetPlayer(routingHeader.ReceiverId, out var receiver)) { diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index edc3f743..106612f3 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Net; using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Types; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; @@ -63,7 +64,7 @@ public sealed class Player : IPlayer private ConcurrentDictionary _entitlements = new(); public Player(EndPoint endPoint, IDedicatedInstance instance, - byte connectionId, string secret, string userId, string userName, string? playerSessionId) + byte connectionId, string secret, string userId, string userName, string? playerSessionId, AccessLevel accessLevel = AccessLevel.Player) { Endpoint = endPoint; Instance = instance; @@ -72,6 +73,28 @@ public Player(EndPoint endPoint, IDedicatedInstance instance, UserId = userId; UserName = userName; PlayerSessionId = playerSessionId; + _AccessLevel = accessLevel; + } + public bool IsPatreon { get; set; } = false; + public object MPChatLock { get; set; } = new(); + public bool CanTextChat { get; set; } = false; + public bool CanReceiveVoiceChat { get; set; } = false; + public bool CanTransmitVoiceChat { get; set; } = false; + + private AccessLevel _AccessLevel; + public AccessLevel GetAccessLevel() + { + AccessLevel accessLevel = _AccessLevel; + if (IsServerOwner) + accessLevel = AccessLevel.Manager; + if (IsPatreon) + accessLevel++; + return accessLevel; + } + + public void SetAccessLevel(AccessLevel newLevel) + { + _AccessLevel = newLevel; } public object EntitlementLock { get; set; } = new(); diff --git a/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs b/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs new file mode 100644 index 00000000..8f2b2115 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs @@ -0,0 +1,111 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.Commands; +using BeatTogether.DedicatedServer.Kernel.Enums; +using BeatTogether.DedicatedServer.Kernel.Managers; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; +using Serilog; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; + +namespace BeatTogether.DedicatedServer.Kernel +{ + public class TextCommandRepository : ITextCommandRepository + { + public delegate ITextCommand CommandFactory(); + + private readonly ConcurrentDictionary> _Commands = new(); + private readonly ConcurrentDictionary> _SHCommands = new(); + private readonly ILogger _logger = Log.ForContext(); + public TextCommandRepository() + { + RegisterCommands(); + } + + public bool GetCommand(string[] CommandValues, AccessLevel accessLevel, out ITextCommand Command) + { + bool IsPatreon = (int)accessLevel % 2 == 1; + if ((int)accessLevel == 6) + IsPatreon = true; + CommandFactory CommandDelegate; + while(accessLevel >= 0) + { + if(_Commands.TryGetValue(accessLevel, out var commands)) + { + if(commands.TryGetValue(CommandValues[0], out CommandDelegate!)) + { + Command = CommandDelegate(); + if(CommandValues.Length > 1) + Command.ReadValues(CommandValues[1..]); + return true; + } + } + if (_SHCommands.TryGetValue(accessLevel, out commands)) + { + if (commands.TryGetValue(CommandValues[0], out CommandDelegate!)) + { + Command = CommandDelegate(); + if (CommandValues.Length > 1) + Command.ReadValues(CommandValues[1..]); + return true; + } + } + accessLevel -= IsPatreon ? 2 : 1; + } + Command = null!; + return false; + } + + public string[] GetTextCommandNames(AccessLevel accessLevel) + { + bool IsPatreon = (int)accessLevel % 2 == 1; + if ((int)accessLevel == 6) + IsPatreon = true; + List Commands = new(); + while (accessLevel >= 0) + { + if (_Commands.TryGetValue(accessLevel, out var commands)) + { + Commands.AddRange(commands.Keys); + } + accessLevel -= IsPatreon ? 2 : 1; + } + return Commands.ToArray(); + } + + public void RegisterCommand(AccessLevel accessLevel) where T : class, ITextCommand, new() + { + Type typeFromHandle = typeof(T); + ITextCommand command = new T(); + ConcurrentDictionary Commands; + ConcurrentDictionary SHCommands; + if (!_Commands.TryGetValue(accessLevel, out Commands!)) + { + _Commands.TryAdd(accessLevel, new ConcurrentDictionary()); + _Commands.TryGetValue(accessLevel, out Commands!); + _SHCommands.TryAdd(accessLevel, new ConcurrentDictionary()); + } + _SHCommands.TryGetValue(accessLevel, out SHCommands!); + Commands.TryAdd(command.CommandName, () => new T()); + SHCommands.TryAdd(command.ShortHandName, () => new T()); + } + + + private void RegisterCommands() + { + RegisterCommand(AccessLevel.Player); + + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj index 1c9a0ce3..6500adec 100644 --- a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj +++ b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj @@ -9,7 +9,7 @@ - + diff --git a/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserRequest.cs b/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserRequest.cs index 3bc09ba5..a6b4adb3 100644 --- a/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserRequest.cs +++ b/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserRequest.cs @@ -1,6 +1,5 @@ using BeatTogether.Core.Messaging.Abstractions; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Extensions; using Krypton.Buffers; namespace BeatTogether.DedicatedServer.Messaging.Messages.GameLift diff --git a/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs b/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs index c8d7bc1f..51afb59e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs @@ -66,46 +66,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteString(FacialHairId); writer.WriteString(HandsId); } - public void ReadFrom(ref MemoryBuffer reader) - { - HeadTopId = reader.ReadString(); - HeadTopPrimaryColor = reader.ReadColor(); - HandsColor = reader.ReadColor(); - ClothesId = reader.ReadString(); - ClothesPrimaryColor = reader.ReadColor(); - ClothesSecondaryColor = reader.ReadColor(); - ClothesDetailColor = reader.ReadColor(); - reader.SkipBytes(8); - EyesId = reader.ReadString(); - MouthId = reader.ReadString(); - GlassesColor = reader.ReadColor(); - FacialHairColor = reader.ReadColor(); - HeadTopSecondaryColor = reader.ReadColor(); - GlassesId = reader.ReadString(); - FacialHairId = reader.ReadString(); - HandsId = reader.ReadString(); - SkinColorId = GlassesId; // Don't ask - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteString(HeadTopId); - writer.WriteColor(HeadTopPrimaryColor); - writer.WriteColor(HandsColor); - writer.WriteString(ClothesId); - writer.WriteColor(ClothesPrimaryColor); - writer.WriteColor(ClothesSecondaryColor); - writer.WriteColor(ClothesDetailColor); - writer.WriteColor(new Color()); - writer.WriteColor(new Color()); - writer.WriteString(EyesId); - writer.WriteString(MouthId); - writer.WriteColor(GlassesColor); - writer.WriteColor(FacialHairColor); - writer.WriteColor(HeadTopSecondaryColor); - writer.WriteString(GlassesId); - writer.WriteString(FacialHairId); - writer.WriteString(HandsId); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/BeatmapIdentifier.cs b/BeatTogether.DedicatedServer.Messaging/Models/BeatmapIdentifier.cs index 6613eaae..dbd1868e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/BeatmapIdentifier.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/BeatmapIdentifier.cs @@ -24,18 +24,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteString(Characteristic); writer.WriteVarUInt((uint)Difficulty); } - public void ReadFrom(ref MemoryBuffer reader) - { - LevelId = reader.ReadString(); - Characteristic = reader.ReadString(); - Difficulty = (BeatmapDifficulty)reader.ReadVarUInt(); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteString(LevelId); - writer.WriteString(Characteristic); - writer.WriteVarUInt((uint)Difficulty); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs index 46b6b8db..9cf6483f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs @@ -39,17 +39,6 @@ public void ReadFrom(ref SpanBuffer reader) } public void WriteTo(ref SpanBuffer writer) - { - writer.WriteUInt64(Top); - writer.WriteUInt64(Bottom); - } - public void ReadFrom(ref MemoryBuffer reader) - { - Top = reader.ReadUInt64(); - Bottom = reader.ReadUInt64(); - } - - public void WriteTo(ref MemoryBuffer writer) { writer.WriteUInt64(Top); writer.WriteUInt64(Bottom); diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ByteArray.cs b/BeatTogether.DedicatedServer.Messaging/Models/ByteArray.cs index 0aa53e26..bd4b4ff9 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ByteArray.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ByteArray.cs @@ -21,16 +21,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteVarUInt((Data != null) ? (uint)Data.Length : 0); writer.WriteBytes(Data); } - public void ReadFrom(ref MemoryBuffer reader) - { - int length = (int)reader.ReadVarUInt(); - Data = reader.ReadBytes(length).ToArray(); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteVarUInt((Data != null) ? (uint)Data.Length : 0); - writer.WriteBytes(Data); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ColorNoAlpha.cs b/BeatTogether.DedicatedServer.Messaging/Models/ColorNoAlpha.cs index 2086c677..8642c282 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ColorNoAlpha.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ColorNoAlpha.cs @@ -23,18 +23,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteFloat32(g); writer.WriteFloat32(b); } - public void ReadFrom(ref MemoryBuffer reader) - { - r = reader.ReadFloat32(); - g = reader.ReadFloat32(); - b = reader.ReadFloat32(); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteFloat32(r); - writer.WriteFloat32(g); - writer.WriteFloat32(b); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ColorScheme.cs b/BeatTogether.DedicatedServer.Messaging/Models/ColorScheme.cs index 962c040e..b94b2a9b 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ColorScheme.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ColorScheme.cs @@ -35,26 +35,5 @@ public void WriteTo(ref SpanBuffer writer) EnvironmentColor0Boost.WriteTo(ref writer); EnvironmentColor1Boost.WriteTo(ref writer); } - public void ReadFrom(ref MemoryBuffer reader) - { - SaberAColor.ReadFrom(ref reader); - SaberBColor.ReadFrom(ref reader); - ObstaclesColor.ReadFrom(ref reader); - EnvironmentColor0.ReadFrom(ref reader); - EnvironmentColor1.ReadFrom(ref reader); - EnvironmentColor0Boost.ReadFrom(ref reader); - EnvironmentColor1Boost.ReadFrom(ref reader); - } - - public void WriteTo(ref MemoryBuffer writer) - { - SaberAColor.WriteTo(ref writer); - SaberBColor.WriteTo(ref writer); - ObstaclesColor.WriteTo(ref writer); - EnvironmentColor0.WriteTo(ref writer); - EnvironmentColor1.WriteTo(ref writer); - EnvironmentColor0Boost.WriteTo(ref writer); - EnvironmentColor1Boost.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs index 832880ab..3759fe83 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs @@ -70,56 +70,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteBool(IsConnectionOwner); } } - - public void ReadFrom(ref MemoryBuffer reader) - { - Secret = null; - PlayerSessionId = null; - - var initialOffset = reader.Offset; - - // Try to read as a GameLift connection request - try - { - UserId = reader.ReadString(); - UserName = reader.ReadString(); - IsConnectionOwner = reader.ReadBool(); - PlayerSessionId = reader.ReadString(); - } - catch (Exception ex) { } - - if (PlayerSessionId != null && PlayerSessionId.StartsWith(SessionIdPrefix)) - // Read OK, valid session identifier - return; - - // Rewind, try to read as basic request - reader.SkipBytes(initialOffset - reader.Offset); - - Secret = reader.ReadString(); - UserId = reader.ReadString(); - UserName = reader.ReadString(); - IsConnectionOwner = reader.ReadBool(); - PlayerSessionId = null; - } - - public void WriteTo(ref MemoryBuffer writer) - { - if (!string.IsNullOrEmpty(PlayerSessionId)) - { - // GameLift - writer.WriteString(UserId); - writer.WriteString(UserName); - writer.WriteBool(IsConnectionOwner); - writer.WriteString(PlayerSessionId); - } - else - { - // Basic - writer.WriteString(Secret ?? ""); - writer.WriteString(UserId); - writer.WriteString(UserName); - writer.WriteBool(IsConnectionOwner); - } - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/GameplayModifiers.cs b/BeatTogether.DedicatedServer.Messaging/Models/GameplayModifiers.cs index d8842132..7ee4dc61 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/GameplayModifiers.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/GameplayModifiers.cs @@ -67,50 +67,6 @@ public void WriteTo(ref SpanBuffer writer) num |= (SmallCubes ? 67108864 : 0); writer.WriteInt32(num); } - public void ReadFrom(ref MemoryBuffer reader) - { - int @int = reader.ReadInt32(); - Energy = (EnergyType)(@int & 15); - DemoNoFail = (@int & 32) != 0; - InstaFail = (@int & 64) != 0; - FailOnSaberClash = (@int & 128) != 0; - EnabledObstacle = (EnabledObstacleType)(@int >> 8 & 15); - DemoNoObstacles = (@int & 4096) != 0; - NoBombs = (@int & 8192) != 0; - FastNotes = (@int & 16384) != 0; - StrictAngles = (@int & 32768) != 0; - DisappearingArrows = (@int & 65536) != 0; - GhostNotes = (@int & 131072) != 0; - Speed = (GameplayModifiers.SongSpeed)(@int >> 18 & 15); - NoArrows = (@int & 4194304) != 0; - NoFailOn0Energy = (@int & 8388608) != 0; - ProMode = (@int & 16777216) != 0; - ZenMode = (@int & 33554432) != 0; - SmallCubes = (@int & 67108864) != 0; - } - - public void WriteTo(ref MemoryBuffer writer) - { - int num = 0; - num |= (int)(Energy & (EnergyType)15); - num |= (DemoNoFail ? 32 : 0); - num |= (InstaFail ? 64 : 0); - num |= (FailOnSaberClash ? 128 : 0); - num |= (int)((int)(EnabledObstacle & (EnabledObstacleType)15) << 8); - num |= (DemoNoObstacles ? 4096 : 0); - num |= (NoBombs ? 8192 : 0); - num |= (FastNotes ? 16384 : 0); - num |= (StrictAngles ? 32768 : 0); - num |= (DisappearingArrows ? 65536 : 0); - num |= (GhostNotes ? 131072 : 0); - num |= (int)((int)(Speed & (SongSpeed)15) << 18); - num |= (NoArrows ? 4194304 : 0); - num |= (NoFailOn0Energy ? 8388608 : 0); - num |= (ProMode ? 16777216 : 0); - num |= (ZenMode ? 33554432 : 0); - num |= (SmallCubes ? 67108864 : 0); - writer.WriteInt32(num); - } public enum EnabledObstacleType { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs b/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs index bca5daf7..0728d1a3 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs @@ -87,60 +87,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteVarInt(MaxCombo); writer.WriteFloat32(EndSongTime); } - public void ReadFrom(ref MemoryBuffer reader) - { - GameplayModifiers.ReadFrom(ref reader); - ModifiedScore = reader.ReadVarInt(); - MultipliedScore = reader.ReadVarInt(); - Rank = (Rank)reader.ReadVarInt(); - FullCombo = reader.ReadBool(); - LeftSaberMovementDistance = reader.ReadFloat32(); - RightSaberMovementDistance = reader.ReadFloat32(); - LeftHandMovementDistance = reader.ReadFloat32(); - RightHandMovementDistance = reader.ReadFloat32(); - LevelEndStateType = (LevelEndStateType)reader.ReadVarInt(); - LevelEndAction = (LevelEndAction)reader.ReadVarInt(); - Energy = reader.ReadFloat32(); - GoodCutsCount = reader.ReadVarInt(); - BadCutsCount = reader.ReadVarInt(); - MissedCount = reader.ReadVarInt(); - NotGoodCount = reader.ReadVarInt(); - OkCount = reader.ReadVarInt(); - MaxCutScore = reader.ReadVarInt(); - TotalCutScore = reader.ReadVarInt(); - GoodCutsCountForNotesWithFullScoreScoringType = reader.ReadVarInt(); - AverageCenterDistanceCutScoreForNotesWithFullScoreScoringType = reader.ReadFloat32(); - AverageCutScoreForNotesWithFullScoreScoringType = reader.ReadFloat32(); - MaxCombo = reader.ReadVarInt(); - EndSongTime = reader.ReadFloat32(); - } - - public void WriteTo(ref MemoryBuffer writer) - { - GameplayModifiers.WriteTo(ref writer); - writer.WriteVarInt(ModifiedScore); - writer.WriteVarInt(MultipliedScore); - writer.WriteVarInt((int)Rank); - writer.WriteBool(FullCombo); - writer.WriteFloat32(LeftSaberMovementDistance); - writer.WriteFloat32(RightSaberMovementDistance); - writer.WriteFloat32(LeftHandMovementDistance); - writer.WriteFloat32(RightHandMovementDistance); - writer.WriteVarInt((int)LevelEndStateType); - writer.WriteVarInt((int)LevelEndAction); - writer.WriteFloat32(Energy); - writer.WriteVarInt(GoodCutsCount); - writer.WriteVarInt(BadCutsCount); - writer.WriteVarInt(MissedCount); - writer.WriteVarInt(NotGoodCount); - writer.WriteVarInt(OkCount); - writer.WriteVarInt(MaxCutScore); - writer.WriteVarInt(TotalCutScore); - writer.WriteVarInt(GoodCutsCountForNotesWithFullScoreScoringType); - writer.WriteFloat32(AverageCenterDistanceCutScoreForNotesWithFullScoreScoringType); - writer.WriteFloat32(AverageCutScoreForNotesWithFullScoreScoringType); - writer.WriteVarInt(MaxCombo); - writer.WriteFloat32(EndSongTime); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerLevelCompletionResults.cs b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerLevelCompletionResults.cs index c8aa8dcd..63efd302 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerLevelCompletionResults.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerLevelCompletionResults.cs @@ -28,23 +28,6 @@ public void WriteTo(ref SpanBuffer writer) if (HasAnyResult()) LevelCompletionResults.WriteTo(ref writer); } - public void ReadFrom(ref MemoryBuffer reader) - { - PlayerLevelEndState = (MultiplayerPlayerLevelEndState) reader.ReadVarInt(); - PlayerLevelEndReason = (MultiplayerPlayerLevelEndReason) reader.ReadVarInt(); - - if (HasAnyResult()) - LevelCompletionResults.ReadFrom(ref reader); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteVarInt((int) PlayerLevelEndState); - writer.WriteVarInt((int) PlayerLevelEndReason); - - if (HasAnyResult()) - LevelCompletionResults.WriteTo(ref writer); - } public bool HasAnyResult() { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/NodePoseSyncState.cs b/BeatTogether.DedicatedServer.Messaging/Models/NodePoseSyncState.cs index f382059f..d2b8abda 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/NodePoseSyncState.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/NodePoseSyncState.cs @@ -22,18 +22,5 @@ public void WriteTo(ref SpanBuffer writer) LeftController.WriteTo(ref writer); RightController.WriteTo(ref writer); } - public void ReadFrom(ref MemoryBuffer reader) - { - Head.ReadFrom(ref reader); - LeftController.ReadFrom(ref reader); - RightController.ReadFrom(ref reader); - } - - public void WriteTo(ref MemoryBuffer writer) - { - Head.WriteTo(ref writer); - LeftController.WriteTo(ref writer); - RightController.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/NoteCutInfo.cs b/BeatTogether.DedicatedServer.Messaging/Models/NoteCutInfo.cs index 45fd5fff..890d66f4 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/NoteCutInfo.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/NoteCutInfo.cs @@ -60,42 +60,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteFloat32(TimeToNextNote); MoveVec.WriteTo(ref writer); } - public void ReadFrom(ref MemoryBuffer reader) - { - CutWasOk = reader.ReadUInt8(); - SaberSpeed = reader.ReadFloat32(); - SaberDir.ReadFrom(ref reader); - CutPoint.ReadFrom(ref reader); - CutNormal.ReadFrom(ref reader); - NotePosition.ReadFrom(ref reader); - NoteScale.ReadFrom(ref reader); - NoteRotation.ReadFrom(ref reader); - GameplayType = (NoteGameplayType) reader.ReadVarInt(); - ColorType = reader.ReadVarInt(); - LineLayer = reader.ReadVarInt(); - NoteLineIndex = reader.ReadVarInt(); - NoteTime = reader.ReadFloat32(); - TimeToNextNote = reader.ReadFloat32(); - MoveVec.ReadFrom(ref reader); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteUInt8(CutWasOk); - writer.WriteFloat32(SaberSpeed); - SaberDir.WriteTo(ref writer); - CutPoint.WriteTo(ref writer); - CutNormal.WriteTo(ref writer); - NotePosition.WriteTo(ref writer); - NoteScale.WriteTo(ref writer); - NoteRotation.WriteTo(ref writer); - writer.WriteVarInt((int)GameplayType); - writer.WriteVarInt(ColorType); - writer.WriteVarInt(LineLayer); - writer.WriteVarInt(NoteLineIndex); - writer.WriteFloat32(NoteTime); - writer.WriteFloat32(TimeToNextNote); - MoveVec.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/NoteMissInfo.cs b/BeatTogether.DedicatedServer.Messaging/Models/NoteMissInfo.cs index 81ef67c1..98dbe7a8 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/NoteMissInfo.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/NoteMissInfo.cs @@ -26,20 +26,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteVarInt(NoteLineIndex); writer.WriteFloat32(NoteTime); } - public void ReadFrom(ref MemoryBuffer reader) - { - ColorType = reader.ReadVarInt(); - NoteLineLayer = reader.ReadVarInt(); - NoteLineIndex = reader.ReadVarInt(); - NoteTime = reader.ReadFloat32(); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteVarInt(ColorType); - writer.WriteVarInt(NoteLineLayer); - writer.WriteVarInt(NoteLineIndex); - writer.WriteFloat32(NoteTime); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/PlayerPermissionConfiguration.cs b/BeatTogether.DedicatedServer.Messaging/Models/PlayerPermissionConfiguration.cs index 0f01fa4e..a0e707f1 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/PlayerPermissionConfiguration.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/PlayerPermissionConfiguration.cs @@ -30,22 +30,5 @@ public void WriteTo(ref SpanBuffer writer) int num = (IsServerOwner ? 1 : 0) | (HasRecommendBeatmapsPermission ? 2 : 0) | (HasRecommendGameplayModifiersPermission ? 4 : 0) | (HasKickVotePermission ? 8 : 0) | (HasInvitePermission ? 16 : 0); writer.WriteUInt8((byte)num); } - public void ReadFrom(ref MemoryBuffer reader) - { - UserId = reader.ReadString(); - byte num = reader.ReadUInt8(); - IsServerOwner = (num & 1) > 0; - HasRecommendBeatmapsPermission = (num & 2) > 0; - HasRecommendGameplayModifiersPermission = (num & 4) > 0; - HasKickVotePermission = (num & 8) > 0; - HasInvitePermission = (num & 16) > 0; - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteString(UserId); - int num = (IsServerOwner ? 1 : 0) | (HasRecommendBeatmapsPermission ? 2 : 0) | (HasRecommendGameplayModifiersPermission ? 4 : 0) | (HasKickVotePermission ? 8 : 0) | (HasInvitePermission ? 16 : 0); - writer.WriteUInt8((byte)num); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettings.cs b/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettings.cs index a7efdcf4..7ae7ce6a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettings.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettings.cs @@ -35,26 +35,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteFloat32(HeadPosToPlayerHeightOffset); ColorScheme.WriteTo(ref writer); } - public void ReadFrom(ref MemoryBuffer reader) - { - UserId = reader.ReadString(); - UserName = reader.ReadString(); - LeftHanded = reader.ReadBool(); - AutomaticPlayerHeight = reader.ReadBool(); - PlayerHeight = reader.ReadFloat32(); - HeadPosToPlayerHeightOffset = reader.ReadFloat32(); - ColorScheme.ReadFrom(ref reader); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteString(UserId); - writer.WriteString(UserName); - writer.WriteBool(LeftHanded); - writer.WriteBool(AutomaticPlayerHeight); - writer.WriteFloat32(PlayerHeight); - writer.WriteFloat32(HeadPosToPlayerHeightOffset); - ColorScheme.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettingsAtStart.cs b/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettingsAtStart.cs index c97694a7..b2fc948d 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettingsAtStart.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettingsAtStart.cs @@ -25,23 +25,5 @@ public void WriteTo(ref SpanBuffer writer) playerSpecificSettings.WriteTo(ref writer); } } - public void ReadFrom(ref MemoryBuffer reader) - { - int count = reader.ReadInt32(); - ActivePlayerSpecificSettingsAtStart = new PlayerSpecificSettings[count]; - for (int i = 0; i < count; i++) - { - ActivePlayerSpecificSettingsAtStart[i].ReadFrom(ref reader); - } - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteInt32(ActivePlayerSpecificSettingsAtStart.Length); - foreach(PlayerSpecificSettings playerSpecificSettings in ActivePlayerSpecificSettingsAtStart) - { - playerSpecificSettings.WriteTo(ref writer); - } - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/PlayersPermissionConfiguration.cs b/BeatTogether.DedicatedServer.Messaging/Models/PlayersPermissionConfiguration.cs index bde47daf..435033d2 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/PlayersPermissionConfiguration.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/PlayersPermissionConfiguration.cs @@ -24,22 +24,5 @@ public void WriteTo(ref SpanBuffer writer) PlayersPermission[i].WriteTo(ref writer); } } - public void ReadFrom(ref MemoryBuffer reader) - { - PlayersPermission = new PlayerPermissionConfiguration[reader.ReadInt32()]; - for (int i = 0; i < PlayersPermission.Length; i++) - { - PlayersPermission[i].ReadFrom(ref reader); - } - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteInt32(PlayersPermission.Length); - for (int i = 0; i < PlayersPermission.Length; i++) - { - PlayersPermission[i].WriteTo(ref writer); - } - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/Pose.cs b/BeatTogether.DedicatedServer.Messaging/Models/Pose.cs index 5212b4a2..31ad728a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/Pose.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/Pose.cs @@ -20,16 +20,5 @@ public void WriteTo(ref SpanBuffer writer) Position.WriteTo(ref writer); Rotation.WriteTo(ref writer); } - public void ReadFrom(ref MemoryBuffer reader) - { - Position.ReadFrom(ref reader); - Rotation.ReadFrom(ref reader); - } - - public void WriteTo(ref MemoryBuffer writer) - { - Position.WriteTo(ref writer); - Rotation.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ProcessingPacketInfo.cs b/BeatTogether.DedicatedServer.Messaging/Models/ProcessingPacketInfo.cs deleted file mode 100644 index 0a7cbae6..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Models/ProcessingPacketInfo.cs +++ /dev/null @@ -1,11 +0,0 @@ -using BeatTogether.LiteNetLib.Abstractions; - -namespace BeatTogether.DedicatedServer.Messaging.Models -{ - public struct ProcessingPacketInfo //TODO this isnt used? - { - public uint length; - public int startPosition; - public INetSerializable packet; - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Models/Quaternion.cs b/BeatTogether.DedicatedServer.Messaging/Models/Quaternion.cs index ca18d99b..7312ff1f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/Quaternion.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/Quaternion.cs @@ -23,18 +23,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteVarInt(b); writer.WriteVarInt(c); } - public void ReadFrom(ref MemoryBuffer reader) - { - a = reader.ReadVarInt(); - b = reader.ReadVarInt(); - c = reader.ReadVarInt(); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteVarInt(a); - writer.WriteVarInt(b); - writer.WriteVarInt(c); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/StandardScoreSyncState.cs b/BeatTogether.DedicatedServer.Messaging/Models/StandardScoreSyncState.cs index 5236b564..8ce31866 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/StandardScoreSyncState.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/StandardScoreSyncState.cs @@ -29,22 +29,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteVarInt(Combo); writer.WriteVarInt(Multiplier); } - public void ReadFrom(ref MemoryBuffer reader) - { - ModifiedScore = reader.ReadVarInt(); - RawScore = reader.ReadVarInt(); - ImmediateMaxPossibleScore = reader.ReadVarInt(); - Combo = reader.ReadVarInt(); - Multiplier = reader.ReadVarInt(); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteVarInt(ModifiedScore); - writer.WriteVarInt(RawScore); - writer.WriteVarInt(ImmediateMaxPossibleScore); - writer.WriteVarInt(Combo); - writer.WriteVarInt(Multiplier); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/Vector3.cs b/BeatTogether.DedicatedServer.Messaging/Models/Vector3.cs index eb997594..81e77059 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/Vector3.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/Vector3.cs @@ -23,18 +23,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteVarInt(y); writer.WriteVarInt(z); } - public void ReadFrom(ref MemoryBuffer reader) - { - x = reader.ReadVarInt(); - y = reader.ReadVarInt(); - z = reader.ReadVarInt(); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteVarInt(x); - writer.WriteVarInt(y); - writer.WriteVarInt(z); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/KickPlayerPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/KickPlayerPacket.cs index f4fbd0b0..11d20307 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/KickPlayerPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/KickPlayerPacket.cs @@ -18,14 +18,5 @@ public void ReadFrom(ref SpanBuffer reader) { DisconnectedReason = (DisconnectedReason)reader.ReadVarInt(); } - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteVarInt((int)DisconnectedReason); - } - - public void ReadFrom(ref MemoryBuffer reader) - { - DisconnectedReason = (DisconnectedReason)reader.ReadVarInt(); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/LevelFinishedPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/LevelFinishedPacket.cs index 8b42ea85..1f822918 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/LevelFinishedPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/LevelFinishedPacket.cs @@ -20,17 +20,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); Results.WriteTo(ref writer); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - Results.ReadFrom(ref reader); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - Results.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteCutPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteCutPacket.cs index 64179377..a1382dcd 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteCutPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteCutPacket.cs @@ -24,20 +24,5 @@ public override void WriteTo(ref SpanBuffer writer) writer.WriteFloat32(SongTime); Info.WriteTo(ref writer); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - SongTime = reader.ReadFloat32(); - if (HasValue1) - Info.ReadFrom(ref reader); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteFloat32(SongTime); - Info.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteMissPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteMissPacket.cs index 226caded..a1ac658b 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteMissPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteMissPacket.cs @@ -24,20 +24,5 @@ public override void WriteTo(ref SpanBuffer writer) writer.WriteFloat32(SongTime); Info.WriteTo(ref writer); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - SongTime = reader.ReadFloat32(); - if (HasValue1) - Info.ReadFrom(ref reader); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteFloat32(SongTime); - Info.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteSpawn.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteSpawn.cs new file mode 100644 index 00000000..e5b6166e --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteSpawn.cs @@ -0,0 +1,17 @@ +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.LiteNetLib.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc +{ + public sealed class NoteSpawnPacket : BaseRpcWithValuesPacket + { + public override void ReadFrom(ref SpanBuffer reader) + { + base.ReadFrom(ref reader); + } + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/ObstacleSpawnPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/ObstacleSpawnPacket.cs new file mode 100644 index 00000000..874859c3 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/ObstacleSpawnPacket.cs @@ -0,0 +1,17 @@ +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.LiteNetLib.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc +{ + public sealed class ObstacleSpawnPacket : BaseRpcWithValuesPacket + { + public override void ReadFrom(ref SpanBuffer reader) + { + base.ReadFrom(ref reader); + } + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacket.cs index f0ba48dd..e410a0d6 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacket.cs @@ -20,17 +20,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); PlayerSpecificSettings.WriteTo(ref writer); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - PlayerSpecificSettings.ReadFrom(ref reader); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - PlayerSpecificSettings.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneSyncFinishedPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneSyncFinishedPacket.cs index 4ec0c206..a2bd9479 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneSyncFinishedPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneSyncFinishedPacket.cs @@ -25,20 +25,5 @@ public override void WriteTo(ref SpanBuffer writer) PlayersAtStart.WriteTo(ref writer); writer.WriteString(SessionGameId); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - PlayersAtStart.ReadFrom(ref reader); - if (HasValue1) - SessionGameId = reader.ReadString(); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - PlayersAtStart.WriteTo(ref writer); - writer.WriteString(SessionGameId); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetPlayerDidConnectLatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetPlayerDidConnectLatePacket.cs index 49c03055..35296123 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetPlayerDidConnectLatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetPlayerDidConnectLatePacket.cs @@ -29,23 +29,5 @@ public override void WriteTo(ref SpanBuffer writer) PlayersAtStart.WriteTo(ref writer); writer.WriteString(SessionGameId); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - UserId = reader.ReadString(); - if (HasValue1) - PlayersAtStart.ReadFrom(ref reader); - if (HasValue2) - SessionGameId = reader.ReadString(); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteString(UserId); - PlayersAtStart.WriteTo(ref writer); - writer.WriteString(SessionGameId); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs index a713293f..ae7fae63 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs @@ -19,17 +19,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); writer.WriteFloat32(StartTime); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - StartTime = reader.ReadFloat32(); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteFloat32(StartTime); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SliderSpawnPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SliderSpawnPacket.cs new file mode 100644 index 00000000..c0d3f7d0 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SliderSpawnPacket.cs @@ -0,0 +1,17 @@ +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.LiteNetLib.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc +{ + public sealed class SliderSpawnPacket : BaseRpcWithValuesPacket + { + public override void ReadFrom(ref SpanBuffer reader) + { + base.ReadFrom(ref reader); + } + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcBasePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcBasePacket.cs new file mode 100644 index 00000000..67c08941 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcBasePacket.cs @@ -0,0 +1,26 @@ +using BeatTogether.Extensions; +using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets +{ + public class MpcBasePacket : INetSerializable + { + + public uint ProtocolVersion; + + public virtual void WriteTo(ref SpanBuffer writer) + { + ProtocolVersion = 1; + + writer.WriteVarUInt(ProtocolVersion); + } + + public virtual void ReadFrom(ref SpanBuffer reader) + { + ProtocolVersion = reader.ReadVarUInt(); + } + } +} + + diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcCapabilitiesPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcCapabilitiesPacket.cs new file mode 100644 index 00000000..4ec207dc --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcCapabilitiesPacket.cs @@ -0,0 +1,30 @@ +using BeatTogether.LiteNetLib.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets +{ + public class MpcCapabilitiesPacket : MpcBasePacket + { + public bool CanTextChat; + public bool CanReceiveVoiceChat; + public bool CanTransmitVoiceChat; + + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteBool(CanTextChat); + writer.WriteBool(CanReceiveVoiceChat); + writer.WriteBool(CanTransmitVoiceChat); + } + + public override void ReadFrom(ref SpanBuffer reader) + { + base.ReadFrom(ref reader); + + CanTextChat = reader.ReadBool(); + CanReceiveVoiceChat = reader.ReadBool(); + CanTransmitVoiceChat = reader.ReadBool(); + } + } +} + + diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcTextChatPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcTextChatPacket.cs new file mode 100644 index 00000000..79ae54bf --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcTextChatPacket.cs @@ -0,0 +1,25 @@ +using BeatTogether.Extensions; +using BeatTogether.LiteNetLib.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets +{ + public class MpcTextChatPacket : MpcBasePacket + { + public string Text = string.Empty; + + public override void WriteTo(ref SpanBuffer writer) + { + base.WriteTo(ref writer); + writer.WriteString(Text); + } + + public override void ReadFrom(ref SpanBuffer reader) + { + base.ReadFrom(ref reader); + + Text = reader.ReadString(); + } + } +} + + diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/GetIsEntitledToLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/GetIsEntitledToLevelPacket.cs index 1ac09535..a46c404f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/GetIsEntitledToLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/GetIsEntitledToLevelPacket.cs @@ -20,17 +20,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); writer.WriteString(LevelId); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - LevelId = reader.ReadString(); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteString(LevelId); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/RequestKickPlayerPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/RequestKickPlayerPacket.cs index d8aa404b..a892511a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/RequestKickPlayerPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/RequestKickPlayerPacket.cs @@ -16,18 +16,6 @@ public override void ReadFrom(ref SpanBuffer reader) } public override void WriteTo(ref SpanBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteString(KickedPlayerId); - } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - KickedPlayerId = reader.ReadString(); - } - - public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteString(KickedPlayerId); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs index 36ca72ab..25612d0d 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs @@ -15,18 +15,6 @@ public override void ReadFrom(ref SpanBuffer reader) } public override void WriteTo(ref SpanBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteFloat32(CountdownTime); - } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - CountdownTime = reader.ReadFloat32(); - } - - public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteFloat32(CountdownTime); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacket.cs index 2d2a4c5c..da82342c 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacket.cs @@ -25,20 +25,5 @@ public override void WriteTo(ref SpanBuffer writer) writer.WriteString(LevelId); writer.WriteVarInt((int)Entitlement); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - LevelId = reader.ReadString(); - if (HasValue1) - Entitlement = (EntitlementStatus)reader.ReadVarInt(); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteString(LevelId); - writer.WriteVarInt((int)Entitlement); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsInLobbyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsInLobbyPacket.cs index 28b5c79b..8bac21b9 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsInLobbyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsInLobbyPacket.cs @@ -19,17 +19,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); writer.WriteBool(IsInLobby); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - IsInLobby = reader.ReadBool(); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteBool(IsInLobby); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsReadyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsReadyPacket.cs index 41340279..2714ade7 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsReadyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsReadyPacket.cs @@ -19,17 +19,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); writer.WriteBool(IsReady); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - IsReady = reader.ReadBool(); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteBool(IsReady); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsStartButtonEnabledPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsStartButtonEnabledPacket.cs index 0bc8d8d6..eedf9f3e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsStartButtonEnabledPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsStartButtonEnabledPacket.cs @@ -17,18 +17,6 @@ public override void ReadFrom(ref SpanBuffer reader) } public override void WriteTo(ref SpanBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteVarInt((int)Reason); - } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - Reason = (CannotStartGameReason)reader.ReadVarInt(); - } - - public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteVarInt((int)Reason); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs index 82766326..0965ea4e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs @@ -21,17 +21,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); writer.WriteVarInt((int)State); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - State = (MultiplayerGameState)reader.ReadVarInt(); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteVarInt((int)State); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetOwnedSongPacksPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetOwnedSongPacksPacket.cs index e6d93e10..693cd0f8 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetOwnedSongPacksPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetOwnedSongPacksPacket.cs @@ -20,17 +20,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); SongPackMask?.WriteTo(ref writer); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - SongPackMask.ReadFrom(ref reader); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - SongPackMask?.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersMissingEntitlementsToLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersMissingEntitlementsToLevelPacket.cs index fc1e9f2e..a127c77a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersMissingEntitlementsToLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersMissingEntitlementsToLevelPacket.cs @@ -27,30 +27,6 @@ public override void WriteTo(ref SpanBuffer writer) { base.WriteTo(ref writer); - writer.WriteInt32(PlayersWithoutEntitlements.Length); - foreach (string player in PlayersWithoutEntitlements) - { - writer.WriteString(player); - } - } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - - if (HasValue0) - { - PlayersWithoutEntitlements = new string[reader.ReadInt32()]; - for (int i = 0; i < PlayersWithoutEntitlements.Length; i++) - { - PlayersWithoutEntitlements[i] = reader.ReadString(); - } - } - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteInt32(PlayersWithoutEntitlements.Length); foreach (string player in PlayersWithoutEntitlements) { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersPermissionConfigurationPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersPermissionConfigurationPacket.cs index 5ad619cd..6152c16a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersPermissionConfigurationPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersPermissionConfigurationPacket.cs @@ -20,17 +20,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); PermissionConfiguration.WriteTo(ref writer); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - PermissionConfiguration.ReadFrom(ref reader); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - PermissionConfiguration.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacket.cs index c9f3b018..dd12e1a3 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacket.cs @@ -20,17 +20,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); BeatmapIdentifier.WriteTo(ref writer); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - BeatmapIdentifier.ReadFrom(ref reader); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - BeatmapIdentifier.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacket.cs index 9c197187..faa5fc5d 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacket.cs @@ -20,17 +20,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); Modifiers.WriteTo(ref writer); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - Modifiers.ReadFrom(ref reader); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - Modifiers.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedBeatmap.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedBeatmap.cs index 042ba5ea..fd74c077 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedBeatmap.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedBeatmap.cs @@ -20,17 +20,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); Beatmap.WriteTo(ref writer); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - Beatmap.ReadFrom(ref reader); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - Beatmap.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedGameplayModifiers.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedGameplayModifiers.cs index 7b4ac002..7edb19c3 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedGameplayModifiers.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedGameplayModifiers.cs @@ -20,17 +20,5 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); Modifiers.WriteTo(ref writer); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - Modifiers.ReadFrom(ref reader); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - Modifiers.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs index 1d0b90cd..753b9f6c 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs @@ -15,18 +15,6 @@ public override void ReadFrom(ref SpanBuffer reader) } public override void WriteTo(ref SpanBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteFloat32(StartTime); - } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - StartTime = reader.ReadFloat32(); - } - - public override void WriteTo(ref MemoryBuffer writer) { base.WriteTo(ref writer); writer.WriteFloat32(StartTime); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs index da876d0c..fb9a9a32 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs @@ -28,23 +28,5 @@ public override void WriteTo(ref SpanBuffer writer) Modifiers.WriteTo(ref writer); writer.WriteFloat32(StartTime); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - if (HasValue0) - Beatmap.ReadFrom(ref reader); - if (HasValue1) - Modifiers.ReadFrom(ref reader); - if (HasValue2) - StartTime = reader.ReadFloat32(); - } - - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - Beatmap.WriteTo(ref writer); - Modifiers.WriteTo(ref writer); - writer.WriteFloat32(StartTime); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/DediPacketSetNewManager.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/DediPacketSetNewManager.cs index 9abfecec..efe1c4bf 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/DediPacketSetNewManager.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/DediPacketSetNewManager.cs @@ -17,14 +17,5 @@ public void ReadFrom(ref SpanBuffer bufferReader) { NewManagerID = bufferReader.ReadString(); } - public void WriteTo(ref MemoryBuffer bufferWriter) - { - bufferWriter.WriteString(NewManagerID); - } - - public void ReadFrom(ref MemoryBuffer bufferReader) - { - NewManagerID = bufferReader.ReadString(); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs index 31000e1c..990d3738 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs @@ -24,11 +24,6 @@ public void WriteTo(ref SpanBuffer bufferWriter) { throw new System.NotImplementedException(); } - - public void WriteTo(ref MemoryBuffer bufferWriter) - { - throw new System.NotImplementedException(); - } public void ReadFrom(ref SpanBuffer bufferReader) { levelHash = bufferReader.ReadString(); @@ -68,46 +63,5 @@ public void ReadFrom(ref SpanBuffer bufferReader) bufferReader.ReadColor(); } } - - public void ReadFrom(ref MemoryBuffer bufferReader) - { - levelHash = bufferReader.ReadString(); - songName = bufferReader.ReadString(); - songSubName = bufferReader.ReadString(); - songAuthorName = bufferReader.ReadString(); - levelAuthorName = bufferReader.ReadString(); - beatsPerMinute = bufferReader.ReadFloat32(); - songDuration = bufferReader.ReadFloat32(); - - characteristic = bufferReader.ReadString(); - difficulty = bufferReader.ReadUInt32(); - - var difficultyCount = bufferReader.ReadByte(); - for (int i = 0; i < difficultyCount; i++) - { - byte difficulty = bufferReader.ReadByte(); - var requirementCount = bufferReader.ReadByte(); - string[] reqsForDifficulty = new string[requirementCount]; - for (int j = 0; j < requirementCount; j++) - reqsForDifficulty[j] = bufferReader.ReadString(); - requirements[difficulty] = reqsForDifficulty; - } - - byte count = bufferReader.ReadByte(); - for (int i = 0; i < count; i++) - { - bufferReader.ReadString(); - bufferReader.ReadString(); - bufferReader.ReadString(); - } - - byte count2 = bufferReader.ReadByte(); - for (int i = 0; i < count2; i++) - { - bufferReader.ReadByte(); - bufferReader.ReadColor(); - } - } - } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStateDeltaPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStateDeltaPacket.cs index 982f7253..2c5aa246 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStateDeltaPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStateDeltaPacket.cs @@ -26,20 +26,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteVarInt(TimeOffsetMs); Delta.WriteTo(ref writer); } - public void ReadFrom(ref MemoryBuffer reader) - { - SyncStateId = reader.ReadUInt8(); - TimeOffsetMs = reader.ReadVarInt(); - - if (!((SyncStateId & 128) > 0)) - Delta.ReadFrom(ref reader); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteUInt8(SyncStateId); - writer.WriteVarInt(TimeOffsetMs); - Delta.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs index 68c3debc..bd2e4729 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs @@ -24,18 +24,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteFloat32(Time); State.WriteTo(ref writer); } - public void ReadFrom(ref MemoryBuffer reader) - { - SyncStateId = reader.ReadUInt8(); - Time = reader.ReadFloat32(); - State.ReadFrom(ref reader); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteUInt8(SyncStateId); - writer.WriteFloat32(Time); - State.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStateDeltaPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStateDeltaPacket.cs index 4da7c9b7..bbf20f12 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStateDeltaPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStateDeltaPacket.cs @@ -25,19 +25,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteVarInt(TimeOffsetMs); Delta.WriteTo(ref writer); } - public void ReadFrom(ref MemoryBuffer reader) - { - SyncStateId = reader.ReadUInt8(); - TimeOffsetMs = reader.ReadVarInt(); - if (!((SyncStateId & 128) > 0)) - Delta.ReadFrom(ref reader); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteUInt8(SyncStateId); - writer.WriteVarInt(TimeOffsetMs); - Delta.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs index 4ea635ff..cec87d3d 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs @@ -23,18 +23,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteFloat32(Time); State.WriteTo(ref writer); } - public void ReadFrom(ref MemoryBuffer reader) - { - SyncStateId = reader.ReadUInt8(); - Time = reader.ReadFloat32(); - State.ReadFrom(ref reader); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteUInt8(SyncStateId); - writer.WriteFloat32(Time); - State.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs index facd8850..c2e6df18 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs @@ -16,14 +16,5 @@ public void ReadFrom(ref SpanBuffer reader) { PingTime = reader.ReadFloat32(); } - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteFloat32(PingTime); - } - - public void ReadFrom(ref MemoryBuffer reader) - { - PingTime = reader.ReadFloat32(); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerConnectedPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerConnectedPacket.cs index 4ebf8eca..85b1d35e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerConnectedPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerConnectedPacket.cs @@ -26,20 +26,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteString(UserName); writer.WriteBool(IsConnectionOwner); } - public void ReadFrom(ref MemoryBuffer reader) - { - RemoteConnectionId = reader.ReadUInt8(); - UserId = reader.ReadString(); - UserName = reader.ReadString(); - IsConnectionOwner = reader.ReadBool(); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteUInt8(RemoteConnectionId); - writer.WriteString(UserId); - writer.WriteString(UserName); - writer.WriteBool(IsConnectionOwner); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerDisconnectedPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerDisconnectedPacket.cs index eb702a95..174d0c01 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerDisconnectedPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerDisconnectedPacket.cs @@ -18,14 +18,5 @@ public void WriteTo(ref SpanBuffer writer) { writer.WriteVarInt((int)DisconnectedReason); } - public void ReadFrom(ref MemoryBuffer reader) - { - DisconnectedReason = (DisconnectedReason)reader.ReadVarInt(); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteVarInt((int)DisconnectedReason); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs index 6706582f..575df89a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs @@ -26,20 +26,5 @@ public void WriteTo(ref SpanBuffer writer) Random.WriteTo(ref writer); PublicEncryptionKey.WriteTo(ref writer); } - public void ReadFrom(ref MemoryBuffer reader) - { - PlayerState.ReadFrom(ref reader); - PlayerAvatar.ReadFrom(ref reader); - Random.ReadFrom(ref reader); - PublicEncryptionKey.ReadFrom(ref reader); - } - - public void WriteTo(ref MemoryBuffer writer) - { - PlayerState.WriteTo(ref writer); - PlayerAvatar.WriteTo(ref writer); - Random.WriteTo(ref writer); - PublicEncryptionKey.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs index dc33ee2b..1cb2ddf8 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs @@ -16,14 +16,5 @@ public void WriteTo(ref SpanBuffer writer) { writer.WriteFloat32(Latency); } - public void ReadFrom(ref MemoryBuffer reader) - { - Latency = reader.ReadFloat32(); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteFloat32(Latency); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerSortOrderPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerSortOrderPacket.cs index 41ff307f..57cc5ab8 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerSortOrderPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerSortOrderPacket.cs @@ -20,16 +20,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteString(UserId); writer.WriteVarInt(SortIndex); } - public void ReadFrom(ref MemoryBuffer reader) - { - UserId = reader.ReadString(); - SortIndex = reader.ReadVarInt(); - } - - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteString(UserId); - writer.WriteVarInt(SortIndex); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerStatePacket.cs index 1cc98118..1dd0d132 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerStatePacket.cs @@ -17,14 +17,5 @@ public void WriteTo(ref SpanBuffer writer) { PlayerState.WriteTo(ref writer); } - public void ReadFrom(ref MemoryBuffer reader) - { - PlayerState.ReadFrom(ref reader); - } - - public void WriteTo(ref MemoryBuffer writer) - { - PlayerState.WriteTo(ref writer); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs index 0680afb5..c244980e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs @@ -16,14 +16,5 @@ public void ReadFrom(ref SpanBuffer reader) { PingTime = reader.ReadFloat32(); } - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteFloat32(PingTime); - } - - public void ReadFrom(ref MemoryBuffer reader) - { - PingTime = reader.ReadFloat32(); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs index ac714cd5..60331ffa 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs @@ -16,14 +16,5 @@ public void ReadFrom(ref SpanBuffer reader) { SyncTime = reader.ReadFloat32(); } - public void WriteTo(ref MemoryBuffer writer) - { - writer.WriteFloat32(SyncTime); - } - - public void ReadFrom(ref MemoryBuffer reader) - { - SyncTime = reader.ReadFloat32(); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/GameplayRpcPacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/GameplayRpcPacketRegistry.cs index a53a54b3..fcf0a75a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/GameplayRpcPacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/GameplayRpcPacketRegistry.cs @@ -20,6 +20,9 @@ public override void Register() AddPacket(GameplayRpcPacketType.LevelFinished); AddPacket(GameplayRpcPacketType.NoteCut); AddPacket(GameplayRpcPacketType.NoteMissed); + AddPacket(GameplayRpcPacketType.ObstacleSpawned); + AddPacket(GameplayRpcPacketType.NoteSpawned); + AddPacket(GameplayRpcPacketType.SliderSpawned); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs index efdd1c42..731d1c83 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; using BeatTogether.LiteNetLib.Abstractions; using System; using System.Collections.Concurrent; @@ -8,13 +9,14 @@ namespace BeatTogether.DedicatedServer.Messaging.Registries { public class MultiplayerCorePacketRegistry : BasePacketRegistry { - private readonly ConcurrentDictionary _factories = new(); - public override void Register() { AddPacket(); AddPacket(); + AddPacket(); + AddPacket(); + AddPacket(); } public bool TryCreatePacket(string packetId, [MaybeNullWhen(false)] out INetSerializable packet) @@ -28,11 +30,9 @@ public bool TryCreatePacket(string packetId, [MaybeNullWhen(false)] out INetSeri packet = null; return false; } - protected void AddPacket() where T : class, INetSerializable, new() { Type typeFromHandle = typeof(T); - _factories[typeFromHandle.Name] = () => new T(); } } diff --git a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs index a7d8b419..4dcab520 100644 --- a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs +++ b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs @@ -3,7 +3,7 @@ public sealed class NodeConfiguration { public string HostName { get; set; } = "127.0.0.1"; - public string NodeVersion { get; } = "1.3.0"; + public string NodeVersion { get; } = "1.4.0"; public int BasePort { get; set; } = 30000; public int MaximumSlots { get; set; } = 10000; } diff --git a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs index 14c53d10..2cea0444 100644 --- a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs +++ b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs @@ -79,10 +79,10 @@ private Task HandlePlayerConnectedToMatchmaking(PlayerConnectedToMatchmakingServ _logger.Verbose( "Adding encrypted end point " + $"(RemoteEndPoint='{remoteEndPoint}', " + - $"Random='{BitConverter.ToString(random)}', " + - $"PublicKey='{BitConverter.ToString(publicKey)}')." + $"Random='{BitConverter.ToString(random!)}', " + + $"PublicKey='{BitConverter.ToString(publicKey!)}')." ); - _packetEncryptionLayer.AddEncryptedEndPoint(remoteEndPoint, random, publicKey); + _packetEncryptionLayer.AddEncryptedEndPoint(remoteEndPoint, random!, publicKey!); } else { diff --git a/BeatTogether.DedicatedServer.Node/NodeService.cs b/BeatTogether.DedicatedServer.Node/NodeService.cs index 2ec32121..429393da 100644 --- a/BeatTogether.DedicatedServer.Node/NodeService.cs +++ b/BeatTogether.DedicatedServer.Node/NodeService.cs @@ -68,14 +68,10 @@ public async Task CreateMatchmakingServer(Creat matchmakingServer.PlayerConnectedEvent += HandleUpdatePlayerEvent; matchmakingServer.PlayerDisconnectedEvent += HandlePlayerDisconnectEvent; - matchmakingServer.PlayerDisconnectBeforeJoining += HandlePlayerCountChange;//Updates master server player count - //matchmakingServer.StartEvent += HandleStartEvent; + matchmakingServer.PlayerDisconnectBeforeJoining += HandlePlayerLeaveBeforeJoining; matchmakingServer.StopEvent += HandleStopEvent; matchmakingServer.GameIsInLobby += HandleGameInLobbyEvent; - //matchmakingServer.StateChangedEvent += HandleStateChangedEvent; //For master server to check if a game is ongoing or not - //matchmakingServer.UpdateBeatmapEvent += HandleBeatmapChangedEvent; - //matchmakingServer.UpdateInstanceEvent += HandleConfigChangeEvent; - //matchmakingServer.LevelFinishedEvent += HandleLevelFinishedEvent; + matchmakingServer.UpdateInstanceEvent += HandleConfigChangeEvent; await matchmakingServer.Start(); return new CreateMatchmakingServerResponse( @@ -88,35 +84,11 @@ public async Task CreateMatchmakingServer(Creat #region EventHandlers - /* - private void HandleLevelFinishedEvent(string secret, BeatmapIdentifier beatmap, List<(string, BeatmapDifficulty, LevelCompletionResults)> Results) - { - Interface.Models.BeatmapIdentifier beatmapIdentifier = new(beatmap.LevelId, beatmap.Characteristic, (Interface.Models.BeatmapDifficulty)beatmap.Difficulty); - List<(string, Interface.Models.BeatmapDifficulty, Interface.Models.LevelCompletionResults)> FinalResults = new(); - foreach (var item in Results) - { - FinalResults.Add((item.Item1, (Interface.Models.BeatmapDifficulty)item.Item2, LevelCompletionCast(item.Item3))); - } - _autobus.Publish(new LevelCompletionResultsEvent(secret, beatmapIdentifier, FinalResults)); - } - */ + private void HandleGameInLobbyEvent(string secret, bool state) { - //_autobus.Publish(new UpdateStatusEvent(secret, (Interface.Enums.CountdownState)countdownState, (Interface.Enums.MultiplayerGameState)gameState, (Interface.Enums.GameplayState)GameplayState)); - _autobus.Publish(new ServerInGameplayEvent(secret, !state)); - } - /* - private void HandleStateChangedEvent(string secret, CountdownState countdownState, MultiplayerGameState gameState, GameplayManagerState GameplayState) - { - //_autobus.Publish(new UpdateStatusEvent(secret, (Interface.Enums.CountdownState)countdownState, (Interface.Enums.MultiplayerGameState)gameState, (Interface.Enums.GameplayState)GameplayState)); - _autobus.Publish(new ServerInGameplayEvent(secret, gameState == MultiplayerGameState.Game)); - } - - private void HandleBeatmapChangedEvent(string secret, BeatmapIdentifier? beatmap, GameplayModifiers modifiers, bool IsGameplay, DateTime StartTime) - { - _autobus.Publish(new SelectedBeatmapEvent(secret, beatmap is not null ? beatmap.LevelId : string.Empty, beatmap is not null ? beatmap.Characteristic : string.Empty, beatmap is not null ? (uint)beatmap.Difficulty : uint.MinValue, IsGameplay, GameplayCast(modifiers), StartTime)); + _autobus.Publish(new ServerInGameplayEvent(secret, !state, string.Empty)); } - */ public static Interface.Models.GameplayModifiers GameplayCast(GameplayModifiers v) { return new Interface.Models.GameplayModifiers((Interface.Models.EnergyType)v.Energy, v.NoFailOn0Energy, v.DemoNoFail, v.InstaFail, v.FailOnSaberClash, (Interface.Models.EnabledObstacleType)v.EnabledObstacle, v.DemoNoObstacles, v.FastNotes, v.StrictAngles, v.DisappearingArrows, v.GhostNotes, v.NoBombs, (Interface.Models.SongSpeed)v.Speed, v.NoArrows, v.ProMode, v.ZenMode, v.SmallCubes); @@ -146,11 +118,12 @@ public static Interface.Models.AvatarData AvatarCast(AvatarData v) v.MouthId); } - /* + private void HandleConfigChangeEvent(IDedicatedInstance inst) { - _autobus.Publish(new UpdateServerEvent( + _autobus.Publish(new UpdateInstanceConfigEvent( inst._configuration.Secret, + inst._configuration.ServerName, new Interface.Models.GameplayServerConfiguration( inst._configuration.MaxPlayerCount, (Interface.Enums.DiscoveryPolicy)inst._configuration.DiscoveryPolicy, @@ -158,47 +131,27 @@ private void HandleConfigChangeEvent(IDedicatedInstance inst) (Interface.Enums.GameplayServerMode)inst._configuration.GameplayServerMode, (Interface.Enums.SongSelectionMode)inst._configuration.SongSelectionMode, (Interface.Enums.GameplayServerControlSettings)inst._configuration.GameplayServerControlSettings - ), - inst._configuration.Port, - inst._configuration.ManagerId, - inst._configuration.ServerId, - inst._configuration.ServerName, - inst._configuration.DestroyInstanceTimeout, - inst._configuration.SetConstantManagerFromUserId, - inst._configuration.AllowPerPlayerDifficulties, - inst._configuration.AllowPerPlayerModifiers, - inst._configuration.AllowChroma, - inst._configuration.AllowMappingExtensions, - inst._configuration.AllowNoodleExtensions, - inst._configuration.KickPlayersWithoutEntitlementTimeout, - inst._configuration.CountdownConfig.CountdownTimePlayersReady, - inst._configuration.CountdownConfig.BeatMapStartCountdownTime, - inst._configuration.CountdownConfig.ResultsScreenTime)); + ) + )); } - private void HandleStartEvent(IDedicatedInstance inst) - { - HandleConfigChangeEvent(inst); - } - */ private void HandleStopEvent(IDedicatedInstance inst) { - _autobus.Publish(new MatchmakingServerStoppedEvent(inst._configuration.Secret));//Tells the master server and api server that the server has stopped + _autobus.Publish(new MatchmakingServerStoppedEvent(inst._configuration.Secret)); } - private void HandleUpdatePlayerEvent(IPlayer player, int PlayerCount) + private void HandleUpdatePlayerEvent(IPlayer player) { - _autobus.Publish(new PlayerLeaveServerEvent(player.Secret, string.Empty, string.Empty, PlayerCount)); - //_autobus.Publish(new PlayerJoinEvent(player.Secret, player.Endpoint.ToString()!, player.UserId, player.UserName, player.ConnectionId, player.SortIndex, AvatarCast(player.Avatar))); + _autobus.Publish(new PlayerJoinEvent(player.Secret, ((IPEndPoint)player.Endpoint).ToString(), player.UserId)); } - private void HandlePlayerDisconnectEvent(IPlayer player, int count) //Updates master server player count And removes the players encryption data from the server + private void HandlePlayerDisconnectEvent(IPlayer player) { _packetEncryptionLayer.RemoveEncryptedEndPoint((IPEndPoint)player.Endpoint); - _autobus.Publish(new PlayerLeaveServerEvent(player.Secret, player.UserId, ((IPEndPoint)player.Endpoint).ToString(), count)); + _autobus.Publish(new PlayerLeaveServerEvent(player.Secret, player.UserId, ((IPEndPoint)player.Endpoint).ToString())); } - private void HandlePlayerCountChange(string Secret, EndPoint endPoint, int count) //Updates master server player count + private void HandlePlayerLeaveBeforeJoining(string Secret, EndPoint endPoint, string[] Players) { _packetEncryptionLayer.RemoveEncryptedEndPoint((IPEndPoint)endPoint); - _autobus.Publish(new PlayerLeaveServerEvent(Secret,string.Empty, string.Empty, count)); + _autobus.Publish(new UpdatePlayersEvent(Secret, Players)); } #endregion } From 6749f68d295e41190edd4a6a669d9093b8d5ffe4 Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 8 May 2023 23:23:05 +0100 Subject: [PATCH 006/120] Bumped LNL dependency --- BeatTogether.DedicatedServer.Kernel/PacketSource.cs | 2 +- .../BeatTogether.DedicatedServer.Messaging.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index 60e51a10..e3f4944d 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -122,7 +122,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D } if(packet is NoteSpawnPacket || packet is ObstacleSpawnPacket || packet is SliderSpawnPacket) //Note packet logic { - if (_configuration.DisableNotes || _playerRegistry.GetPlayerCount() > 14) + if (_configuration.DisableNotes || _playerRegistry.GetPlayerCount() > 15) return; method = DeliveryMethod.Unreliable; break; diff --git a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj index 6500adec..4e4b8d33 100644 --- a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj +++ b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj @@ -9,7 +9,7 @@ - + From 4d110969a579509765850b126a16b41e7d18bbb1 Mon Sep 17 00:00:00 2001 From: cubic Date: Wed, 10 May 2023 20:26:52 +0100 Subject: [PATCH 007/120] Server now stores CLient version, Platform, and UsersPlatformID server side Connecting and disconnecting is now in a semaphore instead of a lock changed the names of several commands Added a ForceEnableNotes config Lessoned memory usage/cpu usage in packet encryption writer Lessoned memory allocations in the outbound packet function Removed concurrent dictionaries from player registry Changed locking logic for player joins/disconnects --- .../Abstractions/IHandshakeSessionRegistry.cs | 5 +- .../Abstractions/IPlayer.cs | 5 +- .../Abstractions/IPlayerRegistry.cs | 3 - ...Handler.cs => SetBeatmapRoutingHandler.cs} | 10 +- ...dHandler.cs => SetChromaCommandHandler.cs} | 8 +- ...dler.cs => SetMappingExtensionsHandler.cs} | 8 +- ...ndler.cs => SetNoodleExtensionsHandler.cs} | 8 +- ...fHandler.cs => SetPerPlayerDiffHandler.cs} | 8 +- ...odHandler.cs => SetPerPlayerModHandler.cs} | 8 +- ...leBeatmapNotes.cs => SetBeatmapRouting.cs} | 10 +- .../Commands/{AllowChroma.cs => SetChroma.cs} | 6 +- ...gExtensions.cs => SetMappingExtensions.cs} | 6 +- .../Commands/{AllowNoodle.cs => SetNoodle.cs} | 6 +- ...culties.cs => SetPerPlayerDifficulties.cs} | 6 +- ...rModifiers.cs => SetPerPlayerModifiers.cs} | 6 +- .../Configuration/InstanceConfiguration.cs | 1 + .../DedicatedInstance.cs | 511 ++++++++++-------- .../Abstractions/IEncryptedPacketWriter.cs | 1 - .../Encryption/EncryptedPacketWriter.cs | 12 +- .../Encryption/PacketEncryptionLayer.cs | 14 +- .../Enums/Platform.cs | 14 + .../Handshake/HandshakeSessionRegistry.cs | 21 + .../Managers/LobbyManager.cs | 9 +- .../PacketDispatcher.cs | 3 - .../GetExtraPlayerDataPacketHandler.cs | 35 ++ .../PacketSource.cs | 2 +- BeatTogether.DedicatedServer.Kernel/Player.cs | 4 +- .../PlayerRegistry.cs | 78 ++- .../TextCommandRepository.cs | 12 +- ...tTogether.DedicatedServer.Messaging.csproj | 2 +- .../Models/BitMask128.cs | 1 - .../Models/ConnectionRequestData.cs | 3 +- .../MpCorePackets/GetMpPlayerData.cs | 16 + .../MpCorePackets/MpPlayerData.cs | 26 + .../MultiplayerCorePacketRegistry.cs | 2 + .../BeatTogether.DedicatedServer.Node.csproj | 2 +- .../MasterServerEventHandler.cs | 12 +- 37 files changed, 534 insertions(+), 350 deletions(-) rename BeatTogether.DedicatedServer.Kernel/CommandHandlers/{DisableBeatmapNotesHandler.cs => SetBeatmapRoutingHandler.cs} (65%) rename BeatTogether.DedicatedServer.Kernel/CommandHandlers/{AllowChromaCommandHandler.cs => SetChromaCommandHandler.cs} (72%) rename BeatTogether.DedicatedServer.Kernel/CommandHandlers/{AllowMappingExtensionsHandler.cs => SetMappingExtensionsHandler.cs} (69%) rename BeatTogether.DedicatedServer.Kernel/CommandHandlers/{AllowNoodleExtensionsHandler.cs => SetNoodleExtensionsHandler.cs} (70%) rename BeatTogether.DedicatedServer.Kernel/CommandHandlers/{AllowPerPlayerDiffHandler.cs => SetPerPlayerDiffHandler.cs} (69%) rename BeatTogether.DedicatedServer.Kernel/CommandHandlers/{AllowPerPlayerModHandler.cs => SetPerPlayerModHandler.cs} (69%) rename BeatTogether.DedicatedServer.Kernel/Commands/{DisableBeatmapNotes.cs => SetBeatmapRouting.cs} (60%) rename BeatTogether.DedicatedServer.Kernel/Commands/{AllowChroma.cs => SetChroma.cs} (72%) rename BeatTogether.DedicatedServer.Kernel/Commands/{AllowMappingExtensions.cs => SetMappingExtensions.cs} (70%) rename BeatTogether.DedicatedServer.Kernel/Commands/{AllowNoodle.cs => SetNoodle.cs} (70%) rename BeatTogether.DedicatedServer.Kernel/Commands/{AllowPerPlayerDifficulties.cs => SetPerPlayerDifficulties.cs} (70%) rename BeatTogether.DedicatedServer.Kernel/Commands/{AllowPerPlayerModifiers.cs => SetPerPlayerModifiers.cs} (70%) create mode 100644 BeatTogether.DedicatedServer.Kernel/Enums/Platform.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetMpPlayerData.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPlayerData.cs diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeSessionRegistry.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeSessionRegistry.cs index 2152632a..03c7790e 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeSessionRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeSessionRegistry.cs @@ -1,4 +1,5 @@ -using System.Net; +using System.Diagnostics.CodeAnalysis; +using System.Net; using BeatTogether.DedicatedServer.Kernel.Handshake; namespace BeatTogether.DedicatedServer.Kernel.Abstractions @@ -8,6 +9,8 @@ public interface IHandshakeSessionRegistry HandshakeSession GetOrAdd(EndPoint endPoint); HandshakeSession? TryGetByPlayerSessionId(string playerSessionId); void AddPendingPlayerSessionId(string playerSessionId); + void AddExtraPlayerSessionData(string playerSessionId, string ClientVersion, byte Platform, string PlayerPlatformUserId); + void RemoveExtraPlayerSessionData(string playerSessionId, out string ClientVersion, out byte Platform, out string PlayerPlatformUserId); bool TryRemovePendingPlayerSessionId(string playerSessionId); } } \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index 7ae79bde..bfc30904 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -17,7 +17,9 @@ public interface IPlayer string UserName { get; } byte[]? Random { get; set; } byte[]? PublicEncryptionKey { get; set; } - + string ClientVersion { get; set; } + Platform Platform { get; set; } + string PlatformUserId { get; set; } object LatencyLock { get; set; } RollingAverage Latency { get; } float SyncTime { get; } @@ -50,7 +52,6 @@ public interface IPlayer bool IsActive { get; } bool FinishedLevel { get; } bool InMenu { get; } - bool IsModded { get; } object InLobbyLock { get; set; } bool InLobby { get; set; } object EntitlementLock { get; set; } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs index b630e42e..bf43f7fc 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs @@ -10,9 +10,6 @@ public interface IPlayerRegistry bool AddPlayer(IPlayer player); void RemovePlayer(IPlayer player); int GetPlayerCount(); - IPlayer GetPlayer(EndPoint remoteEndPoint); - IPlayer GetPlayer(byte connectionId); - IPlayer GetPlayer(string userId); bool TryGetPlayer(EndPoint remoteEndPoint, [MaybeNullWhen(false)] out IPlayer player); bool TryGetPlayer(byte connectionId, [MaybeNullWhen(false)] out IPlayer player); bool TryGetPlayer(string userId, [MaybeNullWhen(false)] out IPlayer player); diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/DisableBeatmapNotesHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetBeatmapRoutingHandler.cs similarity index 65% rename from BeatTogether.DedicatedServer.Kernel/CommandHandlers/DisableBeatmapNotesHandler.cs rename to BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetBeatmapRoutingHandler.cs index 022de726..6a20a14a 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/DisableBeatmapNotesHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetBeatmapRoutingHandler.cs @@ -5,23 +5,23 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers { - class DisableBeatmapNotesHandler : BaseCommandHandler + class SetNoteRoutingHandler : BaseCommandHandler { private readonly IPacketDispatcher _packetDisapatcher; private readonly InstanceConfiguration _Configuration; - public DisableBeatmapNotesHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + public SetNoteRoutingHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) { _packetDisapatcher = packetDisapatcher; _Configuration = instanceConfiguration; } - public override void Handle(IPlayer player, DisableBeatmapNotes command) + public override void Handle(IPlayer player, SetNoteRouting command) { - _Configuration.DisableNotes = command.Disabled; + _Configuration.DisableNotes = !command.Enabled; _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { - Text = "Disabled beatmap notes is: " + command.Disabled + Text = "Beatmap notes: " + command.Enabled }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowChromaCommandHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetChromaCommandHandler.cs similarity index 72% rename from BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowChromaCommandHandler.cs rename to BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetChromaCommandHandler.cs index f16cccfc..5521d2c3 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowChromaCommandHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetChromaCommandHandler.cs @@ -5,23 +5,23 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers { - class AllowChromaHandler : BaseCommandHandler + class SetChromaHandler : BaseCommandHandler { private readonly IPacketDispatcher _packetDisapatcher; private readonly InstanceConfiguration _Configuration; - public AllowChromaHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + public SetChromaHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) { _packetDisapatcher = packetDisapatcher; _Configuration = instanceConfiguration; } - public override void Handle(IPlayer player, AllowChroma command) + public override void Handle(IPlayer player, SetChroma command) { _Configuration.AllowChroma = command.Enabled; _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { - Text = "Allow Chroma is: " + command.Enabled + Text = "Chroma: " + command.Enabled }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowMappingExtensionsHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetMappingExtensionsHandler.cs similarity index 69% rename from BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowMappingExtensionsHandler.cs rename to BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetMappingExtensionsHandler.cs index d5b502ef..be6b056d 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowMappingExtensionsHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetMappingExtensionsHandler.cs @@ -5,23 +5,23 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers { - class AllowMappingExtensionsHandler : BaseCommandHandler + class SetMappingExtensionsHandler : BaseCommandHandler { private readonly IPacketDispatcher _packetDisapatcher; private readonly InstanceConfiguration _Configuration; - public AllowMappingExtensionsHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + public SetMappingExtensionsHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) { _packetDisapatcher = packetDisapatcher; _Configuration = instanceConfiguration; } - public override void Handle(IPlayer player, AllowMappingExtensions command) + public override void Handle(IPlayer player, SetMappingExtensions command) { _Configuration.AllowMappingExtensions = command.Enabled; _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { - Text = "Allow Mapping Extensions is: " + command.Enabled + Text = "Mapping Extensions: " + command.Enabled }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowNoodleExtensionsHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetNoodleExtensionsHandler.cs similarity index 70% rename from BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowNoodleExtensionsHandler.cs rename to BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetNoodleExtensionsHandler.cs index 37b216db..1f659ea2 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowNoodleExtensionsHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetNoodleExtensionsHandler.cs @@ -5,23 +5,23 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers { - class AllowNoodleExtensionsHandler : BaseCommandHandler + class SetNoodleExtensionsHandler : BaseCommandHandler { private readonly IPacketDispatcher _packetDisapatcher; private readonly InstanceConfiguration _Configuration; - public AllowNoodleExtensionsHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + public SetNoodleExtensionsHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) { _packetDisapatcher = packetDisapatcher; _Configuration = instanceConfiguration; } - public override void Handle(IPlayer player, AllowNoodle command) + public override void Handle(IPlayer player, SetNoodleExtensions command) { _Configuration.AllowNoodleExtensions = command.Enabled; _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { - Text = "Allow Noodle is: " + command.Enabled + Text = "Noodle Extensions: " + command.Enabled }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerDiffHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs similarity index 69% rename from BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerDiffHandler.cs rename to BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs index ec5f4ef1..143ba9ee 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerDiffHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs @@ -5,23 +5,23 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers { - class AllowPerPlayerDiffHandler : BaseCommandHandler + class SetPerPlayerDiffHandler : BaseCommandHandler { private readonly IPacketDispatcher _packetDisapatcher; private readonly InstanceConfiguration _Configuration; - public AllowPerPlayerDiffHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + public SetPerPlayerDiffHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) { _packetDisapatcher = packetDisapatcher; _Configuration = instanceConfiguration; } - public override void Handle(IPlayer player, AllowPerPlayerDifficulties command) + public override void Handle(IPlayer player, SetPerPlayerDifficulties command) { _Configuration.AllowPerPlayerDifficulties = command.Enabled; _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { - Text = "Allow per player difficulties is: " + command.Enabled + Text = "Per player difficulties: " + command.Enabled }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerModHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs similarity index 69% rename from BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerModHandler.cs rename to BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs index cdd033d0..87da208a 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/AllowPerPlayerModHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs @@ -5,23 +5,23 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers { - class AllowPerPlayerModHandler : BaseCommandHandler + class SetPerPlayerModifiersHandler : BaseCommandHandler { private readonly IPacketDispatcher _packetDisapatcher; private readonly InstanceConfiguration _Configuration; - public AllowPerPlayerModHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) + public SetPerPlayerModifiersHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) { _packetDisapatcher = packetDisapatcher; _Configuration = instanceConfiguration; } - public override void Handle(IPlayer player, AllowPerPlayerModifiers command) + public override void Handle(IPlayer player, SetPerPlayerModifiers command) { _Configuration.AllowPerPlayerModifiers = command.Enabled; _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { - Text = "Allow per player modifiers is: " + command.Enabled + Text = "Per player modifiers: " + command.Enabled }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); } } diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/DisableBeatmapNotes.cs b/BeatTogether.DedicatedServer.Kernel/Commands/SetBeatmapRouting.cs similarity index 60% rename from BeatTogether.DedicatedServer.Kernel/Commands/DisableBeatmapNotes.cs rename to BeatTogether.DedicatedServer.Kernel/Commands/SetBeatmapRouting.cs index 6c3158ff..46c07e74 100644 --- a/BeatTogether.DedicatedServer.Kernel/Commands/DisableBeatmapNotes.cs +++ b/BeatTogether.DedicatedServer.Kernel/Commands/SetBeatmapRouting.cs @@ -2,18 +2,18 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands { - public class DisableBeatmapNotes : ITextCommand + public class SetNoteRouting : ITextCommand { - public string CommandName => "disablenotes"; - public string ShortHandName => "dn"; + public string CommandName => "setnotesvisible"; + public string ShortHandName => "n"; public string Description => "disables beatmap notes if set to true. Notes will be disabled automaticly if there are over 14 players, default false"; - public bool Disabled = false; + public bool Enabled = true; public void ReadValues(string[] Values) { if (Values != null) - Disabled = Values[0] == "true"; + Enabled = Values[0] == "true" || Values[0] == "t"; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/AllowChroma.cs b/BeatTogether.DedicatedServer.Kernel/Commands/SetChroma.cs similarity index 72% rename from BeatTogether.DedicatedServer.Kernel/Commands/AllowChroma.cs rename to BeatTogether.DedicatedServer.Kernel/Commands/SetChroma.cs index 2762b0a3..c53ad358 100644 --- a/BeatTogether.DedicatedServer.Kernel/Commands/AllowChroma.cs +++ b/BeatTogether.DedicatedServer.Kernel/Commands/SetChroma.cs @@ -2,9 +2,9 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands { - public class AllowChroma : ITextCommand + public class SetChroma : ITextCommand { - public string CommandName => "allowchroma"; + public string CommandName => "setchroma"; public string ShortHandName => "ch"; public string Description => "if set to false, then chroma maps will be unplayable, default true"; @@ -13,7 +13,7 @@ public class AllowChroma : ITextCommand public void ReadValues(string[] Values) { if (Values != null) - Enabled = Values[0] == "true"; + Enabled = Values[0] == "true" || Values[0] == "t"; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/AllowMappingExtensions.cs b/BeatTogether.DedicatedServer.Kernel/Commands/SetMappingExtensions.cs similarity index 70% rename from BeatTogether.DedicatedServer.Kernel/Commands/AllowMappingExtensions.cs rename to BeatTogether.DedicatedServer.Kernel/Commands/SetMappingExtensions.cs index 739db5d5..71a1901a 100644 --- a/BeatTogether.DedicatedServer.Kernel/Commands/AllowMappingExtensions.cs +++ b/BeatTogether.DedicatedServer.Kernel/Commands/SetMappingExtensions.cs @@ -2,9 +2,9 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands { - public class AllowMappingExtensions : ITextCommand + public class SetMappingExtensions : ITextCommand { - public string CommandName => "allowme"; + public string CommandName => "setmappingextensions"; public string ShortHandName => "me"; public string Description => "if set to false, then mapping extensions maps will be unplayable, default true"; @@ -13,7 +13,7 @@ public class AllowMappingExtensions : ITextCommand public void ReadValues(string[] Values) { if (Values != null) - Enabled = Values[0] == "true"; + Enabled = Values[0] == "true" || Values[0] == "t"; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/AllowNoodle.cs b/BeatTogether.DedicatedServer.Kernel/Commands/SetNoodle.cs similarity index 70% rename from BeatTogether.DedicatedServer.Kernel/Commands/AllowNoodle.cs rename to BeatTogether.DedicatedServer.Kernel/Commands/SetNoodle.cs index 3ee599bf..33279b31 100644 --- a/BeatTogether.DedicatedServer.Kernel/Commands/AllowNoodle.cs +++ b/BeatTogether.DedicatedServer.Kernel/Commands/SetNoodle.cs @@ -2,9 +2,9 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands { - public class AllowNoodle : ITextCommand + public class SetNoodleExtensions : ITextCommand { - public string CommandName => "allownoodle"; + public string CommandName => "setnoodleextensions"; public string ShortHandName => "ne"; public string Description => "if set to false, then noodle maps will be unplayable, default true"; @@ -13,7 +13,7 @@ public class AllowNoodle : ITextCommand public void ReadValues(string[] Values) { if (Values != null) - Enabled = Values[0] == "true"; + Enabled = Values[0] == "true" || Values[0] == "t"; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerDifficulties.cs b/BeatTogether.DedicatedServer.Kernel/Commands/SetPerPlayerDifficulties.cs similarity index 70% rename from BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerDifficulties.cs rename to BeatTogether.DedicatedServer.Kernel/Commands/SetPerPlayerDifficulties.cs index 8dfcf61b..3dc1ce9d 100644 --- a/BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerDifficulties.cs +++ b/BeatTogether.DedicatedServer.Kernel/Commands/SetPerPlayerDifficulties.cs @@ -2,9 +2,9 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands { - public class AllowPerPlayerDifficulties : ITextCommand + public class SetPerPlayerDifficulties : ITextCommand { - public string CommandName => "allowperplayerdifficulties"; + public string CommandName => "setperplayerdifficulties"; public string ShortHandName => "ppd"; public string Description => "if set to true, then players will use what ever difficulty they have selected, default false"; @@ -13,7 +13,7 @@ public class AllowPerPlayerDifficulties : ITextCommand public void ReadValues(string[] Values) { if (Values != null) - Enabled = Values[0] == "true"; + Enabled = Values[0] == "true" || Values[0] == "t"; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerModifiers.cs b/BeatTogether.DedicatedServer.Kernel/Commands/SetPerPlayerModifiers.cs similarity index 70% rename from BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerModifiers.cs rename to BeatTogether.DedicatedServer.Kernel/Commands/SetPerPlayerModifiers.cs index cac4c1d6..26248bc5 100644 --- a/BeatTogether.DedicatedServer.Kernel/Commands/AllowPerPlayerModifiers.cs +++ b/BeatTogether.DedicatedServer.Kernel/Commands/SetPerPlayerModifiers.cs @@ -2,9 +2,9 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands { - public class AllowPerPlayerModifiers : ITextCommand + public class SetPerPlayerModifiers : ITextCommand { - public string CommandName => "allowperplayermodifiers"; + public string CommandName => "setperplayermodifiers"; public string ShortHandName => "ppm"; public string Description => "if set to true, then players will use what ever modifiers they have selected, default false"; @@ -13,7 +13,7 @@ public class AllowPerPlayerModifiers : ITextCommand public void ReadValues(string[] Values) { if (Values != null) - Enabled = Values[0] == "true"; + Enabled = Values[0] == "true" || Values[0] == "t"; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs index 124ecb43..d5af0a21 100644 --- a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs +++ b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs @@ -25,6 +25,7 @@ public sealed class InstanceConfiguration public bool AllowMappingExtensions { get; set; } public bool AllowNoodleExtensions { get; set; } public bool DisableNotes { get; set; } + public bool ForceEnableNotes { get; set; } = false; public float KickPlayersWithoutEntitlementTimeout { get; set; } = 30f; public int MaxLengthCommand { get; set; } = 200; public bool ApplyNoFailModifier { get; set; } = true; diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 832f05e0..fa96d8da 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading; @@ -12,6 +13,8 @@ using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; using BeatTogether.LiteNetLib; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Configuration; @@ -47,14 +50,19 @@ public sealed class DedicatedInstance : LiteNetServer, IDedicatedInstance private readonly IPlayerRegistry _playerRegistry; private readonly IServiceProvider _serviceProvider; private readonly PacketEncryptionLayer _packetEncryptionLayer; - - private readonly ConcurrentQueue _releasedConnectionIds = new(); - private readonly ConcurrentQueue _releasedSortIndices = new(); - private readonly ILogger _logger = Log.ForContext(); - private long _startTime; + private byte _connectionIdCount = 0; + private readonly object _ConnectionIDLock = new(); private int _lastSortIndex = -1; + private readonly object _SortIndexLock = new(); + private readonly Queue _releasedConnectionIds = new(); + private readonly object _releasedConnectionIds_Lock = new(); + private readonly Queue _releasedSortIndices = new(); + private readonly object _releasedSortIndices_Lock = new(); + private readonly ILogger _logger = Log.ForContext(); + + private long _startTime; private CancellationTokenSource? _waitForPlayerCts = null; private CancellationTokenSource? _stopServerCts; private IPacketDispatcher _packetDispatcher = null!; @@ -73,8 +81,7 @@ public DedicatedInstance( liteNetConfiguration, registry, serviceProvider, - false, - 0, + (configuration.MaxPlayerCount/5), packetLayer) { _configuration = configuration; @@ -179,12 +186,14 @@ public Task Stop(CancellationToken cancellationToken = default) return Task.CompletedTask; } - object SortIndexLock = new(); public int GetNextSortIndex() { - if (_releasedSortIndices.TryDequeue(out var sortIndex)) - return sortIndex; - lock (SortIndexLock) + lock (_releasedSortIndices_Lock) + { + if (_releasedSortIndices.TryDequeue(out var sortIndex)) + return sortIndex; + } + lock (_SortIndexLock) { _lastSortIndex++; if (_lastSortIndex > _configuration.MaxPlayerCount) @@ -195,27 +204,39 @@ public int GetNextSortIndex() } } - public void ReleaseSortIndex(int sortIndex) => - _releasedSortIndices.Enqueue(sortIndex); - - object ConnectionIDLock = new(); - public byte GetNextConnectionId() //ID 0 is server, ID 127 also means send to all players, 255 will mean perm spectator when/if implimented. Starts at 1 because funny server logic + public void ReleaseSortIndex(int sortIndex) { - if (_releasedConnectionIds.TryDequeue(out var connectionId)) - return connectionId; - lock (ConnectionIDLock) + lock (_releasedSortIndices_Lock) + { + _releasedSortIndices.Enqueue(sortIndex); + } + } + + public byte GetNextConnectionId() //ID 0 is server, ID 127 means send to all players + { + lock (_releasedConnectionIds_Lock) + { + if (_releasedConnectionIds.TryDequeue(out var connectionId)) + return connectionId; + } + lock (_ConnectionIDLock) { _connectionIdCount++; if (_connectionIdCount == 127) _connectionIdCount++; - if (_connectionIdCount > (byte.MaxValue - 5)) + if (_connectionIdCount > (byte.MaxValue - 5)) //Currently not implimented to use ID's over 126 client side return 255; //Give them an unusedID so they dont conflict with anyone return _connectionIdCount; } } - public void ReleaseConnectionId(byte connectionId) => - _releasedConnectionIds.Enqueue(connectionId); + public void ReleaseConnectionId(byte connectionId) + { + lock (_releasedConnectionIds_Lock) + { + _releasedConnectionIds.Enqueue(connectionId); + } + } public void SetState(MultiplayerGameState state) { @@ -231,8 +252,6 @@ public void SetState(MultiplayerGameState state) #region LiteNetServer - object AcceptConnectionLock = new(); - public override bool ShouldAcceptConnection(EndPoint endPoint, ref SpanBuffer additionalData) { @@ -245,6 +264,7 @@ public override bool ShouldAcceptConnection(EndPoint endPoint, ref SpanBuffer ad _logger.Information("connection accepted"); return true; } + private readonly object _PlayerJoining_Lock = new(); public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBuffer additionalData) { var connectionRequestData = new ConnectionRequestData(); @@ -266,33 +286,30 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBuffer additionalDat $"(RemoteEndPoint='{endPoint}', " + $"Secret='{connectionRequestData.Secret}', " + $"UserId='{connectionRequestData.UserId}', " + - $"UserName='{connectionRequestData.UserName}', " + - $"IsConnectionOwner={connectionRequestData.IsConnectionOwner})." + $"UserName='{connectionRequestData.UserName}', " ); if (string.IsNullOrEmpty(connectionRequestData.UserId) || string.IsNullOrEmpty(connectionRequestData.UserName)) - //string.IsNullOrEmpty(connectionRequestData.Secret)) { _logger.Warning( "Received a connection request with invalid data " + $"(RemoteEndPoint='{endPoint}', " + - //$"Secret='{connectionRequestData.Secret}', " + $"UserId='{connectionRequestData.UserId}', " + $"UserName='{connectionRequestData.UserName}', " + $"IsConnectionOwner={connectionRequestData.IsConnectionOwner})." ); return true; } - - lock (AcceptConnectionLock) + IPlayer player; + lock (_PlayerJoining_Lock) { if (_playerRegistry.GetPlayerCount() >= _configuration.MaxPlayerCount) { _logger.Information("Max player count"); return true; } - if(connectionRequestData.UserName == "IGGAMES" || connectionRequestData.UserName == "IGGGAMES") + if (connectionRequestData.UserName == "IGGAMES" || connectionRequestData.UserName == "IGGGAMES") { _logger.Information("an IGG player just tried joining after passing master auth"); return true; @@ -300,7 +317,7 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBuffer additionalDat int sortIndex = GetNextSortIndex(); byte connectionId = GetNextConnectionId(); - var player = new Player( + player = new Player( endPoint, this, connectionId, @@ -312,39 +329,43 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBuffer additionalDat { SortIndex = sortIndex }; - if (_configuration.ServerName == string.Empty) - { - _logger.Information("About to update servers name" + _configuration.ServerName); - _configuration.ServerName = player.UserName + "'s server"; - InstanceConfigUpdated(); - _logger.Information("Updated servers name to: " + _configuration.ServerName); - } if (!_playerRegistry.AddPlayer(player)) { ReleaseSortIndex(player.SortIndex); ReleaseConnectionId(player.ConnectionId); return true; } - _logger.Information( - "Player joined dedicated server " + - $"(RemoteEndPoint='{player.Endpoint}', " + - $"ConnectionId={player.ConnectionId}, " + - $"Secret='{player.Secret}', " + - $"UserId='{player.UserId}', " + - $"UserName='{player.UserName}', " + - $"SortIndex={player.SortIndex})." - ); + } - if (_waitForPlayerCts != null) - _waitForPlayerCts.Cancel(); + if (_configuration.ServerName == string.Empty) + { + _logger.Information("About to update servers name" + _configuration.ServerName); + _configuration.ServerName = player.UserName + "'s server"; + InstanceConfigUpdated(); + _logger.Information("Updated servers name to: " + _configuration.ServerName); } + _logger.Information( + "Player joined dedicated server " + + $"(RemoteEndPoint='{player.Endpoint}', " + + $"ConnectionId={player.ConnectionId}, " + + $"Secret='{player.Secret}', " + + $"UserId='{player.UserId}', " + + $"UserName='{player.UserName}', " + + $"SortIndex={player.SortIndex})." + ); + + if (_waitForPlayerCts != null) + _waitForPlayerCts.Cancel(); - // Retrieve encryption params from handshake process by player session token, if provided + // Retrieve encryption params and platform data from handshake process by player session token, if provided if (!string.IsNullOrEmpty(connectionRequestData.PlayerSessionId)) { var handshakeSession = _handshakeSessionRegistry.TryGetByPlayerSessionId(connectionRequestData.PlayerSessionId); - + _handshakeSessionRegistry.RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out var ClientVer, out var Platform, out var PlayerPlatformUserId); + player.ClientVersion = ClientVer; + player.Platform = (Platform)Platform; + player.PlatformUserId = PlayerPlatformUserId; if (handshakeSession != null && handshakeSession.EncryptionParameters != null) { _packetEncryptionLayer.AddEncryptedEndPoint((IPEndPoint)endPoint, @@ -353,149 +374,177 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBuffer additionalDat } return false; - } - +} public override void OnLatencyUpdate(EndPoint endPoint, int latency) => _logger.Verbose($"Latency updated (RemoteEndPoint='{endPoint}', Latency={0.001f * latency})."); - object ConnectionLock = new(); - public override void OnConnect(EndPoint endPoint) + SemaphoreSlim ConnectDisconnectSemaphore = new SemaphoreSlim(1); + + public override async void OnConnect(EndPoint endPoint) { - lock (ConnectionLock) + await ConnectDisconnectSemaphore.WaitAsync(); + _logger.Information($"Endpoint connected (RemoteEndPoint='{endPoint}')"); + + if (!_playerRegistry.TryGetPlayer(endPoint, out var player)) { - _logger.Information($"Endpoint connected (RemoteEndPoint='{endPoint}')"); + _logger.Warning( + "Failed to retrieve player " + + $"(RemoteEndPoint='{endPoint}')." + ); + Disconnect(endPoint); + return; + } + //Send new player their sort order and other data + _packetDispatcher.SendToPlayer(player, new INetSerializable[] + { + new SyncTimePacket + { + SyncTime = RunTime + }, + new PlayerSortOrderPacket + { + UserId = player.UserId, + SortIndex = player.SortIndex + }, + new PlayerConnectedPacket + { + RemoteConnectionId = 0, + UserId = _configuration.ServerId, + UserName = _configuration.ServerName, + IsConnectionOwner = true + }, + new SetIsStartButtonEnabledPacket// Disables start button if they are server owner without selected song + { + Reason = player.UserId == _configuration.ServerOwnerId ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None + } + } + ,DeliveryMethod.ReliableOrdered); - if (!_playerRegistry.TryGetPlayer(endPoint, out var player)) + //Sends to all players that they have connected + _packetDispatcher.SendExcludingPlayer(player, new INetSerializable[] + { + new SyncTimePacket { - _logger.Warning( - "Failed to retrieve player " + - $"(RemoteEndPoint='{endPoint}')." - ); - Disconnect(endPoint); - return; - } + SyncTime = RunTime + }, + new PlayerConnectedPacket + { + RemoteConnectionId = player.ConnectionId, + UserId = player.UserId, + UserName = player.UserName, + IsConnectionOwner = false + }, + new PlayerSortOrderPacket + { + UserId = player.UserId, + SortIndex = player.SortIndex + }, + } + , DeliveryMethod.ReliableOrdered); - //Send to existing players that a new player has joined - _packetDispatcher.SendExcludingPlayer(player, new INetSerializable[] - { - new SyncTimePacket - { - SyncTime = RunTime - }, - new PlayerConnectedPacket + foreach (IPlayer p in _playerRegistry.Players) + { + if (p.ConnectionId != player.ConnectionId) + { + // Send all player connection data packets to new player + _packetDispatcher.SendToPlayer(player,new INetSerializable[]{ + new PlayerConnectedPacket { - RemoteConnectionId = player.ConnectionId, - UserId = player.UserId, - UserName = player.UserName, + RemoteConnectionId = p.ConnectionId, + UserId = p.UserId, + UserName = p.UserName, IsConnectionOwner = false }, - new PlayerSortOrderPacket + new PlayerSortOrderPacket { - UserId = player.UserId, - SortIndex = player.SortIndex + UserId = p.UserId, + SortIndex = p.SortIndex } - } - ,DeliveryMethod.ReliableOrdered); + }, DeliveryMethod.ReliableOrdered); - //Send new player their sort order and other data - _packetDispatcher.SendToPlayer(player, new INetSerializable[] + // Send all player identity packets to new player + _packetDispatcher.SendFromPlayerToPlayer(p, player, new INetSerializable[] { - new SyncTimePacket - { - SyncTime = RunTime - }, - new PlayerSortOrderPacket - { - UserId = player.UserId, - SortIndex = player.SortIndex - }, - new PlayerConnectedPacket + new PlayerIdentityPacket { - RemoteConnectionId = 0, - UserId = _configuration.ServerId, - UserName = _configuration.ServerName, - IsConnectionOwner = true + PlayerState = p.State, + PlayerAvatar = p.Avatar, + Random = new ByteArray { Data = p.Random }, + PublicEncryptionKey = new ByteArray { Data = p.PublicEncryptionKey } }, - new SetIsStartButtonEnabledPacket// Disables start button if they are server owner without selected song + new MpPlayerData { - Reason = player.UserId == _configuration.ServerOwnerId ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None + PlatformID = p.PlatformUserId!, + Platform = (byte)p.Platform, + ClientVersion = p.ClientVersion! } - } - ,DeliveryMethod.ReliableOrdered); + },DeliveryMethod.ReliableOrdered); + + } + } + ConnectDisconnectSemaphore.Release(); - foreach (IPlayer p in _playerRegistry.Players) + foreach (IPlayer p in _playerRegistry.Players) + { + if (p.ConnectionId != player.ConnectionId) { - if (p.ConnectionId != player.ConnectionId) + _packetDispatcher.SendFromPlayerToPlayer(player, p, new MpPlayerData { - // Send all player connection data packets to new player - _packetDispatcher.SendToPlayer(player,new INetSerializable[]{ - new PlayerConnectedPacket - { - RemoteConnectionId = p.ConnectionId, - UserId = p.UserId, - UserName = p.UserName, - IsConnectionOwner = false - }, - new PlayerSortOrderPacket - { - UserId = p.UserId, - SortIndex = p.SortIndex - } - }, DeliveryMethod.ReliableOrdered); - - // Send all player identity packets to new player - _packetDispatcher.SendFromPlayerToPlayer(p, player, new PlayerIdentityPacket - { - PlayerState = p.State, - PlayerAvatar = p.Avatar, - Random = new ByteArray { Data = p.Random }, - PublicEncryptionKey = new ByteArray { Data = p.PublicEncryptionKey } - }, DeliveryMethod.ReliableOrdered); - } + PlatformID = player.PlatformUserId!, + Platform = (byte)player.Platform, + ClientVersion = player.ClientVersion! + }, DeliveryMethod.ReliableOrdered); } + } + + // Update permissions - constant manager possibly does not work + if ((_configuration.SetConstantManagerFromUserId == player.UserId || _playerRegistry.GetPlayerCount() == 1) && _configuration.GameplayServerMode == GameplayServerMode.Managed) + { + _configuration.ServerOwnerId = player.UserId; + } - // Update permissions - constant manager possibly does not work - if ((_configuration.SetConstantManagerFromUserId == player.UserId || _playerRegistry.GetPlayerCount() == 1) && _configuration.GameplayServerMode == GameplayServerMode.Managed) + _packetDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket + { + PermissionConfiguration = new PlayersPermissionConfiguration { - _configuration.ServerOwnerId = player.UserId; + PlayersPermission = _playerRegistry.Players.Select(x => new PlayerPermissionConfiguration + { + UserId = x.UserId, + IsServerOwner = x.IsServerOwner, + HasRecommendBeatmapsPermission = x.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = x.CanRecommendModifiers, + HasKickVotePermission = x.CanKickVote, + HasInvitePermission = x.CanInvite + }).ToArray() } + }, DeliveryMethod.ReliableOrdered); + PlayerConnectedEvent?.Invoke(player); - _packetDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket + if((_playerRegistry.GetPlayerCount() == 6 || _playerRegistry.GetPlayerCount() == 10) && _playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var serverOwner)) + { + _packetDispatcher.SendToPlayer(serverOwner, new MpcTextChatPacket() { - PermissionConfiguration = new PlayersPermissionConfiguration - { - PlayersPermission = _playerRegistry.Players.Select(x => new PlayerPermissionConfiguration - { - UserId = x.UserId, - IsServerOwner = x.IsServerOwner, - HasRecommendBeatmapsPermission = x.CanRecommendBeatmaps, - HasRecommendGameplayModifiersPermission = x.CanRecommendModifiers, - HasKickVotePermission = x.CanKickVote, - HasInvitePermission = x.CanInvite - }).ToArray() - } - }, DeliveryMethod.ReliableOrdered); - PlayerConnectedEvent?.Invoke(player); + Text = "Do players seem to lag during gameplay? Disable beatmap notes by typing '/n false' or '/n f', Type '/h n' For more info on the command" + },DeliveryMethod.ReliableOrdered); } - + _packetDispatcher.SendToNearbyPlayers(new MpcTextChatPacket() + { + Text = "Player joined: " + player.UserName + " They are using: " + player.Platform.ToString() + " And game version: " + player.ClientVersion + }, DeliveryMethod.ReliableOrdered); } - object DisconnectplayerLock = new(); public void DisconnectPlayer(string UserId) { - lock (DisconnectplayerLock) - { - if(_playerRegistry.TryGetPlayer(UserId, out var player)) - _packetDispatcher.SendToPlayer(player, new KickPlayerPacket - { - DisconnectedReason = DisconnectedReason.Kicked - }, DeliveryMethod.ReliableOrdered); - } + + if(_playerRegistry.TryGetPlayer(UserId, out var player)) + _packetDispatcher.SendToPlayer(player, new KickPlayerPacket + { + DisconnectedReason = DisconnectedReason.Kicked + }, DeliveryMethod.ReliableOrdered); } - object DisconnectLock = new(); - public override void OnDisconnect(EndPoint endPoint, DisconnectReason reason) + public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reason) { _logger.Information( "Endpoint disconnected " + @@ -509,80 +558,74 @@ public override void OnDisconnect(EndPoint endPoint, DisconnectReason reason) ); return; } - - // Disconnect player - lock (DisconnectLock) + await ConnectDisconnectSemaphore.WaitAsync(); + if (_playerRegistry.TryGetPlayer(endPoint, out var player)) { - if (_playerRegistry.TryGetPlayer(endPoint, out var player)) + //Sends to all players that they have disconnected + _packetDispatcher.SendFromPlayer(player, new PlayerDisconnectedPacket { - _packetDispatcher.SendFromPlayer(player, new PlayerDisconnectedPacket - { - DisconnectedReason = DisconnectedReason.ClientConnectionClosed - }, DeliveryMethod.ReliableOrdered); - - if (_configuration.ServerOwnerId == player.UserId) - _configuration.ServerOwnerId = ""; + DisconnectedReason = DisconnectedReason.ClientConnectionClosed + }, DeliveryMethod.ReliableOrdered); + + if (_configuration.ServerOwnerId == player.UserId) + _configuration.ServerOwnerId = ""; - _playerRegistry.RemovePlayer(player); - ReleaseSortIndex(player.SortIndex); - ReleaseConnectionId(player.ConnectionId); + _playerRegistry.RemovePlayer(player); + ReleaseSortIndex(player.SortIndex); + ReleaseConnectionId(player.ConnectionId); - PlayerDisconnectedEvent?.Invoke(player); - } + PlayerDisconnectedEvent?.Invoke(player); + } + if (_playerRegistry.GetPlayerCount() != 0 && string.IsNullOrEmpty(_configuration.ServerOwnerId) && _configuration.GameplayServerMode == GameplayServerMode.Managed) + { + var serverOwner = _playerRegistry.Players[0]; + _configuration.ServerOwnerId = serverOwner.UserId; - if (_playerRegistry.GetPlayerCount() == 0) + // Update permissions + _packetDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket { - NoPlayersTime = RunTime; - if (_configuration.DestroyInstanceTimeout != -1) + PermissionConfiguration = new PlayersPermissionConfiguration { - _waitForPlayerCts = new CancellationTokenSource(); - _ = Task.Delay((int)(_configuration.DestroyInstanceTimeout * 1000), _waitForPlayerCts.Token).ContinueWith(t => + PlayersPermission = _playerRegistry.Players.Select(x => new PlayerPermissionConfiguration { - if (!t.IsCanceled && _playerRegistry.GetPlayerCount() == 0) - { - _logger.Information("No players joined within the closing timeout, stopping lobby now"); - _ = Stop(CancellationToken.None); - } - else - { - _waitForPlayerCts = null; - } - }); + UserId = x.UserId, + IsServerOwner = x.IsServerOwner, + HasRecommendBeatmapsPermission = x.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = x.CanRecommendModifiers, + HasKickVotePermission = x.CanKickVote, + HasInvitePermission = x.CanInvite + }).ToArray() } - } - else + }, DeliveryMethod.ReliableOrdered); + + // Disable start button if they are server owner without selected song + if (serverOwner.BeatmapIdentifier == null) + _packetDispatcher.SendToPlayer(serverOwner, new SetIsStartButtonEnabledPacket + { + Reason = CannotStartGameReason.NoSongSelected + }, DeliveryMethod.ReliableOrdered); + } + ConnectDisconnectSemaphore.Release(); + + if (_playerRegistry.GetPlayerCount() == 0) + { + NoPlayersTime = RunTime; + if (_configuration.DestroyInstanceTimeout != -1) { - // Set new server owner if server owner left - if (_configuration.ServerOwnerId == "" && _configuration.GameplayServerMode == GameplayServerMode.Managed) + _waitForPlayerCts = new CancellationTokenSource(); + _ = Task.Delay((int)(_configuration.DestroyInstanceTimeout * 1000), _waitForPlayerCts.Token).ContinueWith(t => { - _configuration.ServerOwnerId = _playerRegistry.Players[0].UserId; - var serverOwner = _playerRegistry.GetPlayer(_configuration.ServerOwnerId); - - // Disable start button if they are server owner without selected song - if (serverOwner.BeatmapIdentifier == null) - _packetDispatcher.SendToPlayer(serverOwner, new SetIsStartButtonEnabledPacket - { - Reason = CannotStartGameReason.NoSongSelected - }, DeliveryMethod.ReliableOrdered); - - // Update permissions - _packetDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket + if (!t.IsCanceled && _playerRegistry.GetPlayerCount() == 0) { - PermissionConfiguration = new PlayersPermissionConfiguration - { - PlayersPermission = _playerRegistry.Players.Select(x => new PlayerPermissionConfiguration - { - UserId = x.UserId, - IsServerOwner = x.IsServerOwner, - HasRecommendBeatmapsPermission = x.CanRecommendBeatmaps, - HasRecommendGameplayModifiersPermission = x.CanRecommendModifiers, - HasKickVotePermission = x.CanKickVote, - HasInvitePermission = x.CanInvite - }).ToArray() - } - }, DeliveryMethod.ReliableOrdered); - } + _logger.Information("No players joined within the closing timeout, stopping lobby now"); + _ = Stop(CancellationToken.None); + } + else + { + _waitForPlayerCts = null; + } + }); } } } @@ -592,22 +635,24 @@ public override void OnDisconnect(EndPoint endPoint, DisconnectReason reason) private async void SendSyncTime(CancellationToken cancellationToken) { - foreach (IPlayer player in _playerRegistry.Players) + while (!cancellationToken.IsCancellationRequested) { - _packetDispatcher.SendToPlayer(player, new SyncTimePacket() + foreach (IPlayer player in _playerRegistry.Players) { - SyncTime = player.SyncTime - }, DeliveryMethod.ReliableOrdered); - } - try - { - await Task.Delay(SyncTimeDelay, cancellationToken); - } - catch (TaskCanceledException) - { - return; + _packetDispatcher.SendToPlayer(player, new SyncTimePacket() + { + SyncTime = player.SyncTime + }, DeliveryMethod.ReliableOrdered); + } + try + { + await Task.Delay(SyncTimeDelay, cancellationToken); + } + catch (TaskCanceledException) + { + return; + } } - SendSyncTime(cancellationToken); } public void InstanceConfigUpdated() diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/Abstractions/IEncryptedPacketWriter.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/Abstractions/IEncryptedPacketWriter.cs index d441431d..ac0b9208 100644 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/Abstractions/IEncryptedPacketWriter.cs +++ b/BeatTogether.DedicatedServer.Kernel/Encryption/Abstractions/IEncryptedPacketWriter.cs @@ -1,6 +1,5 @@ using System; using System.Security.Cryptography; -using BinaryRecords; using Krypton.Buffers; namespace BeatTogether.DedicatedServer.Kernel.Encryption.Abstractions diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs index 8963e66c..41ee1ffc 100644 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs +++ b/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs @@ -1,6 +1,7 @@ using System; using System.Security.Cryptography; using BeatTogether.DedicatedServer.Kernel.Encryption.Abstractions; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; namespace BeatTogether.DedicatedServer.Kernel.Encryption @@ -14,18 +15,15 @@ public EncryptedPacketWriter( { _rngCryptoServiceProvider = rngCryptoServiceProvider; } - public void WriteTo(ref SpanBufferWriter bufferWriter, ReadOnlySpan data, uint sequenceId, byte[] key, HMAC hmac) { - var unencryptedBufferWriter = new SpanBufferWriter(stackalloc byte[data.Length]); + var unencryptedBufferWriter = new SpanBuffer(stackalloc byte[data.Length + 128 + 10], false); unencryptedBufferWriter.WriteBytes(data); - - var hashBufferWriter = new SpanBufferWriter(stackalloc byte[data.Length + 4]); - hashBufferWriter.WriteBytes(data); - hashBufferWriter.WriteUInt32(sequenceId); + unencryptedBufferWriter.WriteUInt32(sequenceId); Span hash = stackalloc byte[32]; - if (!hmac.TryComputeHash(hashBufferWriter.Data, hash, out _)) + if (!hmac.TryComputeHash(unencryptedBufferWriter.Data, hash, out _)) throw new Exception("Failed to compute message hash."); + unencryptedBufferWriter.SetOffset(data.Length); unencryptedBufferWriter.WriteBytes(hash.Slice(0, 10)); var iv = new byte[16]; diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs index cdee445a..d2ec3db8 100644 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs @@ -262,19 +262,17 @@ public void ProcessOutBoundPacket(EndPoint endPoint, ref Memory data) } } - var bufferWriter = new SpanBufferWriter(stackalloc byte[(int)((data.Length + 1)* 1.8)]); //Kinda just estimating the size the packet will be after encryption, to avoid having the span buffer get resized + var bufferWriter = new SpanBufferWriter(stackalloc byte[data.Length + 256], false); if (encryptionParameters != null) { bufferWriter.WriteBool(true); // isEncrypted - using (var hmac = new HMACSHA256(encryptionParameters.SendMac)) - { - _encryptedPacketWriter.WriteTo( - ref bufferWriter, data.Span, - encryptionParameters.GetNextSequenceId(), - encryptionParameters.SendKey, hmac); - } + using var hmac = new HMACSHA256(encryptionParameters.SendMac); + _encryptedPacketWriter.WriteTo( + ref bufferWriter, data.Span, + encryptionParameters.GetNextSequenceId(), + encryptionParameters.SendKey, hmac); } else { diff --git a/BeatTogether.DedicatedServer.Kernel/Enums/Platform.cs b/BeatTogether.DedicatedServer.Kernel/Enums/Platform.cs new file mode 100644 index 00000000..f5fc4aa3 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Enums/Platform.cs @@ -0,0 +1,14 @@ +namespace BeatTogether.DedicatedServer.Kernel.Enums +{ + public enum Platform : byte + { + Test, + OculusRift, + OculusQuest, + Steam, + PS4, + PS4Dev, + PS4Cert, + Oculus = 1 + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeSessionRegistry.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeSessionRegistry.cs index 86bc01ae..f9550772 100644 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeSessionRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeSessionRegistry.cs @@ -1,4 +1,5 @@ using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net; using BeatTogether.DedicatedServer.Kernel.Abstractions; @@ -10,6 +11,7 @@ public class HandshakeSessionRegistry : IHandshakeSessionRegistry { private readonly ConcurrentDictionary _sessions; private readonly ConcurrentDictionary _pendingPlayerSessionIds; + private readonly ConcurrentDictionary _pendingPlayerSessionData; private readonly ILogger _logger; @@ -17,6 +19,7 @@ public HandshakeSessionRegistry() { _sessions = new(); _pendingPlayerSessionIds = new(); + _pendingPlayerSessionData = new(); _logger = Log.ForContext(); } @@ -37,6 +40,24 @@ public void AddPendingPlayerSessionId(string playerSessionId) { _pendingPlayerSessionIds[playerSessionId] = true; } + public void AddExtraPlayerSessionData(string playerSessionId, string ClientVersion, byte PlatformId, string PlayerPlatformUserId) + { + _pendingPlayerSessionData[playerSessionId] = (ClientVersion, PlatformId, PlayerPlatformUserId); + } + + public void RemoveExtraPlayerSessionData(string playerSessionId, out string ClientVersion, out byte Platform, out string PlayerPlatformUserId) + { + if(_pendingPlayerSessionData.TryRemove(playerSessionId, out var Values)) + { + ClientVersion = Values.Item1; + Platform = Values.Item2; + PlayerPlatformUserId = Values.Item3; + return; + } + ClientVersion = "ERROR"; + Platform = 0; + PlayerPlatformUserId = "ERROR"; + } public bool TryRemovePendingPlayerSessionId(string playerSessionId) { diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index d2bbf2ad..54ea86f8 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -423,7 +423,10 @@ private GameplayModifiers GetSelectedModifiers() { switch(_configuration.SongSelectionMode) { - case SongSelectionMode.ServerOwnerPicks: return _playerRegistry.GetPlayer(_configuration.ServerOwnerId).Modifiers; + case SongSelectionMode.ServerOwnerPicks: + if(_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var ServerOwner)) + return ServerOwner.Modifiers; + return EmptyModifiers; case SongSelectionMode.Vote: GameplayModifiers gameplayModifiers = new(); Dictionary voteDictionary = new(); @@ -458,7 +461,9 @@ private GameplayModifiers GetSelectedModifiers() }; return Modifiers; } - gameplayModifiers = _playerRegistry.GetPlayer(RandomlyPickedPlayer).Modifiers; + gameplayModifiers = new(); + if (_playerRegistry.TryGetPlayer(RandomlyPickedPlayer, out var Randomplayer)) + gameplayModifiers = Randomplayer.Modifiers; if (_configuration.ApplyNoFailModifier) gameplayModifiers.NoFailOn0Energy = true; return gameplayModifiers; diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index f4969458..2fee28bd 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -1,6 +1,4 @@ using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Messaging.Enums; -using BeatTogether.DedicatedServer.Messaging.Registries; using BeatTogether.Extensions; using BeatTogether.LiteNetLib; using BeatTogether.LiteNetLib.Abstractions; @@ -9,7 +7,6 @@ using BeatTogether.LiteNetLib.Enums; using BeatTogether.LiteNetLib.Util; using Serilog; -using System; using System.Net; namespace BeatTogether.DedicatedServer.Kernel diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs new file mode 100644 index 00000000..5d7c348f --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs @@ -0,0 +1,35 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; +using BeatTogether.LiteNetLib.Enums; +using System.Threading.Tasks; + +namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc +{ + class GetMpPlayerDataPacketHandler : BasePacketHandler + { + private readonly IPacketDispatcher _PacketDispatcher; + private readonly IPlayerRegistry _PlayerRegistry; + + public GetMpPlayerDataPacketHandler( + IPacketDispatcher packetDispatcher, + IPlayerRegistry playerRegistry) + { + _PacketDispatcher = packetDispatcher; + _PlayerRegistry = playerRegistry; + } + + public override Task Handle(IPlayer sender, MpPlayerData packet) + { + + foreach (var Player in _PlayerRegistry.Players) + { + _PacketDispatcher.SendFromPlayerToPlayer(Player, sender, new MpPlayerData() + { + Platform = (byte)Player.Platform, + ClientVersion = Player.ClientVersion + }, DeliveryMethod.ReliableOrdered); + } + return Task.CompletedTask; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index e3f4944d..2364d01b 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -122,7 +122,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D } if(packet is NoteSpawnPacket || packet is ObstacleSpawnPacket || packet is SliderSpawnPacket) //Note packet logic { - if (_configuration.DisableNotes || _playerRegistry.GetPlayerCount() > 15) + if (_configuration.DisableNotes || (_playerRegistry.GetPlayerCount() > 15 ) && !_configuration.ForceEnableNotes) return; method = DeliveryMethod.Unreliable; break; diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index 106612f3..f1ebc678 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -28,6 +28,9 @@ public sealed class Player : IPlayer public int SortIndex { get; set; } public byte[]? Random { get; set; } public byte[]? PublicEncryptionKey { get; set; } + public string ClientVersion { get; set; } = "Pre-1.29"; + public Platform Platform { get; set; } = Platform.Test; //Unknown + public string PlatformUserId { get; set; } = ""; public object PlayerIdentityLock { get; set; } = new(); public AvatarData Avatar { get; set; } = new(); public object ReadyLock { get; set; } = new(); @@ -58,7 +61,6 @@ public sealed class Player : IPlayer public bool IsActive => State.Contains("is_active"); public bool FinishedLevel => State.Contains("finished_level"); public bool InMenu => State.Contains("in_menu"); - public bool IsModded => State.Contains("modded"); private const float _syncTimeOffset = 0.06f; private ConcurrentDictionary _entitlements = new(); diff --git a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs index cd4a819e..3b2efec7 100644 --- a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net; @@ -10,48 +10,68 @@ public sealed class PlayerRegistry : IPlayerRegistry { public IPlayer[] Players { get => _playersByUserId.Values.ToArray(); } - private readonly ConcurrentDictionary _playersByRemoteEndPoint = new(); - private readonly ConcurrentDictionary _playersByConnectionId = new(); - private readonly ConcurrentDictionary _playersByUserId = new(); + private object PlayerDictionaries_Lock = new(); + private readonly Dictionary _playersByRemoteEndPoint = new(); + private readonly Dictionary _playersByConnectionId = new(); + private readonly Dictionary _playersByUserId = new(); + + private int _PlayerCount = 0; public int GetPlayerCount() { - return _playersByUserId.Count; + lock(PlayerDictionaries_Lock) + { + return _PlayerCount; + } } public bool AddPlayer(IPlayer player) { - if(_playersByUserId.TryAdd(player.UserId, player)) + lock (PlayerDictionaries_Lock) { - _playersByRemoteEndPoint.TryAdd(player.Endpoint, player); - _playersByConnectionId.TryAdd(player.ConnectionId, player); - return true; + if (_playersByUserId.TryAdd(player.UserId, player)) + { + _playersByRemoteEndPoint.TryAdd(player.Endpoint, player); + _playersByConnectionId.TryAdd(player.ConnectionId, player); + _PlayerCount++; + return true; + } } return false; } public void RemovePlayer(IPlayer player) { - _playersByRemoteEndPoint.TryRemove(player.Endpoint, out _); - _playersByUserId.TryRemove(player.UserId, out _); - _playersByConnectionId.TryRemove(player.ConnectionId, out _); + lock (PlayerDictionaries_Lock) + { + if (_playersByUserId.Remove(player.UserId, out _)) + { + _playersByRemoteEndPoint.Remove(player.Endpoint, out _); + _playersByConnectionId.Remove(player.ConnectionId, out _); + _PlayerCount--; + } + } } - public IPlayer GetPlayer(EndPoint remoteEndPoint) => - _playersByRemoteEndPoint[remoteEndPoint]; - - public IPlayer GetPlayer(byte connectionId) => - _playersByConnectionId[connectionId]; - - public IPlayer GetPlayer(string userId) => - _playersByUserId[userId]; - - public bool TryGetPlayer(EndPoint remoteEndPoint, [MaybeNullWhen(false)] out IPlayer player) => - _playersByRemoteEndPoint.TryGetValue(remoteEndPoint, out player); - - public bool TryGetPlayer(byte connectionId, [MaybeNullWhen(false)] out IPlayer player) => - _playersByConnectionId.TryGetValue(connectionId, out player); - - public bool TryGetPlayer(string userId, [MaybeNullWhen(false)] out IPlayer player) => - _playersByUserId.TryGetValue(userId, out player); + public bool TryGetPlayer(EndPoint remoteEndPoint, [MaybeNullWhen(false)] out IPlayer player) + { + lock (PlayerDictionaries_Lock) + { + return _playersByRemoteEndPoint.TryGetValue(remoteEndPoint, out player); + } + } + public bool TryGetPlayer(byte connectionId, [MaybeNullWhen(false)] out IPlayer player) + { + lock (PlayerDictionaries_Lock) + { + return _playersByConnectionId.TryGetValue(connectionId, out player); + } + } + public bool TryGetPlayer(string userId, [MaybeNullWhen(false)] out IPlayer player) + { + lock (PlayerDictionaries_Lock) + { + return _playersByUserId.TryGetValue(userId, out player); + } + } } } diff --git a/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs b/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs index 8f2b2115..59e43aab 100644 --- a/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs +++ b/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs @@ -95,12 +95,12 @@ private void RegisterCommands() { RegisterCommand(AccessLevel.Player); - RegisterCommand(AccessLevel.Manager); - RegisterCommand(AccessLevel.Manager); - RegisterCommand(AccessLevel.Manager); - RegisterCommand(AccessLevel.Manager); - RegisterCommand(AccessLevel.Manager); - RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); RegisterCommand(AccessLevel.Manager); RegisterCommand(AccessLevel.Manager); RegisterCommand(AccessLevel.Manager); diff --git a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj index 4e4b8d33..d091e539 100644 --- a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj +++ b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj @@ -9,7 +9,7 @@ - + diff --git a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs index 9cf6483f..7e6ebc54 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs @@ -1,6 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Util; -using Krypton.Buffers; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs index 3759fe83..dd2a45ed 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs @@ -2,6 +2,7 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; using BeatTogether.LiteNetLib.Util; +using BinaryRecords.Exceptions; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -35,7 +36,7 @@ public void ReadFrom(ref SpanBuffer reader) IsConnectionOwner = reader.ReadBool(); PlayerSessionId = reader.ReadString(); } - catch (Exception ex) { } + catch (EndOfBufferException) { } if (PlayerSessionId != null && PlayerSessionId.StartsWith(SessionIdPrefix)) // Read OK, valid session identifier diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetMpPlayerData.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetMpPlayerData.cs new file mode 100644 index 00000000..03d709ca --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetMpPlayerData.cs @@ -0,0 +1,16 @@ +using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets +{ + public sealed class GetMpPlayerData : INetSerializable + { + public void ReadFrom(ref SpanBuffer bufferReader) + { + } + + public void WriteTo(ref SpanBuffer bufferWriter) + { + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPlayerData.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPlayerData.cs new file mode 100644 index 00000000..bb935e66 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPlayerData.cs @@ -0,0 +1,26 @@ +using BeatTogether.Extensions; +using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets +{ + public sealed class MpPlayerData : INetSerializable + { + public string PlatformID = string.Empty; + public byte Platform; + public string ClientVersion = string.Empty; + + public void WriteTo(ref SpanBuffer bufferWriter) + { + bufferWriter.WriteString(PlatformID); + bufferWriter.WriteUInt8(Platform); + bufferWriter.WriteString(ClientVersion); + } + public void ReadFrom(ref SpanBuffer bufferReader) + { + PlatformID = bufferReader.ReadString(); + Platform = bufferReader.ReadUInt8(); + ClientVersion = bufferReader.ReadString(); + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs index 731d1c83..cc1ee3e5 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs @@ -17,6 +17,8 @@ public override void Register() AddPacket(); AddPacket(); AddPacket(); + AddPacket(); + AddPacket(); } public bool TryCreatePacket(string packetId, [MaybeNullWhen(false)] out INetSerializable packet) diff --git a/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj b/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj index 947d96f1..187f3457 100644 --- a/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj +++ b/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj @@ -13,7 +13,7 @@ - + diff --git a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs index 2cea0444..6fc49ec6 100644 --- a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs +++ b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs @@ -70,6 +70,9 @@ private Task HandlePlayerConnectedToMatchmaking(PlayerConnectedToMatchmakingServ var publicKey = @event.PublicKey; var playerSessionId = @event.PlayerSessionId; var serverSecret = @event.Secret; + var PlayerClientVersion = @event.ClientVersion; + var PlayerPlatform = @event.Platform; + var PlayerPlatformUserId = @event.PlatformUserId; // Clients connecting via Graph API will connect directly to us to negotiate encryption parameters var hasEncryptionParams = random != null && publicKey != null && random.Length > 0 && publicKey.Length > 0; @@ -91,10 +94,11 @@ private Task HandlePlayerConnectedToMatchmaking(PlayerConnectedToMatchmakingServ $"(RemoteEndPoint='{remoteEndPoint}', " + $"PlayerSessionId='{playerSessionId}')." ); - - TryGetDedicatedInstance(serverSecret)? - .GetHandshakeSessionRegistry() - .AddPendingPlayerSessionId(playerSessionId); + + var HandshakeRegistry = TryGetDedicatedInstance(serverSecret)? + .GetHandshakeSessionRegistry(); + HandshakeRegistry?.AddPendingPlayerSessionId(playerSessionId); + HandshakeRegistry?.AddExtraPlayerSessionData(playerSessionId, PlayerClientVersion, PlayerPlatform, PlayerPlatformUserId); } _autobus.Publish(new NodeReceivedPlayerEncryptionEvent(_configuration.HostName, @event.RemoteEndPoint)); From 9c9c5da61839f3e48660cc9d12be3a19c9047260 Mon Sep 17 00:00:00 2001 From: cubic Date: Wed, 10 May 2023 20:27:16 +0100 Subject: [PATCH 008/120] Bump node ver --- .../BeatTogether.DedicatedServer.Node.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj b/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj index 187f3457..baac3102 100644 --- a/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj +++ b/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj @@ -7,7 +7,7 @@ BeatTogether Team BeatTogether https://github.com/beattogether/BeatTogether.DedicatedServer - 1.1.0 + 1.1.1 enable From fb059d30c3f784687d035cccbaad281b94e98cd0 Mon Sep 17 00:00:00 2001 From: cubic Date: Wed, 10 May 2023 21:23:12 +0100 Subject: [PATCH 009/120] Bumped lnl dependency --- .../BeatTogether.DedicatedServer.Messaging.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj index d091e539..05bbd13a 100644 --- a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj +++ b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj @@ -9,7 +9,7 @@ - + From 9c7cf4d05be64fcfd8b8a8e127f74eb04fdebd49 Mon Sep 17 00:00:00 2001 From: cubic Date: Thu, 11 May 2023 17:58:34 +0100 Subject: [PATCH 010/120] Server now sends less movement packets the more players there are in the lobby in bigger lobbies, movement is paused when players join to give the server time to send packets to all the clients --- .../Abstractions/IPlayer.cs | 2 + .../Abstractions/IPlayerRegistry.cs | 5 +- .../DedicatedInstance.cs | 84 ++++++++++++------- .../PacketSource.cs | 25 +++++- BeatTogether.DedicatedServer.Kernel/Player.cs | 4 + .../PlayerRegistry.cs | 36 ++++++++ 6 files changed, 121 insertions(+), 35 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index bfc30904..c30496e2 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -71,5 +71,7 @@ public interface IPlayer public bool MappingExtensions { get; set; } public BeatmapDifficulty[] BeatmapDifficulties { get; set; } void ResetRecommendedMapRequirements(); + long TicksAtLastSyncStateDelta { get; set; } + long TicksAtLastSyncState { get; set; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs index bf43f7fc..35b46fac 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs @@ -6,12 +6,15 @@ namespace BeatTogether.DedicatedServer.Kernel.Abstractions public interface IPlayerRegistry { IPlayer[] Players { get; } - bool AddPlayer(IPlayer player); void RemovePlayer(IPlayer player); int GetPlayerCount(); bool TryGetPlayer(EndPoint remoteEndPoint, [MaybeNullWhen(false)] out IPlayer player); bool TryGetPlayer(byte connectionId, [MaybeNullWhen(false)] out IPlayer player); bool TryGetPlayer(string userId, [MaybeNullWhen(false)] out IPlayer player); + + bool ShouldPauseNodePoseSyncPackets(); + void SetShouldPauseSyncPackets(bool Joining); + int GetMillisBetweenSyncStatePackets(); } } diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index fa96d8da..b5f66542 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -81,7 +81,7 @@ public DedicatedInstance( liteNetConfiguration, registry, serviceProvider, - (configuration.MaxPlayerCount/5), + (configuration.MaxPlayerCount/20+1), packetLayer) { _configuration = configuration; @@ -394,7 +394,7 @@ public override async void OnConnect(EndPoint endPoint) Disconnect(endPoint); return; } - //Send new player their sort order and other data + //Send new player their sort order and server's data _packetDispatcher.SendToPlayer(player, new INetSerializable[] { new SyncTimePacket @@ -417,9 +417,8 @@ public override async void OnConnect(EndPoint endPoint) { Reason = player.UserId == _configuration.ServerOwnerId ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None } - } - ,DeliveryMethod.ReliableOrdered); - + },DeliveryMethod.ReliableOrdered); + _playerRegistry.SetShouldPauseSyncPackets(true); //Sends to all players that they have connected _packetDispatcher.SendExcludingPlayer(player, new INetSerializable[] { @@ -482,29 +481,12 @@ public override async void OnConnect(EndPoint endPoint) } } - ConnectDisconnectSemaphore.Release(); - - - foreach (IPlayer p in _playerRegistry.Players) - { - if (p.ConnectionId != player.ConnectionId) - { - _packetDispatcher.SendFromPlayerToPlayer(player, p, new MpPlayerData - { - PlatformID = player.PlatformUserId!, - Platform = (byte)player.Platform, - ClientVersion = player.ClientVersion! - }, DeliveryMethod.ReliableOrdered); - } - } - // Update permissions - constant manager possibly does not work if ((_configuration.SetConstantManagerFromUserId == player.UserId || _playerRegistry.GetPlayerCount() == 1) && _configuration.GameplayServerMode == GameplayServerMode.Managed) { _configuration.ServerOwnerId = player.UserId; } - - _packetDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket + _packetDispatcher.SendToPlayer(player, new SetPlayersPermissionConfigurationPacket { PermissionConfiguration = new PlayersPermissionConfiguration { @@ -519,6 +501,43 @@ public override async void OnConnect(EndPoint endPoint) }).ToArray() } }, DeliveryMethod.ReliableOrdered); + + _packetDispatcher.SendExcludingPlayer(player, new SetPlayersPermissionConfigurationPacket + { + PermissionConfiguration = new PlayersPermissionConfiguration + { + PlayersPermission = new PlayerPermissionConfiguration[] + { + new PlayerPermissionConfiguration() + { + UserId = player!.UserId, + IsServerOwner = player.IsServerOwner, + HasRecommendBeatmapsPermission = player.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = player.CanRecommendModifiers, + HasKickVotePermission = player.CanKickVote, + HasInvitePermission = player.CanInvite + } + } + } + }, DeliveryMethod.ReliableOrdered); + _playerRegistry.SetShouldPauseSyncPackets(false); + + ConnectDisconnectSemaphore.Release(); + + + foreach (IPlayer p in _playerRegistry.Players) + { + if (p.ConnectionId != player.ConnectionId) + { + _packetDispatcher.SendFromPlayerToPlayer(player, p, new MpPlayerData + { + PlatformID = player.PlatformUserId!, + Platform = (byte)player.Platform, + ClientVersion = player.ClientVersion! + }, DeliveryMethod.ReliableOrdered); + } + } + PlayerConnectedEvent?.Invoke(player); if((_playerRegistry.GetPlayerCount() == 6 || _playerRegistry.GetPlayerCount() == 10) && _playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var serverOwner)) @@ -587,15 +606,18 @@ public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reas { PermissionConfiguration = new PlayersPermissionConfiguration { - PlayersPermission = _playerRegistry.Players.Select(x => new PlayerPermissionConfiguration + PlayersPermission = new PlayerPermissionConfiguration[] { - UserId = x.UserId, - IsServerOwner = x.IsServerOwner, - HasRecommendBeatmapsPermission = x.CanRecommendBeatmaps, - HasRecommendGameplayModifiersPermission = x.CanRecommendModifiers, - HasKickVotePermission = x.CanKickVote, - HasInvitePermission = x.CanInvite - }).ToArray() + new PlayerPermissionConfiguration() + { + UserId = serverOwner!.UserId, + IsServerOwner = serverOwner.IsServerOwner, + HasRecommendBeatmapsPermission = serverOwner.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = serverOwner.CanRecommendModifiers, + HasKickVotePermission = serverOwner.CanKickVote, + HasInvitePermission = serverOwner.CanInvite + } + } } }, DeliveryMethod.ReliableOrdered); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index 2364d01b..6db05514 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -1,7 +1,10 @@ using System; +using System.Diagnostics; using System.Net; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Models; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; using BeatTogether.DedicatedServer.Messaging.Registries; using BeatTogether.Extensions; @@ -67,7 +70,6 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D return; } SpanBuffer HandleRead = new(reader.RemainingData.ToArray()); - while (HandleRead.RemainingSize > 0) @@ -111,7 +113,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D } break; } - + //TODO disable join message config packet if (packet == null) { // skip any unprocessed bytes @@ -122,11 +124,28 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D } if(packet is NoteSpawnPacket || packet is ObstacleSpawnPacket || packet is SliderSpawnPacket) //Note packet logic { - if (_configuration.DisableNotes || (_playerRegistry.GetPlayerCount() > 15 ) && !_configuration.ForceEnableNotes) + if (_configuration.DisableNotes || (_playerRegistry.GetPlayerCount() > 16) && !_configuration.ForceEnableNotes) return; method = DeliveryMethod.Unreliable; break; } + if (packet is NodePoseSyncStatePacket) + { + if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncState) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets() || _playerRegistry.ShouldPauseNodePoseSyncPackets()) + { + return; + } + method = DeliveryMethod.Unreliable; + sender.TicksAtLastSyncState = DateTime.UtcNow.Ticks; + } + if (packet is NodePoseSyncStateDeltaPacket) + { + if((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncStateDelta) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets() || _playerRegistry.ShouldPauseNodePoseSyncPackets()) + { + return; + } + sender.TicksAtLastSyncStateDelta = DateTime.UtcNow.Ticks; + } var packetType = packet.GetType(); var packetHandlerType = typeof(Abstractions.IPacketHandler<>) .MakeGenericType(packetType); diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index f1ebc678..d11f628c 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -122,5 +122,9 @@ public void ResetRecommendedMapRequirements() MappingExtensions = false; BeatmapDifficulties = Array.Empty(); } + + public long TicksAtLastSyncStateDelta { get; set; } = 0; //33ms gaps for 30/sec, 66ms gap for 15/sec + public long TicksAtLastSyncState { get; set; } = 0; + } } diff --git a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs index 3b2efec7..defd4134 100644 --- a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net; +using System.Runtime.CompilerServices; using BeatTogether.DedicatedServer.Kernel.Abstractions; namespace BeatTogether.DedicatedServer.Kernel @@ -33,6 +34,10 @@ public bool AddPlayer(IPlayer player) _playersByRemoteEndPoint.TryAdd(player.Endpoint, player); _playersByConnectionId.TryAdd(player.ConnectionId, player); _PlayerCount++; + lock (MillisBetweenSyncStatePackets_Lock) + { + MillisBetweenSyncStatePackets = (int)(0.84 * _PlayerCount + 15.789); + } return true; } } @@ -48,6 +53,10 @@ public void RemovePlayer(IPlayer player) _playersByRemoteEndPoint.Remove(player.Endpoint, out _); _playersByConnectionId.Remove(player.ConnectionId, out _); _PlayerCount--; + lock (MillisBetweenSyncStatePackets_Lock) + { + MillisBetweenSyncStatePackets = (int)(0.84 * _PlayerCount + 15.789); + } } } } @@ -73,5 +82,32 @@ public bool TryGetPlayer(string userId, [MaybeNullWhen(false)] out IPlayer playe return _playersByUserId.TryGetValue(userId, out player); } } + + private readonly object UnreliableRoutingHold_Lock = new(); + bool UnreliableRoutingHold = false; + public bool ShouldPauseNodePoseSyncPackets() + { + lock (UnreliableRoutingHold_Lock) + { + return UnreliableRoutingHold && GetPlayerCount() > 15; + } + } + public void SetShouldPauseSyncPackets(bool Joining) + { + lock (UnreliableRoutingHold_Lock) + { + UnreliableRoutingHold = Joining; + } + } + + private readonly object MillisBetweenSyncStatePackets_Lock = new(); + private int MillisBetweenSyncStatePackets = 0; + public int GetMillisBetweenSyncStatePackets() + { + lock (MillisBetweenSyncStatePackets_Lock) + { + return MillisBetweenSyncStatePackets; + } + } } } From 335fb807b48f0b51b58feb37e3e222fec6ce304a Mon Sep 17 00:00:00 2001 From: cubic Date: Fri, 12 May 2023 21:51:37 +0100 Subject: [PATCH 011/120] Added a packet to inform the client to change the rate of movement packets --- .../DedicatedInstance.cs | 17 ++++++++++++-- .../MpNodePoseSyncStatePacket.cs | 23 +++++++++++++++++++ .../MultiplayerCorePacketRegistry.cs | 1 + 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpNodePoseSyncStatePacket.cs diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index b5f66542..a9b92314 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -540,7 +540,14 @@ public override async void OnConnect(EndPoint endPoint) PlayerConnectedEvent?.Invoke(player); - if((_playerRegistry.GetPlayerCount() == 6 || _playerRegistry.GetPlayerCount() == 10) && _playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var serverOwner)) + + _packetDispatcher.SendToNearbyPlayers(new MpNodePoseSyncStatePacket + { + fullStateUpdateFrequency = 0.1f, + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f + }, DeliveryMethod.ReliableOrdered); + + if((_playerRegistry.GetPlayerCount() == 7 || _playerRegistry.GetPlayerCount() == 13) && _playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var serverOwner)) { _packetDispatcher.SendToPlayer(serverOwner, new MpcTextChatPacket() { @@ -549,7 +556,7 @@ public override async void OnConnect(EndPoint endPoint) } _packetDispatcher.SendToNearbyPlayers(new MpcTextChatPacket() { - Text = "Player joined: " + player.UserName + " They are using: " + player.Platform.ToString() + " And game version: " + player.ClientVersion + Text = "Player joined: " + player.UserName + " Platform: " + player.Platform.ToString() + " Game version: " + player.ClientVersion }, DeliveryMethod.ReliableOrdered); } @@ -630,6 +637,12 @@ public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reas } ConnectDisconnectSemaphore.Release(); + _packetDispatcher.SendToNearbyPlayers(new MpNodePoseSyncStatePacket + { + fullStateUpdateFrequency = 0.1f, + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f + }, DeliveryMethod.ReliableOrdered); + if (_playerRegistry.GetPlayerCount() == 0) { NoPlayersTime = RunTime; diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpNodePoseSyncStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpNodePoseSyncStatePacket.cs new file mode 100644 index 00000000..8e775c69 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpNodePoseSyncStatePacket.cs @@ -0,0 +1,23 @@ +using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets +{ + public sealed class MpNodePoseSyncStatePacket : INetSerializable + { + public float deltaUpdateFrequency; + public float fullStateUpdateFrequency; + + public void WriteTo(ref SpanBuffer bufferWriter) + { + bufferWriter.WriteFloat32(deltaUpdateFrequency); + bufferWriter.WriteFloat32(fullStateUpdateFrequency); + } + public void ReadFrom(ref SpanBuffer bufferReader) + { + deltaUpdateFrequency = bufferReader.ReadFloat32(); + fullStateUpdateFrequency = bufferReader.ReadFloat32(); + } + } + +} diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs index cc1ee3e5..69bd7c4d 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs @@ -19,6 +19,7 @@ public override void Register() AddPacket(); AddPacket(); AddPacket(); + AddPacket(); } public bool TryCreatePacket(string packetId, [MaybeNullWhen(false)] out INetSerializable packet) From 10ab940cefd543994554016d1770cca3e1a95c36 Mon Sep 17 00:00:00 2001 From: cubic Date: Sat, 13 May 2023 22:56:02 +0100 Subject: [PATCH 012/120] Protected the server update loop from running whilst a player is disconnecting player joins are now smoother? still needs some work --- .../Abstractions/IPacketDispatcher.cs | 15 +- .../Abstractions/IPlayerRegistry.cs | 3 - .../DedicatedInstance.cs | 113 ++++------ .../Managers/LobbyManager.cs | 8 +- .../PacketDispatcher.cs | 202 +++++++++++++++--- .../PacketSource.cs | 4 +- .../PlayerRegistry.cs | 31 ++- 7 files changed, 251 insertions(+), 125 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs index 8853fc59..349a338e 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs @@ -1,5 +1,6 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Enums; +using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { @@ -15,5 +16,17 @@ public interface IPacketDispatcher void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod); void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); - } + + + Task SendToNearbyPlayersAndAwait(INetSerializable packet, DeliveryMethod deliveryMethod); + Task SendToNearbyPlayersAndAwait(INetSerializable[] packets, DeliveryMethod deliveryMethod); + Task SendExcludingPlayerAndAwait(IPlayer excludedPlayer, INetSerializable packet, DeliveryMethod deliveryMethod); + Task SendExcludingPlayerAndAwait(IPlayer excludedPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); + Task SendFromPlayerAndAwait(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod); + Task SendFromPlayerAndAwait(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); + Task SendFromPlayerToPlayerAndAwait(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable packet, DeliveryMethod deliveryMethod); + Task SendFromPlayerToPlayerAndAwait(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); + Task SendToPlayerAndAwait(IPlayer player, INetSerializable packet, DeliveryMethod deliveryMethod); + Task SendToPlayerAndAwait(IPlayer player, INetSerializable[] packets, DeliveryMethod deliveryMethod); + } } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs index 35b46fac..0d162f90 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs @@ -12,9 +12,6 @@ public interface IPlayerRegistry bool TryGetPlayer(EndPoint remoteEndPoint, [MaybeNullWhen(false)] out IPlayer player); bool TryGetPlayer(byte connectionId, [MaybeNullWhen(false)] out IPlayer player); bool TryGetPlayer(string userId, [MaybeNullWhen(false)] out IPlayer player); - - bool ShouldPauseNodePoseSyncPackets(); - void SetShouldPauseSyncPackets(bool Joining); int GetMillisBetweenSyncStatePackets(); } } diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index a9b92314..1b3d8d2e 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -51,6 +51,7 @@ public sealed class DedicatedInstance : LiteNetServer, IDedicatedInstance private readonly IServiceProvider _serviceProvider; private readonly PacketEncryptionLayer _packetEncryptionLayer; + public readonly SemaphoreSlim ConnectDisconnectSemaphore = new(1); private byte _connectionIdCount = 0; private readonly object _ConnectionIDLock = new(); @@ -378,7 +379,7 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBuffer additionalDat public override void OnLatencyUpdate(EndPoint endPoint, int latency) => _logger.Verbose($"Latency updated (RemoteEndPoint='{endPoint}', Latency={0.001f * latency})."); - SemaphoreSlim ConnectDisconnectSemaphore = new SemaphoreSlim(1); + public override async void OnConnect(EndPoint endPoint) { @@ -394,9 +395,10 @@ public override async void OnConnect(EndPoint endPoint) Disconnect(endPoint); return; } - //Send new player their sort order and server's data - _packetDispatcher.SendToPlayer(player, new INetSerializable[] - { + //TODO add in max waiting time so that one player having ping issues does not murderise the whole server + + await _packetDispatcher.SendToPlayerAndAwait(player, new INetSerializable[] + { new SyncTimePacket { SyncTime = RunTime @@ -417,10 +419,9 @@ public override async void OnConnect(EndPoint endPoint) { Reason = player.UserId == _configuration.ServerOwnerId ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None } - },DeliveryMethod.ReliableOrdered); - _playerRegistry.SetShouldPauseSyncPackets(true); + }, DeliveryMethod.ReliableOrdered); //Sends to all players that they have connected - _packetDispatcher.SendExcludingPlayer(player, new INetSerializable[] + await _packetDispatcher.SendExcludingPlayerAndAwait(player, new INetSerializable[] { new SyncTimePacket { @@ -437,16 +438,17 @@ public override async void OnConnect(EndPoint endPoint) { UserId = player.UserId, SortIndex = player.SortIndex - }, + }, } , DeliveryMethod.ReliableOrdered); + Task[] ConnectionTasks = new Task[2]; foreach (IPlayer p in _playerRegistry.Players) { if (p.ConnectionId != player.ConnectionId) { // Send all player connection data packets to new player - _packetDispatcher.SendToPlayer(player,new INetSerializable[]{ + ConnectionTasks[0] = _packetDispatcher.SendToPlayerAndAwait(player, new INetSerializable[]{ new PlayerConnectedPacket { RemoteConnectionId = p.ConnectionId, @@ -462,7 +464,7 @@ public override async void OnConnect(EndPoint endPoint) }, DeliveryMethod.ReliableOrdered); // Send all player identity packets to new player - _packetDispatcher.SendFromPlayerToPlayer(p, player, new INetSerializable[] + ConnectionTasks[1] = _packetDispatcher.SendFromPlayerToPlayerAndAwait(p, player, new INetSerializable[] { new PlayerIdentityPacket { @@ -477,87 +479,62 @@ public override async void OnConnect(EndPoint endPoint) Platform = (byte)p.Platform, ClientVersion = p.ClientVersion! } - },DeliveryMethod.ReliableOrdered); - + }, DeliveryMethod.ReliableOrdered); + await Task.WhenAll(ConnectionTasks); } } + // Update permissions - constant manager possibly does not work if ((_configuration.SetConstantManagerFromUserId == player.UserId || _playerRegistry.GetPlayerCount() == 1) && _configuration.GameplayServerMode == GameplayServerMode.Managed) { _configuration.ServerOwnerId = player.UserId; } - _packetDispatcher.SendToPlayer(player, new SetPlayersPermissionConfigurationPacket - { - PermissionConfiguration = new PlayersPermissionConfiguration - { - PlayersPermission = _playerRegistry.Players.Select(x => new PlayerPermissionConfiguration - { - UserId = x.UserId, - IsServerOwner = x.IsServerOwner, - HasRecommendBeatmapsPermission = x.CanRecommendBeatmaps, - HasRecommendGameplayModifiersPermission = x.CanRecommendModifiers, - HasKickVotePermission = x.CanKickVote, - HasInvitePermission = x.CanInvite - }).ToArray() - } - }, DeliveryMethod.ReliableOrdered); - _packetDispatcher.SendExcludingPlayer(player, new SetPlayersPermissionConfigurationPacket + //Send remaining join packets + ConnectionTasks = new Task[4]; + foreach (IPlayer p in _playerRegistry.Players) { - PermissionConfiguration = new PlayersPermissionConfiguration + ConnectionTasks[0] = _packetDispatcher.SendToPlayerAndAwait(p,new SetPlayersPermissionConfigurationPacket { - PlayersPermission = new PlayerPermissionConfiguration[] + PermissionConfiguration = new PlayersPermissionConfiguration { - new PlayerPermissionConfiguration() + PlayersPermission = _playerRegistry.Players.Select(x => new PlayerPermissionConfiguration { - UserId = player!.UserId, - IsServerOwner = player.IsServerOwner, - HasRecommendBeatmapsPermission = player.CanRecommendBeatmaps, - HasRecommendGameplayModifiersPermission = player.CanRecommendModifiers, - HasKickVotePermission = player.CanKickVote, - HasInvitePermission = player.CanInvite - } + UserId = x.UserId, + IsServerOwner = x.IsServerOwner, + HasRecommendBeatmapsPermission = x.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = x.CanRecommendModifiers, + HasKickVotePermission = x.CanKickVote, + HasInvitePermission = x.CanInvite + }).ToArray() } - } - }, DeliveryMethod.ReliableOrdered); - _playerRegistry.SetShouldPauseSyncPackets(false); - - ConnectDisconnectSemaphore.Release(); - - - foreach (IPlayer p in _playerRegistry.Players) - { + }, DeliveryMethod.ReliableOrdered); if (p.ConnectionId != player.ConnectionId) { - _packetDispatcher.SendFromPlayerToPlayer(player, p, new MpPlayerData + ConnectionTasks[1] = _packetDispatcher.SendFromPlayerToPlayerAndAwait(player, p, new MpPlayerData { PlatformID = player.PlatformUserId!, Platform = (byte)player.Platform, ClientVersion = player.ClientVersion! }, DeliveryMethod.ReliableOrdered); } - } - - PlayerConnectedEvent?.Invoke(player); - - - _packetDispatcher.SendToNearbyPlayers(new MpNodePoseSyncStatePacket - { - fullStateUpdateFrequency = 0.1f, - deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f - }, DeliveryMethod.ReliableOrdered); - - if((_playerRegistry.GetPlayerCount() == 7 || _playerRegistry.GetPlayerCount() == 13) && _playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var serverOwner)) - { - _packetDispatcher.SendToPlayer(serverOwner, new MpcTextChatPacket() + else + { + ConnectionTasks[1] = Task.CompletedTask; + } + ConnectionTasks[2] = _packetDispatcher.SendToPlayerAndAwait(p, new MpNodePoseSyncStatePacket + { + fullStateUpdateFrequency = 0.1f, + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f + }, DeliveryMethod.ReliableOrdered); + ConnectionTasks[3] = _packetDispatcher.SendToPlayerAndAwait(p, new MpcTextChatPacket() { - Text = "Do players seem to lag during gameplay? Disable beatmap notes by typing '/n false' or '/n f', Type '/h n' For more info on the command" - },DeliveryMethod.ReliableOrdered); + Text = "Player joined: " + player.UserName + " Platform: " + player.Platform.ToString() + " Game version: " + player.ClientVersion + }, DeliveryMethod.ReliableOrdered); + await Task.WhenAll(ConnectionTasks); } - _packetDispatcher.SendToNearbyPlayers(new MpcTextChatPacket() - { - Text = "Player joined: " + player.UserName + " Platform: " + player.Platform.ToString() + " Game version: " + player.ClientVersion - }, DeliveryMethod.ReliableOrdered); + ConnectDisconnectSemaphore.Release(); + PlayerConnectedEvent?.Invoke(player); } public void DisconnectPlayer(string UserId) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 54ea86f8..01aabbb1 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -84,12 +84,14 @@ private async void UpdateLoop(CancellationToken cancellationToken) try { await Task.Delay(LoopTime, cancellationToken); + await ((DedicatedInstance)_instance).ConnectDisconnectSemaphore.WaitAsync(cancellationToken); Update(); + ((DedicatedInstance)_instance).ConnectDisconnectSemaphore.Release(); UpdateLoop(cancellationToken); } - catch - { - + catch (TaskCanceledException){} + catch (OperationCanceledException){ + ((DedicatedInstance)_instance).ConnectDisconnectSemaphore.Release(); } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index 2fee28bd..044ed761 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -8,6 +8,8 @@ using BeatTogether.LiteNetLib.Util; using Serilog; using System.Net; +using System.Numerics; +using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel { @@ -34,6 +36,7 @@ public PacketDispatcher( _playerRegistry = playerRegistry; } + #region Sends public void SendToNearbyPlayers(INetSerializable packet, DeliveryMethod deliveryMethod) { _logger.Debug( @@ -94,48 +97,186 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packe Send(player.Endpoint, writer.Data, deliveryMethod); } - public void SendToEndpoint(EndPoint endpoint, INetSerializable packet, DeliveryMethod deliveryMethod) + public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) + { + _logger.Debug( + $"Sending packet of type '{packet.GetType().Name}' " + + $"(SenderId={fromPlayer.ConnectionId})" + ); + + var writer = new SpanBuffer(stackalloc byte[412]); + writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); + WriteOne(ref writer, packet); + + foreach (var player in _playerRegistry.Players) + Send(player.Endpoint, writer.Data, deliveryMethod); + } + public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) + { + _logger.Debug( + $"Sending MultiPacket " + + $"(SenderId={fromPlayer.ConnectionId})" + ); + + var writer = new SpanBuffer(stackalloc byte[1024]); + writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); + WriteMany(ref writer, packets); + + foreach (var player in _playerRegistry.Players) + Send(player.Endpoint, writer.Data, deliveryMethod); + } + + public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) + { + _logger.Debug( + $"Sending packet of type '{packet.GetType().Name}' " + + $"(SenderId={fromPlayer.ConnectionId}, ReceiverId={LocalConnectionId})." + ); + + var writer = new SpanBuffer(stackalloc byte[412]); + writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); + WriteOne(ref writer, packet); + Send(toPlayer.Endpoint, writer.Data, deliveryMethod); + } + public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) + { + _logger.Debug( + $"Sending MultiPacket" + + $"(SenderId={fromPlayer.ConnectionId}, ReceiverId={LocalConnectionId})." + ); + + var writer = new SpanBuffer(stackalloc byte[1024]); + writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); + WriteMany(ref writer, packets); + Send(toPlayer.Endpoint, writer.Data, deliveryMethod); + } + + public void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod deliveryMethod) { _logger.Debug( $"Sending packet of type '{packet.GetType().Name}' " + - $"(To endpoint ={endpoint})" + $"(SenderId={ServerId}, ReceiverId={LocalConnectionId})." ); var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); + Send(player.Endpoint, writer.Data, deliveryMethod); + } + public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMethod deliveryMethod) + { + _logger.Debug( + $"Sending MultiPacket " + + $"(SenderId={ServerId}, ReceiverId={LocalConnectionId})." + ); - Send(endpoint, writer.Data, deliveryMethod); + var writer = new SpanBuffer(stackalloc byte[1024]); + writer.WriteRoutingHeader(ServerId, LocalConnectionId); + WriteMany(ref writer, packets); + Send(player.Endpoint, writer.Data, deliveryMethod); } - public void SendToEndpoint(EndPoint endpoint, INetSerializable[] packets, DeliveryMethod deliveryMethod) + #endregion + + #region AwaitableSends + //Sends with a task that completes when the packet/s have been rec + public Task SendToNearbyPlayersAndAwait(INetSerializable packet, DeliveryMethod deliveryMethod) + { + _logger.Debug( + $"Sending packet of type '{packet.GetType().Name}' " + + $"(SenderId={ServerId})" + ); + + var writer = new SpanBuffer(stackalloc byte[412]); + writer.WriteRoutingHeader(ServerId, LocalConnectionId); + WriteOne(ref writer, packet); + _logger.Verbose("Packet: " + packet.GetType().Name + " Was entered into the spanbuffer correctly, now sending once to each player"); + var players = _playerRegistry.Players; + Task[] tasks = new Task[players.Length]; + for (int i = 0; i < players.Length; i++) + tasks[i] = Send(players[i].Endpoint, writer.Data, deliveryMethod); + return Task.WhenAll(tasks); + } + public Task SendToNearbyPlayersAndAwait(INetSerializable[] packets, DeliveryMethod deliveryMethod) { _logger.Debug( $"Sending MultiPacket " + - $"(To endpoint ={endpoint})" + $"(SenderId={ServerId})" ); var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); + _logger.Verbose("Packets were entered into the spanbuffer correctly, now sending once to each player"); + var players = _playerRegistry.Players; + Task[] tasks = new Task[players.Length]; + for (int i = 0; i < players.Length; i++) + tasks[i] = Send(players[i].Endpoint, writer.Data, deliveryMethod); + return Task.WhenAll(tasks); + } + + public Task SendExcludingPlayerAndAwait(IPlayer excludedPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) + { + _logger.Debug( + $"Sending packet of type '{packet.GetType().Name}' " + + $"(ExcludedId={excludedPlayer.ConnectionId})" + ); - Send(endpoint, writer.Data, deliveryMethod); + var writer = new SpanBuffer(stackalloc byte[412]); + writer.WriteRoutingHeader(ServerId, LocalConnectionId); + WriteOne(ref writer, packet); + + var players = _playerRegistry.Players; + Task[] tasks = new Task[players.Length - 1]; + int i = 0; + foreach (var player in players) + if (player.ConnectionId != excludedPlayer.ConnectionId) + { + tasks[i] = Send(player.Endpoint, writer.Data, deliveryMethod); + i++; + } + return Task.WhenAll(tasks); } + public Task SendExcludingPlayerAndAwait(IPlayer excludedPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) + { + _logger.Debug( + $"Sending MultiPacket " + + $"(ExcludedId={excludedPlayer.ConnectionId})" + ); - public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending packet of type '{packet.GetType().Name}' " + + var writer = new SpanBuffer(stackalloc byte[1024]); + writer.WriteRoutingHeader(ServerId, LocalConnectionId); + WriteMany(ref writer, packets); + var players = _playerRegistry.Players; + Task[] tasks = new Task[players.Length-1]; + int i = 0; + foreach (var player in players) + if (player.ConnectionId != excludedPlayer.ConnectionId) + { + tasks[i] = Send(player.Endpoint, writer.Data, deliveryMethod); + i++; + } + return Task.WhenAll(tasks); + + + } + + public Task SendFromPlayerAndAwait(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) + { + _logger.Debug( + $"Sending packet of type '{packet.GetType().Name}' " + $"(SenderId={fromPlayer.ConnectionId})" ); var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteOne(ref writer, packet); - - foreach (var player in _playerRegistry.Players) - Send(player.Endpoint, writer.Data, deliveryMethod); - } - public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) + var players = _playerRegistry.Players; + Task[] tasks = new Task[players.Length]; + for (int i = 0; i < players.Length; i++) + tasks[i] = Send(players[i].Endpoint, writer.Data, deliveryMethod); + return Task.WhenAll(tasks); + } + public Task SendFromPlayerAndAwait(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) { _logger.Debug( $"Sending MultiPacket " + @@ -145,12 +286,14 @@ public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, Deliv var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteMany(ref writer, packets); - - foreach (var player in _playerRegistry.Players) - Send(player.Endpoint, writer.Data, deliveryMethod); + var players = _playerRegistry.Players; + Task[] tasks = new Task[players.Length]; + for (int i = 0; i < players.Length; i++) + tasks[i] = Send(players[i].Endpoint, writer.Data, deliveryMethod); + return Task.WhenAll(tasks); } - public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) + public Task SendFromPlayerToPlayerAndAwait(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) { _logger.Debug( $"Sending packet of type '{packet.GetType().Name}' " + @@ -160,10 +303,9 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteOne(ref writer, packet); - Send(toPlayer.Endpoint, writer.Data, deliveryMethod); + return Send(toPlayer.Endpoint, writer.Data, deliveryMethod); } - - public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) + public Task SendFromPlayerToPlayerAndAwait(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) { _logger.Debug( $"Sending MultiPacket" + @@ -173,10 +315,10 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteMany(ref writer, packets); - Send(toPlayer.Endpoint, writer.Data, deliveryMethod); + return Send(toPlayer.Endpoint, writer.Data, deliveryMethod); } - public void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod deliveryMethod) + public Task SendToPlayerAndAwait(IPlayer player, INetSerializable packet, DeliveryMethod deliveryMethod) { _logger.Debug( $"Sending packet of type '{packet.GetType().Name}' " + @@ -186,10 +328,9 @@ public void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); - Send(player.Endpoint, writer.Data, deliveryMethod); + return Send(player.Endpoint, writer.Data, deliveryMethod); } - - public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMethod deliveryMethod) + public Task SendToPlayerAndAwait(IPlayer player, INetSerializable[] packets, DeliveryMethod deliveryMethod) { _logger.Debug( $"Sending MultiPacket " + @@ -199,9 +340,11 @@ public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMet var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); - Send(player.Endpoint, writer.Data, deliveryMethod); + return Send(player.Endpoint, writer.Data, deliveryMethod); } + #endregion + #region Writers public void WriteOne(ref SpanBuffer writer, INetSerializable packet) { var type = packet.GetType(); @@ -225,11 +368,12 @@ public void WriteOne(ref SpanBuffer writer, INetSerializable packet) writer.WriteVarUInt((uint)packetWriter.Size); writer.WriteBytes(packetWriter.Data.ToArray()); } - public void WriteMany(ref SpanBuffer writer, INetSerializable[] packets) { for (int i = 0; i < packets.Length; i++) WriteOne(ref writer, packets[i]); } + + #endregion } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index 6db05514..420105e6 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -131,7 +131,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D } if (packet is NodePoseSyncStatePacket) { - if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncState) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets() || _playerRegistry.ShouldPauseNodePoseSyncPackets()) + if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncState) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets()) { return; } @@ -140,7 +140,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D } if (packet is NodePoseSyncStateDeltaPacket) { - if((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncStateDelta) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets() || _playerRegistry.ShouldPauseNodePoseSyncPackets()) + if((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncStateDelta) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets()) { return; } diff --git a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs index defd4134..4ebf51c4 100644 --- a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs @@ -2,14 +2,14 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net; -using System.Runtime.CompilerServices; using BeatTogether.DedicatedServer.Kernel.Abstractions; namespace BeatTogether.DedicatedServer.Kernel { public sealed class PlayerRegistry : IPlayerRegistry { - public IPlayer[] Players { get => _playersByUserId.Values.ToArray(); } + + public IPlayer[] Players { get => GetPlayers(); } private object PlayerDictionaries_Lock = new(); private readonly Dictionary _playersByRemoteEndPoint = new(); @@ -25,6 +25,16 @@ public int GetPlayerCount() return _PlayerCount; } } + + private IPlayer[] GetPlayers() + { + lock (PlayerDictionaries_Lock) + { + return _playersByUserId.Values.ToArray(); + } + } + + public bool AddPlayer(IPlayer player) { lock (PlayerDictionaries_Lock) @@ -83,23 +93,6 @@ public bool TryGetPlayer(string userId, [MaybeNullWhen(false)] out IPlayer playe } } - private readonly object UnreliableRoutingHold_Lock = new(); - bool UnreliableRoutingHold = false; - public bool ShouldPauseNodePoseSyncPackets() - { - lock (UnreliableRoutingHold_Lock) - { - return UnreliableRoutingHold && GetPlayerCount() > 15; - } - } - public void SetShouldPauseSyncPackets(bool Joining) - { - lock (UnreliableRoutingHold_Lock) - { - UnreliableRoutingHold = Joining; - } - } - private readonly object MillisBetweenSyncStatePackets_Lock = new(); private int MillisBetweenSyncStatePackets = 0; public int GetMillisBetweenSyncStatePackets() From 6bff9b910084edb164a704991e28ef1346bf064d Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 15 May 2023 23:02:43 +0100 Subject: [PATCH 013/120] Removed locks around packet handlers, replaced with a per player semaphore slim. Changed joining code to not allow connects and disconnects to happen simultaneously. Packets with the wrong length still get routed (stoped being so because of handling code before routing code). Added avatar packet --- .../Abstractions/IDedicatedInstance.cs | 2 +- .../Abstractions/IPlayer.cs | 14 +- .../Configuration/InstanceConfiguration.cs | 1 + .../DedicatedInstance.cs | 147 ++++++++++-------- .../Managers/Abstractions/ILobbyManager.cs | 10 +- .../Managers/LobbyManager.cs | 101 ++++++------ .../MPChat/MpcCapabilitiesPacketHandler.cs | 9 +- .../ClearRecommendedBeatmapPacketHandler.cs | 13 +- .../ClearRecommendedModifiersPacketHandler.cs | 6 +- .../MenuRpc/GetStartedLevelPacketHandler.cs | 9 +- .../MenuRpc/RequestKickPlayerPacketHandler.cs | 9 +- .../SetIsEntitledToLevelPacketHandler.cs | 17 +- .../MenuRpc/SetIsInLobbyPacketHandler.cs | 24 +-- .../MenuRpc/SetIsReadyPacketHandler.cs | 28 ++-- .../SetRecommendedBeatmapPacketHandler.cs | 34 ++-- .../SetRecommendedModifiersPacketHandler.cs | 13 +- .../DediPacketSetNewManagerHandler.cs | 35 ++--- .../GetExtraPlayerDataPacketHandler.cs | 1 + .../PlayerAvatarPacketHandler.cs | 34 ++++ .../PlayerIdentityPacketHandler.cs | 20 ++- .../PlayerLatencyPacketHandler.cs | 17 +- .../PlayerSortOrderPacketHandler.cs | 16 +- .../PlayerStatePacketHandler.cs | 18 ++- .../PacketSource.cs | 21 ++- BeatTogether.DedicatedServer.Kernel/Player.cs | 35 ++--- ...tTogether.DedicatedServer.Messaging.csproj | 2 +- .../Models/ConnectionRequestData.cs | 51 ++++++ .../Packets/PlayerAvatarPacket.cs | 21 +++ .../Registries/PacketRegistry.cs | 1 + 29 files changed, 406 insertions(+), 303 deletions(-) create mode 100644 BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerAvatarPacketHandler.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/PlayerAvatarPacket.cs diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs index 8db9f94f..2abf65b2 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs @@ -16,7 +16,7 @@ public interface IDedicatedInstance event Action PlayerDisconnectBeforeJoining; event Action GameIsInLobby; event Action UpdateInstanceEvent; - + SemaphoreSlim ConnectDisconnectSemaphore { get; } void InstanceConfigUpdated(); InstanceConfiguration _configuration { get; } bool IsRunning { get; } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index c30496e2..d2d1b7f3 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -3,11 +3,15 @@ using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; using System.Net; +using System.Threading; +using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { public interface IPlayer { + SemaphoreSlim PlayerAccessSemaphore { get; set; } + TaskCompletionSource PlayerInitialised { get; set; } EndPoint Endpoint { get; } IDedicatedInstance Instance { get; } byte ConnectionId { get; } @@ -20,21 +24,14 @@ public interface IPlayer string ClientVersion { get; set; } Platform Platform { get; set; } string PlatformUserId { get; set; } - object LatencyLock { get; set; } RollingAverage Latency { get; } float SyncTime { get; } - object SortLock { get; set; } int SortIndex { get; set; } - object PlayerIdentityLock { get; set; } AvatarData Avatar { get; set; } - object ReadyLock { get; set; } bool IsReady { get; set; } - object BeatmapLock { get; set; } BeatmapIdentifier? BeatmapIdentifier { get; set; } - object ModifiersLock { get; set; } GameplayModifiers Modifiers { get; set; } - object StateLock { get; set; } PlayerStateHash State { get; set; } public bool IsServerOwner { get; } @@ -52,11 +49,8 @@ public interface IPlayer bool IsActive { get; } bool FinishedLevel { get; } bool InMenu { get; } - object InLobbyLock { get; set; } bool InLobby { get; set; } - object EntitlementLock { get; set; } bool IsPatreon { get; set; } - object MPChatLock { get; set; } bool CanTextChat { get; set; } public bool CanReceiveVoiceChat { get; set; } public bool CanTransmitVoiceChat { get; set; } diff --git a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs index d5af0a21..70ba3eed 100644 --- a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs +++ b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs @@ -26,6 +26,7 @@ public sealed class InstanceConfiguration public bool AllowNoodleExtensions { get; set; } public bool DisableNotes { get; set; } public bool ForceEnableNotes { get; set; } = false; + public bool ForceStartMode { get; set; } = false; public float KickPlayersWithoutEntitlementTimeout { get; set; } = 30f; public int MaxLengthCommand { get; set; } = 200; public bool ApplyNoFailModifier { get; set; } = true; diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 1b3d8d2e..accd5e0a 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Net; @@ -50,8 +49,7 @@ public sealed class DedicatedInstance : LiteNetServer, IDedicatedInstance private readonly IPlayerRegistry _playerRegistry; private readonly IServiceProvider _serviceProvider; private readonly PacketEncryptionLayer _packetEncryptionLayer; - - public readonly SemaphoreSlim ConnectDisconnectSemaphore = new(1); + public SemaphoreSlim ConnectDisconnectSemaphore { get; } = new(1); //Stops lobby loop from running during player connection/disconnection, and stops disconnects and connects happening simultaneously private byte _connectionIdCount = 0; private readonly object _ConnectionIDLock = new(); @@ -253,20 +251,18 @@ public void SetState(MultiplayerGameState state) #region LiteNetServer - public override bool ShouldAcceptConnection(EndPoint endPoint, ref SpanBuffer additionalData) + public override async Task ShouldAcceptConnection(EndPoint endPoint, MemoryBuffer additionalData) { - if (ShouldDenyConnection(endPoint, ref additionalData)) + if (await ShouldDenyConnection(endPoint, additionalData)) { string[] Players = _playerRegistry.Players.Select(p => p.UserId).ToArray(); PlayerDisconnectBeforeJoining?.Invoke(_configuration.Secret, endPoint, Players); return false; } - _logger.Information("connection accepted"); return true; } - private readonly object _PlayerJoining_Lock = new(); - public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBuffer additionalData) + public async Task ShouldDenyConnection(EndPoint endPoint, MemoryBuffer additionalData) { var connectionRequestData = new ConnectionRequestData(); try @@ -302,40 +298,37 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBuffer additionalDat ); return true; } - IPlayer player; - lock (_PlayerJoining_Lock) + await ConnectDisconnectSemaphore.WaitAsync(); + if (_playerRegistry.GetPlayerCount() >= _configuration.MaxPlayerCount) { - if (_playerRegistry.GetPlayerCount() >= _configuration.MaxPlayerCount) - { - _logger.Information("Max player count"); - return true; - } - if (connectionRequestData.UserName == "IGGAMES" || connectionRequestData.UserName == "IGGGAMES") - { - _logger.Information("an IGG player just tried joining after passing master auth"); - return true; - } - int sortIndex = GetNextSortIndex(); - byte connectionId = GetNextConnectionId(); - - player = new Player( - endPoint, - this, - connectionId, - _configuration.Secret, - connectionRequestData.UserId, - connectionRequestData.UserName, - connectionRequestData.PlayerSessionId - ) - { - SortIndex = sortIndex - }; - if (!_playerRegistry.AddPlayer(player)) - { - ReleaseSortIndex(player.SortIndex); - ReleaseConnectionId(player.ConnectionId); - return true; - } + _logger.Warning("Master server sent a player to a full server"); + return true; + } + if (connectionRequestData.UserName == "IGGAMES" || connectionRequestData.UserName == "IGGGAMES") + { + _logger.Information("an IGG player just tried joining after passing master auth"); + return true; + } + int sortIndex = GetNextSortIndex(); + byte connectionId = GetNextConnectionId(); + + var player = new Player( + endPoint, + this, + connectionId, + _configuration.Secret, + connectionRequestData.UserId, + connectionRequestData.UserName, + connectionRequestData.PlayerSessionId + ) + { + SortIndex = sortIndex + }; + if (!_playerRegistry.AddPlayer(player)) + { + ReleaseSortIndex(player.SortIndex); + ReleaseConnectionId(player.ConnectionId); + return true; } if (_configuration.ServerName == string.Empty) @@ -373,9 +366,9 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBuffer additionalDat handshakeSession.EncryptionParameters, true); } } - + ConnectDisconnectSemaphore.Release(); return false; -} + } public override void OnLatencyUpdate(EndPoint endPoint, int latency) => _logger.Verbose($"Latency updated (RemoteEndPoint='{endPoint}', Latency={0.001f * latency})."); @@ -383,7 +376,6 @@ public override void OnLatencyUpdate(EndPoint endPoint, int latency) public override async void OnConnect(EndPoint endPoint) { - await ConnectDisconnectSemaphore.WaitAsync(); _logger.Information($"Endpoint connected (RemoteEndPoint='{endPoint}')"); if (!_playerRegistry.TryGetPlayer(endPoint, out var player)) @@ -395,9 +387,13 @@ public override async void OnConnect(EndPoint endPoint) Disconnect(endPoint); return; } - //TODO add in max waiting time so that one player having ping issues does not murderise the whole server + await ConnectDisconnectSemaphore.WaitAsync(); - await _packetDispatcher.SendToPlayerAndAwait(player, new INetSerializable[] + IPlayer[] PlayersAtJoin = _playerRegistry.Players; + + await player.PlayerAccessSemaphore.WaitAsync(); + + var Player_ConnectPacket = new INetSerializable[] { new SyncTimePacket { @@ -419,9 +415,9 @@ public override async void OnConnect(EndPoint endPoint) { Reason = player.UserId == _configuration.ServerOwnerId ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None } - }, DeliveryMethod.ReliableOrdered); - //Sends to all players that they have connected - await _packetDispatcher.SendExcludingPlayerAndAwait(player, new INetSerializable[] + }; + + var SendToOtherPlayers = new INetSerializable[] { new SyncTimePacket { @@ -439,16 +435,24 @@ public override async void OnConnect(EndPoint endPoint) UserId = player.UserId, SortIndex = player.SortIndex }, - } - , DeliveryMethod.ReliableOrdered); + }; + player.PlayerAccessSemaphore.Release(); + _packetDispatcher.SendToPlayer(player, Player_ConnectPacket, DeliveryMethod.ReliableOrdered); + //Sends to all players that they have connected + await _packetDispatcher.SendExcludingPlayerAndAwait(player, SendToOtherPlayers, DeliveryMethod.ReliableOrdered).WaitAsync(TimeSpan.FromMilliseconds(100)); + INetSerializable[] SendToPlayer; + INetSerializable[] SendToPlayerFromPlayers; Task[] ConnectionTasks = new Task[2]; - foreach (IPlayer p in _playerRegistry.Players) + foreach (IPlayer p in PlayersAtJoin) { if (p.ConnectionId != player.ConnectionId) { // Send all player connection data packets to new player - ConnectionTasks[0] = _packetDispatcher.SendToPlayerAndAwait(player, new INetSerializable[]{ + if (!p.PlayerInitialised.Task.IsCompleted) + await p.PlayerInitialised.Task.WaitAsync(TimeSpan.FromMilliseconds(200)); //awaits the player connecting + await p.PlayerAccessSemaphore.WaitAsync(); + SendToPlayer = new INetSerializable[]{ new PlayerConnectedPacket { RemoteConnectionId = p.ConnectionId, @@ -461,17 +465,16 @@ public override async void OnConnect(EndPoint endPoint) UserId = p.UserId, SortIndex = p.SortIndex } - }, DeliveryMethod.ReliableOrdered); - - // Send all player identity packets to new player - ConnectionTasks[1] = _packetDispatcher.SendFromPlayerToPlayerAndAwait(p, player, new INetSerializable[] + }; + SendToPlayerFromPlayers = new INetSerializable[] { - new PlayerIdentityPacket + new PlayerAvatarPacket + { + PlayerAvatar = p.Avatar + }, + new PlayerStatePacket { - PlayerState = p.State, - PlayerAvatar = p.Avatar, - Random = new ByteArray { Data = p.Random }, - PublicEncryptionKey = new ByteArray { Data = p.PublicEncryptionKey } + PlayerState = p.State }, new MpPlayerData { @@ -479,8 +482,13 @@ public override async void OnConnect(EndPoint endPoint) Platform = (byte)p.Platform, ClientVersion = p.ClientVersion! } - }, DeliveryMethod.ReliableOrdered); - await Task.WhenAll(ConnectionTasks); + }; + p.PlayerAccessSemaphore.Release(); + ConnectionTasks[0] = _packetDispatcher.SendToPlayerAndAwait(player, SendToPlayer, DeliveryMethod.ReliableOrdered); + + // Send all player avatars and states to just joined player + ConnectionTasks[1] = _packetDispatcher.SendFromPlayerToPlayerAndAwait(p, player, SendToPlayerFromPlayers, DeliveryMethod.ReliableOrdered); + await Task.WhenAll(ConnectionTasks).WaitAsync(TimeSpan.FromMilliseconds(100)); } } @@ -492,13 +500,13 @@ public override async void OnConnect(EndPoint endPoint) //Send remaining join packets ConnectionTasks = new Task[4]; - foreach (IPlayer p in _playerRegistry.Players) + foreach (IPlayer p in PlayersAtJoin) { ConnectionTasks[0] = _packetDispatcher.SendToPlayerAndAwait(p,new SetPlayersPermissionConfigurationPacket { PermissionConfiguration = new PlayersPermissionConfiguration { - PlayersPermission = _playerRegistry.Players.Select(x => new PlayerPermissionConfiguration + PlayersPermission = PlayersAtJoin.Select(x => new PlayerPermissionConfiguration { UserId = x.UserId, IsServerOwner = x.IsServerOwner, @@ -531,13 +539,13 @@ public override async void OnConnect(EndPoint endPoint) { Text = "Player joined: " + player.UserName + " Platform: " + player.Platform.ToString() + " Game version: " + player.ClientVersion }, DeliveryMethod.ReliableOrdered); - await Task.WhenAll(ConnectionTasks); + await Task.WhenAll(ConnectionTasks).WaitAsync(TimeSpan.FromMilliseconds(100)); } ConnectDisconnectSemaphore.Release(); PlayerConnectedEvent?.Invoke(player); } - public void DisconnectPlayer(string UserId) + public void DisconnectPlayer(string UserId) //Used my master server kick player event { if(_playerRegistry.TryGetPlayer(UserId, out var player)) @@ -579,6 +587,7 @@ public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reas PlayerDisconnectedEvent?.Invoke(player); } + ConnectDisconnectSemaphore.Release(); if (_playerRegistry.GetPlayerCount() != 0 && string.IsNullOrEmpty(_configuration.ServerOwnerId) && _configuration.GameplayServerMode == GameplayServerMode.Managed) { @@ -612,7 +621,7 @@ public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reas Reason = CannotStartGameReason.NoSongSelected }, DeliveryMethod.ReliableOrdered); } - ConnectDisconnectSemaphore.Release(); + _packetDispatcher.SendToNearbyPlayers(new MpNodePoseSyncStatePacket { diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs index 232c2420..e422145d 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs @@ -1,6 +1,7 @@ -using BeatTogether.DedicatedServer.Kernel.Enums; +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.Enums; +using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; -using System.Collections.Generic; namespace BeatTogether.DedicatedServer.Kernel.Managers.Abstractions { @@ -9,8 +10,8 @@ public interface ILobbyManager bool AllPlayersReady { get; } bool SomePlayersReady { get; } bool NoPlayersReady { get; } - bool AllPlayersSpectating { get; } - + bool AllPlayersNotWantToPlayNextLevel { get; } + bool DoesEveryoneOwnBeatmap { get; } BeatmapIdentifier? SelectedBeatmap { get; } GameplayModifiers SelectedModifiers { get; } CountdownState CountDownState { get; } @@ -19,5 +20,6 @@ public interface ILobbyManager void Update(); BeatmapDifficulty[] GetSelectedBeatmapDifficulties(); + CannotStartGameReason GetCannotStartGameReason(IPlayer player, bool DoesEveryoneOwnBeatmap); } } diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 01aabbb1..33acaf33 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.Design; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -27,11 +28,18 @@ namespace BeatTogether.DedicatedServer.Kernel.Managers { public sealed class LobbyManager : ILobbyManager, IDisposable { - - public bool AllPlayersReady => _playerRegistry.Players.All(p => p.IsReady || !p.WantsToPlayNextLevel); //if all players are ready OR spectating - public bool SomePlayersReady => _playerRegistry.Players.Any(p => p.IsReady); //if *any* are ready - public bool NoPlayersReady => _playerRegistry.Players.All(p => !p.IsReady || !p.WantsToPlayNextLevel); //players not ready or spectating - public bool AllPlayersSpectating => _playerRegistry.Players.All(p => !p.WantsToPlayNextLevel); //if all spectating + //TODO - todo list below + /* - Players who dont want to play next level should not block current players from being able to play (if spectating then dont beatmap check them) + * - Use per player semaphores instead of locks around handlers as there are locks around packet sends, which is probably causing a few issues + * - basicly re-write the lobby manager stuff and some gameplay manager things + * + */ + public bool AllPlayersReady => _playerRegistry.Players.All(p => p.IsReady || !p.WantsToPlayNextLevel); //If all are ready or not playing + public bool SomePlayersReady => _playerRegistry.Players.Any(p => p.IsReady); //If anyone is readied + public bool NoPlayersReady => _playerRegistry.Players.All(p => !p.IsReady || !p.WantsToPlayNextLevel); //players not ready or are going to spectate + public bool AllPlayersNotWantToPlayNextLevel => _playerRegistry.Players.All(p => !p.WantsToPlayNextLevel);//if all are going to be spectating + public bool AllPlayersAreInLobby => _playerRegistry.Players.All(p => p.InMenu);//if all are going to be spectating + public bool DoesEveryoneOwnBeatmap => SelectedBeatmap == null || !_playerRegistry.Players.Any(p => p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown); public BeatmapIdentifier? SelectedBeatmap { get; private set; } = null; public GameplayModifiers SelectedModifiers { get; private set; } = new(); @@ -84,14 +92,14 @@ private async void UpdateLoop(CancellationToken cancellationToken) try { await Task.Delay(LoopTime, cancellationToken); - await ((DedicatedInstance)_instance).ConnectDisconnectSemaphore.WaitAsync(cancellationToken); + await _instance.ConnectDisconnectSemaphore.WaitAsync(cancellationToken); Update(); - ((DedicatedInstance)_instance).ConnectDisconnectSemaphore.Release(); + _instance.ConnectDisconnectSemaphore.Release(); UpdateLoop(cancellationToken); } catch (TaskCanceledException){} catch (OperationCanceledException){ - ((DedicatedInstance)_instance).ConnectDisconnectSemaphore.Release(); + _instance.ConnectDisconnectSemaphore.Release(); } } @@ -113,45 +121,32 @@ public void Update() foreach (IPlayer player in _playerRegistry.Players) { - lock (player.EntitlementLock) + if (player.UpdateEntitlement) { - if (player.UpdateEntitlement) - { - if (player.BeatmapIdentifier != null) - _packetDispatcher.SendToPlayer(player, new SetPlayersMissingEntitlementsToLevelPacket - { - PlayersWithoutEntitlements = _playerRegistry.Players - .Where(p => p.GetEntitlement(player.BeatmapIdentifier.LevelId) is EntitlementStatus.NotOwned/* or EntitlementStatus.Unknown*/) - .Select(p => p.UserId).ToArray() - }, DeliveryMethod.ReliableOrdered); - player.UpdateEntitlement = false; - } + if (player.BeatmapIdentifier != null) + _packetDispatcher.SendToPlayer(player, new SetPlayersMissingEntitlementsToLevelPacket + { + PlayersWithoutEntitlements = _playerRegistry.Players + .Where(p => p.GetEntitlement(player.BeatmapIdentifier.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) + .Select(p => p.UserId).ToArray() + }, DeliveryMethod.ReliableOrdered); + player.UpdateEntitlement = false; } } + bool allPlayersOwnBeatmap = DoesEveryoneOwnBeatmap; - if (SelectedBeatmap != null) + if (_configuration.SongSelectionMode == SongSelectionMode.ServerOwnerPicks) { - bool allPlayersOwnBeatmap = _playerRegistry.Players - .All(p => p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.Ok or EntitlementStatus.NotDownloaded); - - if(_configuration.SongSelectionMode == SongSelectionMode.ServerOwnerPicks) + if (_lastBeatmap != SelectedBeatmap || _AllOwnMap != allPlayersOwnBeatmap || _lastSpectatorState != AllPlayersNotWantToPlayNextLevel) { - if (_lastBeatmap != SelectedBeatmap || _AllOwnMap != allPlayersOwnBeatmap || _lastSpectatorState != AllPlayersSpectating) + _packetDispatcher.SendToPlayer(serverOwner!, new SetIsStartButtonEnabledPacket { - if (AllPlayersSpectating) - _packetDispatcher.SendToPlayer(serverOwner!, new SetIsStartButtonEnabledPacket - { - Reason = CannotStartGameReason.AllPlayersSpectating - }, DeliveryMethod.ReliableOrdered); - else - { - _packetDispatcher.SendToPlayer(serverOwner!, new SetIsStartButtonEnabledPacket - { - Reason = allPlayersOwnBeatmap ? CannotStartGameReason.None : CannotStartGameReason.DoNotOwnSong - }, DeliveryMethod.ReliableOrdered); - } - } + Reason = GetCannotStartGameReason(serverOwner!, allPlayersOwnBeatmap) + }, DeliveryMethod.ReliableOrdered); } + } + if (SelectedBeatmap != null) + { _AllOwnMap = allPlayersOwnBeatmap; switch (_configuration.SongSelectionMode) //server modes @@ -172,18 +167,13 @@ public void Update() } else { - if(_configuration.SongSelectionMode == SongSelectionMode.ServerOwnerPicks && _lastBeatmap != SelectedBeatmap) - _packetDispatcher.SendToPlayer(serverOwner!, new SetIsStartButtonEnabledPacket - { - Reason = CannotStartGameReason.NoSongSelected - }, DeliveryMethod.ReliableOrdered); //Send stop countdown packet if the beatmap is somehow set to null (serrver owner may disconnect, or if tournament server setting the beatmap to null should stop the countdown) if (CountDownState != CountdownState.NotCountingDown) CancelCountdown(); } _lastManagerId = _configuration.ServerOwnerId; - _lastSpectatorState = AllPlayersSpectating; + _lastSpectatorState = AllPlayersNotWantToPlayNextLevel; _lastBeatmap = SelectedBeatmap; } @@ -194,7 +184,7 @@ private void CountingDown(bool isReady, bool NotStartable) { if (CountdownEndTime != 0 && CountdownEndTime <= _instance.RunTime) CancelCountdown(); - if ((AllPlayersReady && !AllPlayersSpectating && _AllOwnMap)) + if ((AllPlayersReady && !AllPlayersNotWantToPlayNextLevel && _AllOwnMap)) SetCountdown(CountdownState.StartBeatmapCountdown, _configuration.CountdownConfig.BeatMapStartCountdownTime); else if (isReady && _AllOwnMap) SetCountdown(CountdownState.CountingDown, _configuration.CountdownConfig.CountdownTimePlayersReady); @@ -231,7 +221,7 @@ private void CountingDown(bool isReady, bool NotStartable) } } // If server owner/all players are no longer ready or not all players own beatmap - if (NotStartable || !_AllOwnMap || AllPlayersSpectating) + if (NotStartable || !_AllOwnMap || AllPlayersNotWantToPlayNextLevel) CancelCountdown(); else if (CountDownState == CountdownState.CountingDown && (AllPlayersReady || (CountdownEndTime - _instance.RunTime) < _configuration.CountdownConfig.BeatMapStartCountdownTime)) SetCountdown(CountdownState.StartBeatmapCountdown, _configuration.CountdownConfig.BeatMapStartCountdownTime); @@ -413,7 +403,7 @@ private void CancelCountdown() } return SelectedBeatmap; - case SongSelectionMode.ServerPicks: //TODO, Make this pick a random beatsaver map or something like that + case SongSelectionMode.ServerPicks: return SelectedBeatmap!; }; return null; @@ -474,5 +464,18 @@ private GameplayModifiers GetSelectedModifiers() }; return new GameplayModifiers(); } + + public CannotStartGameReason GetCannotStartGameReason(IPlayer player, bool DoesEveryoneOwnBeatmap) + { + if (player.IsServerOwner && player.BeatmapIdentifier == null) + return CannotStartGameReason.NoSongSelected; + if (!AllPlayersAreInLobby) + return CannotStartGameReason.AllPlayersNotInLobby; + if (AllPlayersNotWantToPlayNextLevel) + return CannotStartGameReason.AllPlayersSpectating; + if (SelectedBeatmap != null && ((_configuration.ForceStartMode && player.GetEntitlement(SelectedBeatmap.LevelId) == EntitlementStatus.NotOwned) || (!_configuration.ForceStartMode && !DoesEveryoneOwnBeatmap))) + return CannotStartGameReason.DoNotOwnSong; + return CannotStartGameReason.None; + } } -} +} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs index 0e95089d..9bbc6c82 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs @@ -23,12 +23,9 @@ public MpcCapabilitiesPacketHandler(IPacketDispatcher packetDispatcher, public override Task Handle(IPlayer sender, MpcCapabilitiesPacket packet) { bool FirstJoin = !sender.CanTextChat && packet.CanTextChat; - lock (sender.MPChatLock) - { - sender.CanReceiveVoiceChat = packet.CanReceiveVoiceChat; - sender.CanTransmitVoiceChat = packet.CanTransmitVoiceChat; - sender.CanTextChat = packet.CanTextChat; - } + sender.CanReceiveVoiceChat = packet.CanReceiveVoiceChat; + sender.CanTransmitVoiceChat = packet.CanTransmitVoiceChat; + sender.CanTextChat = packet.CanTextChat; if (FirstJoin) { _packetDispatcher.SendToPlayer(sender, new MpcTextChatPacket diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs index 53cf03bb..18d026bc 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs @@ -28,15 +28,12 @@ public override Task Handle(IPlayer sender, ClearRecommendedBeatmapPacket packet $"Handling packet of type '{nameof(ClearRecommendedBeatmapPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - lock (sender.BeatmapLock) + sender.BeatmapIdentifier = null; + sender.ResetRecommendedMapRequirements(); + _packetDispatcher.SendToPlayer(sender, new SetIsStartButtonEnabledPacket { - sender.BeatmapIdentifier = null; - sender.ResetRecommendedMapRequirements(); - _packetDispatcher.SendToPlayer(sender, new SetIsStartButtonEnabledPacket - { - Reason = CannotStartGameReason.NoSongSelected - }, DeliveryMethod.ReliableOrdered); - } + Reason = sender.IsServerOwner ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None + }, DeliveryMethod.ReliableOrdered); return Task.CompletedTask; } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedModifiersPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedModifiersPacketHandler.cs index f710a617..f5c95387 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedModifiersPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedModifiersPacketHandler.cs @@ -24,10 +24,8 @@ public override Task Handle(IPlayer sender, ClearRecommendedModifiersPacket pack $"Handling packet of type '{nameof(ClearRecommendedModifiersPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - lock (sender.ModifiersLock) - { - sender.Modifiers = new GameplayModifiers(); - } + + sender.Modifiers = _lobbyManager.EmptyModifiers; return Task.CompletedTask; } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs index 7d6d46ff..6943708f 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs @@ -54,10 +54,11 @@ public override Task Handle(IPlayer sender, GetStartedLevelPacket packet) { if (_lobbyManager.SelectedBeatmap != null) { - _packetDispatcher.SendToPlayer(sender, new GetIsEntitledToLevelPacket - { - LevelId = _lobbyManager.SelectedBeatmap.LevelId - }, DeliveryMethod.ReliableOrdered); + if(sender.GetEntitlement(_lobbyManager.SelectedBeatmap.LevelId) != EntitlementStatus.Ok) + _packetDispatcher.SendToPlayer(sender, new GetIsEntitledToLevelPacket + { + LevelId = _lobbyManager.SelectedBeatmap.LevelId + }, DeliveryMethod.ReliableOrdered); if(_lobbyManager.CountDownState == CountdownState.WaitingForEntitlement || _lobbyManager.CountDownState == CountdownState.StartBeatmapCountdown) { diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs index da0754a0..9e48ca4e 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs @@ -22,21 +22,22 @@ public RequestKickPlayerPacketHandler( _packetDispatcher = packetDispatcher; } - public override Task Handle(IPlayer sender, RequestKickPlayerPacket packet) + public override async Task Handle(IPlayer sender, RequestKickPlayerPacket packet) { _logger.Information( $"Handling packet of type '{nameof(RequestKickPlayerPacket)}' " + $"(SenderId={sender.ConnectionId}, KickedPlayerId={packet.KickedPlayerId})." ); - - if (sender.CanKickVote) + await sender.PlayerAccessSemaphore.WaitAsync(); + bool CanKick = sender.CanKickVote; + sender.PlayerAccessSemaphore.Release(); + if (CanKick) if (_playerRegistry.TryGetPlayer(packet.KickedPlayerId, out var kickedPlayer)) _packetDispatcher.SendToPlayer(kickedPlayer, new KickPlayerPacket { DisconnectedReason = DisconnectedReason.Kicked }, DeliveryMethod.ReliableOrdered); - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacketHandler.cs index b62546c5..f4a8f9e1 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacketHandler.cs @@ -23,22 +23,21 @@ public SetIsEntitledToLevelPacketHandler( _playerRegistry = playerRegistry; } - public override Task Handle(IPlayer sender, SetIsEntitledToLevelPacket packet) + public override async Task Handle(IPlayer sender, SetIsEntitledToLevelPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SetIsEntitledToLevelPacket)}' " + $"(SenderId={sender.ConnectionId}, LevelId={packet.LevelId}, Entitlement={packet.Entitlement})." ); - lock (sender.EntitlementLock) + await sender.PlayerAccessSemaphore.WaitAsync(); + sender.SetEntitlement(packet.LevelId, packet.Entitlement); + foreach (IPlayer player in _playerRegistry.Players) { - sender.SetEntitlement(packet.LevelId, packet.Entitlement); - foreach (IPlayer player in _playerRegistry.Players) - { - if(player.BeatmapIdentifier != null && player.BeatmapIdentifier.LevelId == packet.LevelId) - player.UpdateEntitlement = true; - } + if(player.BeatmapIdentifier != null && player.BeatmapIdentifier.LevelId == packet.LevelId) + player.UpdateEntitlement = true; } - return Task.CompletedTask; + sender.PlayerAccessSemaphore.Release(); + return; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs index d8443e78..62ccd00f 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs @@ -5,6 +5,8 @@ using BeatTogether.LiteNetLib.Enums; using Serilog; using System; +using System.Linq; +using System.Numerics; using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -32,22 +34,24 @@ public SetIsInLobbyPacketHandler( _lobbyManager = lobbyManager; } - public override Task Handle(IPlayer sender, SetIsInLobbyPacket packet) + public override async Task Handle(IPlayer sender, SetIsInLobbyPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SetIsInLobbyPacket)}' " + $"(SenderId={sender.ConnectionId}, InLobby={packet.IsInLobby})." ); - lock (sender.InLobbyLock) + await sender.PlayerAccessSemaphore.WaitAsync(); + bool InLobby = sender.InLobby; + if (packet.IsInLobby == sender.InLobby) + return; + sender.InLobby = packet.IsInLobby; + sender.PlayerAccessSemaphore.Release(); + if (InLobby) { - if (packet.IsInLobby && !sender.InLobby) + _packetDispatcher.SendToPlayer(sender, new SetIsStartButtonEnabledPacket { - _packetDispatcher.SendToPlayer(sender, new SetIsStartButtonEnabledPacket - { - Reason = CannotStartGameReason.NoSongSelected - }, DeliveryMethod.ReliableOrdered); - } - sender.InLobby = packet.IsInLobby; + Reason = sender.IsServerOwner ? _lobbyManager.GetCannotStartGameReason(sender, _lobbyManager.DoesEveryoneOwnBeatmap) : CannotStartGameReason.None + }, DeliveryMethod.ReliableOrdered); if (_lobbyManager.SelectedBeatmap is null) _packetDispatcher.SendToPlayer(sender, new ClearSelectedBeatmap(), DeliveryMethod.ReliableOrdered); @@ -65,7 +69,7 @@ public override Task Handle(IPlayer sender, SetIsInLobbyPacket packet) Modifiers = _lobbyManager.SelectedModifiers }, DeliveryMethod.ReliableOrdered); } - return Task.CompletedTask; + return; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs index 24635f67..eaa8a1ec 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs @@ -29,27 +29,25 @@ public SetIsReadyPacketHandler( _packetDispatcher = packetDispatcher; } - public override Task Handle(IPlayer sender, SetIsReadyPacket packet) + public override async Task Handle(IPlayer sender, SetIsReadyPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SetIsReadyPacket)}' " + $"(SenderId={sender.ConnectionId}, IsReady={packet.IsReady})." ); - lock (sender.ReadyLock) - { - sender.IsReady = packet.IsReady; - //If the player somehow is in the lobby during gameplay then readying should send them to spectate - if (sender.IsReady && _instance.State == MultiplayerGameState.Game && _gameplayManager.CurrentBeatmap != null && _gameplayManager.State == GameplayManagerState.Gameplay) + bool SendToSpectate = false; + await sender.PlayerAccessSemaphore.WaitAsync(); + sender.IsReady = packet.IsReady; + //If the player somehow is in the lobby during gameplay then readying should send them to spectate + SendToSpectate = sender.IsReady && _instance.State == MultiplayerGameState.Game && _gameplayManager.CurrentBeatmap != null && _gameplayManager.State == GameplayManagerState.Gameplay; + sender.PlayerAccessSemaphore.Release(); + if (SendToSpectate) + _packetDispatcher.SendToPlayer(sender, new StartLevelPacket { - _packetDispatcher.SendToPlayer(sender, new StartLevelPacket - { - Beatmap = _gameplayManager.CurrentBeatmap!, - Modifiers = _gameplayManager.CurrentModifiers, - StartTime = _instance.RunTime - }, DeliveryMethod.ReliableOrdered); - } - } - return Task.CompletedTask; + Beatmap = _gameplayManager.CurrentBeatmap!, + Modifiers = _gameplayManager.CurrentModifiers, + StartTime = _instance.RunTime + }, DeliveryMethod.ReliableOrdered); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs index 07a454ab..be1a181a 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs @@ -24,28 +24,32 @@ public SetRecommendedBeatmapPacketHandler( _playerRegistry = playerRegistry; } - public override Task Handle(IPlayer sender, SetRecommendedBeatmapPacket packet) + public override async Task Handle(IPlayer sender, SetRecommendedBeatmapPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SetRecommendedBeatmapPacket)}' " + $"(SenderId={sender.ConnectionId}, LevelId={packet.BeatmapIdentifier.LevelId}, Difficulty={packet.BeatmapIdentifier.Difficulty})." ); - lock (sender.BeatmapLock) - { - if (sender.CanRecommendBeatmaps) - { - sender.BeatmapIdentifier = packet.BeatmapIdentifier; - if (sender.BeatmapIdentifier.LevelId != sender.MapHash) - sender.ResetRecommendedMapRequirements(); - _packetDispatcher.SendToNearbyPlayers(new GetIsEntitledToLevelPacket - { - LevelId = packet.BeatmapIdentifier.LevelId - }, DeliveryMethod.ReliableOrdered); - sender.UpdateEntitlement = true; - } + bool GetEntitlementFromOtherPlayers = false; + await sender.PlayerAccessSemaphore.WaitAsync(); + if (sender.CanRecommendBeatmaps) + { + sender.BeatmapIdentifier = packet.BeatmapIdentifier; + if (sender.BeatmapIdentifier.LevelId != sender.MapHash) + sender.ResetRecommendedMapRequirements(); + GetEntitlementFromOtherPlayers = true; + sender.UpdateEntitlement = true; } - return Task.CompletedTask; + sender.PlayerAccessSemaphore.Release(); + if (GetEntitlementFromOtherPlayers) + { + _packetDispatcher.SendToNearbyPlayers(new GetIsEntitledToLevelPacket + { + LevelId = packet.BeatmapIdentifier.LevelId + }, DeliveryMethod.ReliableOrdered); + } + return; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacketHandler.cs index 1a3d87d7..3d754382 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacketHandler.cs @@ -21,18 +21,17 @@ public SetRecommendedModifiersPacketHandler( _lobbyManager = lobbyManager; } - public override Task Handle(IPlayer sender, SetRecommendedModifiersPacket packet) + public override async Task Handle(IPlayer sender, SetRecommendedModifiersPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SetRecommendedModifiersPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - lock (sender.ModifiersLock) - { - if (sender.CanRecommendModifiers) - sender.Modifiers = packet.Modifiers; - } - return Task.CompletedTask; + await sender.PlayerAccessSemaphore.WaitAsync(); + if (sender.CanRecommendModifiers) + sender.Modifiers = packet.Modifiers; + sender.PlayerAccessSemaphore.Release(); + return; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs index 5a3ab27f..38610279 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs @@ -27,35 +27,32 @@ public DediPacketSetNewManagerPacketHandler( _configuration = configuration; } - object handleLock = new(); public override Task Handle(IPlayer sender, DediPacketSetNewManagerPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(DediPacketSetNewManagerPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - lock (handleLock) + + if (sender.IsServerOwner && _configuration.GameplayServerMode == Enums.GameplayServerMode.Managed) { - if (sender.IsServerOwner && _configuration.GameplayServerMode == Enums.GameplayServerMode.Managed) - { - _configuration.ServerOwnerId = packet.NewManagerID; + _configuration.ServerOwnerId = packet.NewManagerID; - _packetDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket + _packetDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket + { + PermissionConfiguration = new PlayersPermissionConfiguration { - PermissionConfiguration = new PlayersPermissionConfiguration + PlayersPermission = _playerRegistry.Players.Select(x => new PlayerPermissionConfiguration { - PlayersPermission = _playerRegistry.Players.Select(x => new PlayerPermissionConfiguration - { - UserId = x.UserId, - IsServerOwner = x.IsServerOwner, - HasRecommendBeatmapsPermission = x.CanRecommendBeatmaps, - HasRecommendGameplayModifiersPermission = x.CanRecommendModifiers, - HasKickVotePermission = x.CanKickVote, - HasInvitePermission = x.CanInvite - }).ToArray() - } - }, DeliveryMethod.ReliableOrdered); - } + UserId = x.UserId, + IsServerOwner = x.IsServerOwner, + HasRecommendBeatmapsPermission = x.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = x.CanRecommendModifiers, + HasKickVotePermission = x.CanKickVote, + HasInvitePermission = x.CanInvite + }).ToArray() + } + }, DeliveryMethod.ReliableOrdered); } return Task.CompletedTask; } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs index 5d7c348f..d4decb03 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs @@ -25,6 +25,7 @@ public override Task Handle(IPlayer sender, MpPlayerData packet) { _PacketDispatcher.SendFromPlayerToPlayer(Player, sender, new MpPlayerData() { + PlatformID = Player.PlatformUserId, Platform = (byte)Player.Platform, ClientVersion = Player.ClientVersion }, DeliveryMethod.ReliableOrdered); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerAvatarPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerAvatarPacketHandler.cs new file mode 100644 index 00000000..480e4ad9 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerAvatarPacketHandler.cs @@ -0,0 +1,34 @@ +using System.Threading.Tasks; +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Packets; +using Serilog; + +namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers +{ + public sealed class PlayerAvatarPacketHandler : BasePacketHandler + { + private readonly IPacketDispatcher _packetDispatcher; + private readonly IDedicatedInstance _instance; + private readonly ILogger _logger = Log.ForContext(); + + public PlayerAvatarPacketHandler( + IPacketDispatcher packetDispatcher, IDedicatedInstance instance) + { + _packetDispatcher = packetDispatcher; + _instance = instance; + } + + public override async Task Handle(IPlayer sender, PlayerAvatarPacket packet) + { + _logger.Debug( + $"Handling packet of type '{nameof(PlayerAvatarPacket)}' " + + $"(SenderId={sender.ConnectionId})." + ); + await sender.PlayerAccessSemaphore.WaitAsync(); + sender.Avatar = packet.PlayerAvatar; + if (!sender.PlayerInitialised.Task.IsCompleted) + sender.PlayerInitialised.SetResult(); + sender.PlayerAccessSemaphore.Release(); + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs index df8bfd15..dc5c4d0b 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers @@ -20,21 +19,20 @@ public PlayerIdentityPacketHandler( _instance = instance; } - public override Task Handle(IPlayer sender, PlayerIdentityPacket packet) + public override async Task Handle(IPlayer sender, PlayerIdentityPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(PlayerIdentityPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - lock (sender.PlayerIdentityLock) - { - sender.Avatar = packet.PlayerAvatar; - sender.State = packet.PlayerState; - sender.Random = packet.Random.Data ?? Array.Empty(); - sender.PublicEncryptionKey = packet.PublicEncryptionKey.Data ?? Array.Empty(); - _packetDispatcher.SendFromPlayer(sender, packet, DeliveryMethod.ReliableOrdered); - } - return Task.CompletedTask; + await sender.PlayerAccessSemaphore.WaitAsync(); + sender.Avatar = packet.PlayerAvatar; + sender.State = packet.PlayerState; + sender.Random = packet.Random.Data ?? Array.Empty(); + sender.PublicEncryptionKey = packet.PublicEncryptionKey.Data ?? Array.Empty(); + if (!sender.PlayerInitialised.Task.IsCompleted) + sender.PlayerInitialised.SetResult(); + sender.PlayerAccessSemaphore.Release(); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs index 4bebf942..9b825191 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs @@ -17,22 +17,21 @@ public PlayerLatencyPacketHandler( _packetDispatcher = packetDispatcher; } - public override Task Handle(IPlayer sender, PlayerLatencyPacket packet) + public override async Task Handle(IPlayer sender, PlayerLatencyPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SyncTimePacket)}' " + $"(SenderId={sender.ConnectionId}, SyncTime={packet.Latency})." ); - lock (sender.LatencyLock) + await sender.PlayerAccessSemaphore.WaitAsync(); + sender.Latency.Update(packet.Latency); + sender.PlayerAccessSemaphore.Release(); + _packetDispatcher.SendFromPlayer(sender, new PlayerLatencyPacket { - sender.Latency.Update(packet.Latency); - _packetDispatcher.SendFromPlayer(sender, new PlayerLatencyPacket - { - Latency = sender.Latency.CurrentAverage - }, DeliveryMethod.ReliableOrdered); - } - return Task.CompletedTask; + Latency = sender.Latency.CurrentAverage + }, DeliveryMethod.ReliableOrdered); + return; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs index d30c7f7b..f9519424 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs @@ -16,22 +16,20 @@ public PlayerSortOrderPacketHandler(IPacketDispatcher packetDispatcher) _packetDispatcher = packetDispatcher; } - public override Task Handle(IPlayer sender, PlayerSortOrderPacket packet) + public override async Task Handle(IPlayer sender, PlayerSortOrderPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(PlayerSortOrderPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - - lock (sender.SortLock) - { - if (sender.UserId == packet.UserId && sender.SortIndex != packet.SortIndex) + await sender.PlayerAccessSemaphore.WaitAsync(); + if (sender.UserId == packet.UserId && sender.SortIndex != packet.SortIndex) //If they send themselves as being in the wrong place, correct them. Although this probably shouldnt have a handler { - sender.SortIndex = packet.SortIndex; - _packetDispatcher.SendExcludingPlayer(sender, packet, DeliveryMethod.ReliableOrdered); + packet.SortIndex = sender.SortIndex; + _packetDispatcher.SendToPlayer(sender, packet, DeliveryMethod.ReliableOrdered); } - } - return Task.CompletedTask; + sender.PlayerAccessSemaphore.Release(); + return; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs index 8938e6f5..7b3b18d0 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs @@ -9,18 +9,20 @@ public sealed class PlayerStatePacketHandler : BasePacketHandler(); - public override Task Handle(IPlayer sender, PlayerStatePacket packet) + public override async Task Handle(IPlayer sender, PlayerStatePacket packet) { _logger.Debug( $"Handling packet of type '{nameof(PlayerStatePacket)}' " + - $"(SenderId={sender.ConnectionId}, IsPlayer={packet.PlayerState.Contains("player")}, IsModded={packet.PlayerState.Contains("modded")}, " + - $"IsActive={packet.PlayerState.Contains("is_active")}, WantsToPlayNextLevel={packet.PlayerState.Contains("wants_to_play_next_level")})." + $"(SenderId={sender.ConnectionId}, IsPlayer={packet.PlayerState.Contains("player")}" + + $"IsActive={packet.PlayerState.Contains("is_active")}, WantsToPlayNextLevel={packet.PlayerState.Contains("wants_to_play_next_level")}" + + $"IsSpectating={packet.PlayerState.Contains("spectating")}, InMenu={packet.PlayerState.Contains("in_menu")}" + + $"backgrounded={packet.PlayerState.Contains("backgrounded")}, in_gameplay={packet.PlayerState.Contains("in_gameplay")}" + + $"was_active_at_level_start={packet.PlayerState.Contains("was_active_at_level_start")}, finished_level={packet.PlayerState.Contains("finished_level")})." ); - lock (sender.StateLock) - { - sender.State = packet.PlayerState; - } - return Task.CompletedTask; + await sender.PlayerAccessSemaphore.WaitAsync(); + sender.State = packet.PlayerState; + sender.PlayerAccessSemaphore.Release(); + return; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index 420105e6..76a0d17f 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -1,9 +1,8 @@ using System; -using System.Diagnostics; using System.Net; +using System.Reflection.Emit; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; -using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; using BeatTogether.DedicatedServer.Messaging.Registries; @@ -76,11 +75,11 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D { uint length; try { length = HandleRead.ReadVarUInt(); } - catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); return; } + catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); goto RoutePacket; } if (HandleRead.RemainingSize < length) { _logger.Warning($"Packet fragmented (RemainingSize={HandleRead.RemainingSize}, Expected={length})."); - return; + goto RoutePacket; } int prevPosition = HandleRead.Offset; @@ -93,7 +92,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D byte packetId; try { packetId = HandleRead.ReadByte(); } - catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); return; } + catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); goto RoutePacket; } if (packetRegistry.TryCreatePacket(packetId, out packet)) break; if (packetRegistry.TryGetSubPacketRegistry(packetId, out var subPacketRegistry)) @@ -107,19 +106,18 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D string MPCpacketId; try { MPCpacketId = HandleRead.ReadString(); } - catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); return; } + catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); goto RoutePacket; } if (MPCoreRegistry.TryCreatePacket(MPCpacketId, out packet)) break; } break; } - //TODO disable join message config packet if (packet == null) { // skip any unprocessed bytes var processedBytes = HandleRead.Offset - prevPosition; try { HandleRead.SkipBytes((int)length - processedBytes); } - catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); return; } + catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); goto RoutePacket; } continue; } if(packet is NoteSpawnPacket || packet is ObstacleSpawnPacket || packet is SliderSpawnPacket) //Note packet logic @@ -157,7 +155,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D // skip any unprocessed bytes var processedBytes = HandleRead.Offset - prevPosition; try { HandleRead.SkipBytes((int)length - processedBytes); } - catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); return; } + catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); goto RoutePacket; } continue; } @@ -169,13 +167,14 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D { // skip any unprocessed bytes var processedBytes = HandleRead.Offset - prevPosition; - HandleRead.SkipBytes((int)length - processedBytes); + try { HandleRead.SkipBytes((int)length - processedBytes); } + catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); goto RoutePacket; } continue; } ((Abstractions.IPacketHandler)packetHandler).Handle(sender, packet); } - + RoutePacket: //Is this packet meant to be routed? if (routingHeader.ReceiverId != 0) RoutePacket(sender, routingHeader, ref reader, method); diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index d11f628c..36f28c10 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Concurrent; using System.Net; +using System.Threading; +using System.Threading.Tasks; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Types; @@ -11,6 +13,8 @@ namespace BeatTogether.DedicatedServer.Kernel { public sealed class Player : IPlayer { + public SemaphoreSlim PlayerAccessSemaphore { get; set; } = new(1); + public TaskCompletionSource PlayerInitialised { get; set; } = new(); public EndPoint Endpoint { get; } public IDedicatedInstance Instance { get; } public byte ConnectionId { get; } @@ -19,48 +23,40 @@ public sealed class Player : IPlayer public string UserId { get; } public string UserName { get; } public string? PlayerSessionId { get; } - public object LatencyLock { get; set; } = new(); public RollingAverage Latency { get; } = new(30); public float SyncTime => Math.Min(Instance.RunTime - Latency.CurrentAverage - _syncTimeOffset, Instance.RunTime); - public object SortLock { get; set; } = new(); public int SortIndex { get; set; } public byte[]? Random { get; set; } public byte[]? PublicEncryptionKey { get; set; } public string ClientVersion { get; set; } = "Pre-1.29"; public Platform Platform { get; set; } = Platform.Test; //Unknown public string PlatformUserId { get; set; } = ""; - public object PlayerIdentityLock { get; set; } = new(); public AvatarData Avatar { get; set; } = new(); - public object ReadyLock { get; set; } = new(); public bool IsReady { get; set; } - public object InLobbyLock { get; set; } = new(); public bool InLobby { get; set; } - public object BeatmapLock { get; set; } = new(); public BeatmapIdentifier? BeatmapIdentifier { get; set; } = null; - public object ModifiersLock { get; set; } = new(); public GameplayModifiers Modifiers { get; set; } = new(); - public object StateLock { get; set; } = new(); public PlayerStateHash State { get; set; } = new(); public bool IsServerOwner => UserId == Instance._configuration.ServerOwnerId; - public bool CanRecommendBeatmaps => true; + public bool CanRecommendBeatmaps => Instance._configuration.GameplayServerControlSettings is not GameplayServerControlSettings.None; public bool CanRecommendModifiers => - Instance._configuration.GameplayServerControlSettings is Enums.GameplayServerControlSettings.AllowModifierSelection or Enums.GameplayServerControlSettings.All; + Instance._configuration.GameplayServerControlSettings is GameplayServerControlSettings.AllowModifierSelection or GameplayServerControlSettings.All; public bool CanKickVote => UserId == Instance._configuration.ServerOwnerId; public bool CanInvite => - Instance._configuration.DiscoveryPolicy is Enums.DiscoveryPolicy.WithCode or Enums.DiscoveryPolicy.Public; + Instance._configuration.DiscoveryPolicy is DiscoveryPolicy.WithCode or DiscoveryPolicy.Public; public bool IsPlayer => State.Contains("player"); - public bool IsSpectating => State.Contains("spectating"); - public bool WantsToPlayNextLevel => State.Contains("wants_to_play_next_level"); - public bool IsBackgrounded => State.Contains("backgrounded"); - public bool InGameplay => State.Contains("in_gameplay"); - public bool WasActiveAtLevelStart => State.Contains("was_active_at_level_start"); - public bool IsActive => State.Contains("is_active"); - public bool FinishedLevel => State.Contains("finished_level"); - public bool InMenu => State.Contains("in_menu"); + public bool IsSpectating => State.Contains("spectating"); //True if spectating players in gameplay + public bool WantsToPlayNextLevel => State.Contains("wants_to_play_next_level"); //True if spectating is toggled in menu + public bool IsBackgrounded => State.Contains("backgrounded"); //No idea + public bool InGameplay => State.Contains("in_gameplay"); //True while in gameplay + public bool WasActiveAtLevelStart => State.Contains("was_active_at_level_start"); //True if the player was active at the level start - need to check if it means they are a spectator or not + public bool IsActive => State.Contains("is_active"); //No idea, i suppose its the opposite of IsBackgrounded + public bool FinishedLevel => State.Contains("finished_level"); //If the player has finished the level + public bool InMenu => State.Contains("in_menu"); //Should be true while in lobby private const float _syncTimeOffset = 0.06f; private ConcurrentDictionary _entitlements = new(); @@ -99,7 +95,6 @@ public void SetAccessLevel(AccessLevel newLevel) _AccessLevel = newLevel; } - public object EntitlementLock { get; set; } = new(); public EntitlementStatus GetEntitlement(string levelId) => _entitlements.TryGetValue(levelId, out var value) ? value : EntitlementStatus.Unknown; diff --git a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj index 05bbd13a..f9de374d 100644 --- a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj +++ b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj @@ -9,7 +9,7 @@ - + diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs index dd2a45ed..3d93a80a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs @@ -71,5 +71,56 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteBool(IsConnectionOwner); } } + + public void ReadFrom(ref MemoryBuffer reader) + { + Secret = null; + PlayerSessionId = null; + + var initialOffset = reader.Offset; + + // Try to read as a GameLift connection request + try + { + UserId = reader.ReadString(); + UserName = reader.ReadString(); + IsConnectionOwner = reader.ReadBool(); + PlayerSessionId = reader.ReadString(); + } + catch (EndOfBufferException) { } + + if (PlayerSessionId != null && PlayerSessionId.StartsWith(SessionIdPrefix)) + // Read OK, valid session identifier + return; + + // Rewind, try to read as basic request + reader.SkipBytes(initialOffset - reader.Offset); + + Secret = reader.ReadString(); + UserId = reader.ReadString(); + UserName = reader.ReadString(); + IsConnectionOwner = reader.ReadBool(); + PlayerSessionId = null; + } + + public void WriteTo(ref MemoryBuffer writer) + { + if (!string.IsNullOrEmpty(PlayerSessionId)) + { + // GameLift + writer.WriteString(UserId); + writer.WriteString(UserName); + writer.WriteBool(IsConnectionOwner); + writer.WriteString(PlayerSessionId); + } + else + { + // Basic + writer.WriteString(Secret ?? ""); + writer.WriteString(UserId); + writer.WriteString(UserName); + writer.WriteBool(IsConnectionOwner); + } + } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerAvatarPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerAvatarPacket.cs new file mode 100644 index 00000000..b4fe697a --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerAvatarPacket.cs @@ -0,0 +1,21 @@ +using BeatTogether.DedicatedServer.Messaging.Models; +using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets +{ + public sealed class PlayerAvatarPacket : INetSerializable + { + public AvatarData PlayerAvatar { get; set; } = new(); + + public void ReadFrom(ref SpanBuffer reader) + { + PlayerAvatar.ReadFrom(ref reader); + } + + public void WriteTo(ref SpanBuffer writer) + { + PlayerAvatar.WriteTo(ref writer); + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/PacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/PacketRegistry.cs index 796bc499..110e878a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/PacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/PacketRegistry.cs @@ -14,6 +14,7 @@ public override void Register() AddPacket(PacketType.PlayerLatencyUpdate); AddPacket(PacketType.PlayerDisconnected); AddPacket(PacketType.PlayerSortOrderUpdate); + AddPacket(PacketType.PlayerAvatarUpdate); AddPacket(PacketType.KickPlayer); AddPacket(PacketType.PlayerStateUpdate); AddSubPacketRegistry(PacketType.MultiplayerSession); From 0d52e3df14a7b49bb4087198bff3c3731d9a14ce Mon Sep 17 00:00:00 2001 From: cubic Date: Wed, 17 May 2023 02:42:56 +0100 Subject: [PATCH 014/120] Better player join handling --- .../DedicatedInstance.cs | 284 +++++++++++------- .../Managers/LobbyManager.cs | 3 + ...ersPermissionConfigurationPacketHandler.cs | 32 +- .../MenuRpc/RequestKickPlayerPacketHandler.cs | 2 +- .../MenuRpc/SetIsInLobbyPacketHandler.cs | 3 + .../PlayerSortOrderPacketHandler.cs | 11 +- .../PacketSource.cs | 1 - ...tTogether.DedicatedServer.Messaging.csproj | 2 +- .../Models/ConnectionRequestData.cs | 55 +--- 9 files changed, 217 insertions(+), 176 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index accd5e0a..1186fed5 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -251,7 +251,7 @@ public void SetState(MultiplayerGameState state) #region LiteNetServer - public override async Task ShouldAcceptConnection(EndPoint endPoint, MemoryBuffer additionalData) + public override async Task ShouldAcceptConnection(EndPoint endPoint, byte[] additionalData) { if (await ShouldDenyConnection(endPoint, additionalData)) @@ -262,22 +262,37 @@ public override async Task ShouldAcceptConnection(EndPoint endPoint, Memor } return true; } - public async Task ShouldDenyConnection(EndPoint endPoint, MemoryBuffer additionalData) + + private bool GetConnectionData(byte[] additionalData, out ConnectionRequestData connectionRequestData) { - var connectionRequestData = new ConnectionRequestData(); + connectionRequestData = new(); + SpanBuffer spanBuffer = new(additionalData); try { - connectionRequestData.ReadFrom(ref additionalData); + connectionRequestData.ReadFrom(ref spanBuffer); + } + catch(Exception ex) + { + _logger.Warning(ex + + "Failed to deserialize connection request data" + ); + return false; } - catch (Exception e) + return true; + } + + + public async Task ShouldDenyConnection(EndPoint endPoint, byte[] additionalData) + { + //var connectionRequestData = new ConnectionRequestData(); + if(!GetConnectionData(additionalData, out var connectionRequestData)) { - _logger.Warning(e, + _logger.Warning( "Failed to deserialize connection request data " + $"(RemoteEndPoint='{endPoint}')." ); return true; } - _logger.Debug( "Handling connection request " + $"(RemoteEndPoint='{endPoint}', " + @@ -301,11 +316,13 @@ public async Task ShouldDenyConnection(EndPoint endPoint, MemoryBuffer add await ConnectDisconnectSemaphore.WaitAsync(); if (_playerRegistry.GetPlayerCount() >= _configuration.MaxPlayerCount) { + ConnectDisconnectSemaphore.Release(); _logger.Warning("Master server sent a player to a full server"); return true; } if (connectionRequestData.UserName == "IGGAMES" || connectionRequestData.UserName == "IGGGAMES") { + ConnectDisconnectSemaphore.Release(); _logger.Information("an IGG player just tried joining after passing master auth"); return true; } @@ -328,6 +345,7 @@ public async Task ShouldDenyConnection(EndPoint endPoint, MemoryBuffer add { ReleaseSortIndex(player.SortIndex); ReleaseConnectionId(player.ConnectionId); + ConnectDisconnectSemaphore.Release(); return true; } @@ -366,7 +384,39 @@ public async Task ShouldDenyConnection(EndPoint endPoint, MemoryBuffer add handshakeSession.EncryptionParameters, true); } } + ConnectDisconnectSemaphore.Release(); + //Send to all other players that they are connected, before sending to the new player that they have connected + await player.PlayerAccessSemaphore.WaitAsync(); + var SendToOtherPlayers = new INetSerializable[] + { + new SyncTimePacket + { + SyncTime = RunTime + }, + new PlayerConnectedPacket + { + RemoteConnectionId = player.ConnectionId, + UserId = player.UserId, + UserName = player.UserName, + IsConnectionOwner = false + }, + new PlayerSortOrderPacket + { + UserId = player.UserId, + SortIndex = player.SortIndex + }, + new MpNodePoseSyncStatePacket + { + fullStateUpdateFrequency = 0.1f, + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f + }, + }; + player.PlayerAccessSemaphore.Release(); + + _packetDispatcher.SendExcludingPlayer(player, SendToOtherPlayers, DeliveryMethod.ReliableOrdered); + + return false; } public override void OnLatencyUpdate(EndPoint endPoint, int latency) @@ -387,12 +437,15 @@ public override async void OnConnect(EndPoint endPoint) Disconnect(endPoint); return; } - await ConnectDisconnectSemaphore.WaitAsync(); + PlayerConnectedEvent?.Invoke(player); + await Task.Delay(50); + //The player has already been sent to every other player in the should connect function. + //Start of sending other players to player + //Now send all players already in the game to the new player IPlayer[] PlayersAtJoin = _playerRegistry.Players; await player.PlayerAccessSemaphore.WaitAsync(); - var Player_ConnectPacket = new INetSerializable[] { new SyncTimePacket @@ -414,138 +467,156 @@ public override async void OnConnect(EndPoint endPoint) new SetIsStartButtonEnabledPacket// Disables start button if they are server owner without selected song { Reason = player.UserId == _configuration.ServerOwnerId ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None - } + }, + new MpNodePoseSyncStatePacket + { + fullStateUpdateFrequency = 0.1f, + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f + }, }; - - var SendToOtherPlayers = new INetSerializable[] - { - new SyncTimePacket - { - SyncTime = RunTime - }, - new PlayerConnectedPacket - { - RemoteConnectionId = player.ConnectionId, - UserId = player.UserId, - UserName = player.UserName, - IsConnectionOwner = false - }, - new PlayerSortOrderPacket - { - UserId = player.UserId, - SortIndex = player.SortIndex - }, - }; player.PlayerAccessSemaphore.Release(); - _packetDispatcher.SendToPlayer(player, Player_ConnectPacket, DeliveryMethod.ReliableOrdered); - //Sends to all players that they have connected - await _packetDispatcher.SendExcludingPlayerAndAwait(player, SendToOtherPlayers, DeliveryMethod.ReliableOrdered).WaitAsync(TimeSpan.FromMilliseconds(100)); - INetSerializable[] SendToPlayer; - INetSerializable[] SendToPlayerFromPlayers; - Task[] ConnectionTasks = new Task[2]; + await _packetDispatcher.SendToPlayerAndAwait(player, Player_ConnectPacket, DeliveryMethod.ReliableOrdered); + + List MakeBigPacketToSendToPlayer = new(); foreach (IPlayer p in PlayersAtJoin) { - if (p.ConnectionId != player.ConnectionId) + if(p.ConnectionId != player.ConnectionId) { - // Send all player connection data packets to new player - if (!p.PlayerInitialised.Task.IsCompleted) - await p.PlayerInitialised.Task.WaitAsync(TimeSpan.FromMilliseconds(200)); //awaits the player connecting await p.PlayerAccessSemaphore.WaitAsync(); - SendToPlayer = new INetSerializable[]{ - new PlayerConnectedPacket - { - RemoteConnectionId = p.ConnectionId, - UserId = p.UserId, - UserName = p.UserName, - IsConnectionOwner = false - }, - new PlayerSortOrderPacket - { - UserId = p.UserId, - SortIndex = p.SortIndex - } - }; - SendToPlayerFromPlayers = new INetSerializable[] + MakeBigPacketToSendToPlayer.Add(new PlayerConnectedPacket { - new PlayerAvatarPacket - { - PlayerAvatar = p.Avatar - }, - new PlayerStatePacket - { - PlayerState = p.State - }, - new MpPlayerData - { - PlatformID = p.PlatformUserId!, - Platform = (byte)p.Platform, - ClientVersion = p.ClientVersion! - } - }; + RemoteConnectionId = p.ConnectionId, + UserId = p.UserId, + UserName = p.UserName, + IsConnectionOwner = false + }); + MakeBigPacketToSendToPlayer.Add(new PlayerSortOrderPacket + { + UserId = p.UserId, + SortIndex = p.SortIndex + }); p.PlayerAccessSemaphore.Release(); - ConnectionTasks[0] = _packetDispatcher.SendToPlayerAndAwait(player, SendToPlayer, DeliveryMethod.ReliableOrdered); - - // Send all player avatars and states to just joined player - ConnectionTasks[1] = _packetDispatcher.SendFromPlayerToPlayerAndAwait(p, player, SendToPlayerFromPlayers, DeliveryMethod.ReliableOrdered); - await Task.WhenAll(ConnectionTasks).WaitAsync(TimeSpan.FromMilliseconds(100)); } } + foreach (var SubPacket in MakeBigPacketToSendToPlayer.Chunk(20)) + { + await _packetDispatcher.SendToPlayerAndAwait(player, SubPacket.ToArray(), DeliveryMethod.ReliableOrdered); + } + //End of sending other players to player + // Update permissions - constant manager possibly does not work if ((_configuration.SetConstantManagerFromUserId == player.UserId || _playerRegistry.GetPlayerCount() == 1) && _configuration.GameplayServerMode == GameplayServerMode.Managed) { _configuration.ServerOwnerId = player.UserId; + _packetDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket //Sends updated value to all players.//TODO Make a function for updating players permissions as there will be commands for it soon + { + PermissionConfiguration = new PlayersPermissionConfiguration + { + PlayersPermission = new PlayerPermissionConfiguration[] + { + new PlayerPermissionConfiguration() + { + UserId = player.UserId, + IsServerOwner = player.IsServerOwner, + HasRecommendBeatmapsPermission = player.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = player.CanRecommendModifiers, + HasKickVotePermission = player.CanKickVote, + HasInvitePermission = player.CanInvite + } + } + } + }, DeliveryMethod.ReliableOrdered); } - //Send remaining join packets - ConnectionTasks = new Task[4]; - foreach (IPlayer p in PlayersAtJoin) + if (player.Platform == Platform.Test) //If the player is a bot, send permissions. Normal players request this in a packet when they join { - ConnectionTasks[0] = _packetDispatcher.SendToPlayerAndAwait(p,new SetPlayersPermissionConfigurationPacket + bool HasManager = (_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var ServerOwner) && !player.IsServerOwner); + PlayerPermissionConfiguration[] playerPermissionConfigurations = new PlayerPermissionConfiguration[HasManager ? 2 : 1]; + playerPermissionConfigurations[0] = new PlayerPermissionConfiguration + { + UserId = player.UserId, + IsServerOwner = player.IsServerOwner, + HasRecommendBeatmapsPermission = player.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = player.CanRecommendModifiers, + HasKickVotePermission = player.CanKickVote, + HasInvitePermission = player.CanInvite + }; + if (HasManager) + playerPermissionConfigurations[1] = new PlayerPermissionConfiguration + { + UserId = ServerOwner!.UserId, + IsServerOwner = ServerOwner!.IsServerOwner, + HasRecommendBeatmapsPermission = ServerOwner!.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = ServerOwner!.CanRecommendModifiers, + HasKickVotePermission = ServerOwner!.CanKickVote, + HasInvitePermission = ServerOwner!.CanInvite + }; + _packetDispatcher.SendToPlayer(player, new SetPlayersPermissionConfigurationPacket { PermissionConfiguration = new PlayersPermissionConfiguration { - PlayersPermission = PlayersAtJoin.Select(x => new PlayerPermissionConfiguration - { - UserId = x.UserId, - IsServerOwner = x.IsServerOwner, - HasRecommendBeatmapsPermission = x.CanRecommendBeatmaps, - HasRecommendGameplayModifiersPermission = x.CanRecommendModifiers, - HasKickVotePermission = x.CanKickVote, - HasInvitePermission = x.CanInvite - }).ToArray() + PlayersPermission = playerPermissionConfigurations } }, DeliveryMethod.ReliableOrdered); + } + + //Start of sending player avatars and states to new player + INetSerializable[] SendToPlayerFromPlayers = new INetSerializable[3]; + SendToPlayerFromPlayers[0] = new PlayerAvatarPacket(); + SendToPlayerFromPlayers[1] = new PlayerStatePacket(); + SendToPlayerFromPlayers[2] = new MpPlayerData(); + + foreach (IPlayer p in PlayersAtJoin) + { + if (p.ConnectionId != player.ConnectionId) + { + // Send all player connection data packets to new player + //No need to await for players to have sent avatar data or state as the client will share it with them on connect anyway + await p.PlayerAccessSemaphore.WaitAsync(); + ((PlayerAvatarPacket)SendToPlayerFromPlayers[0]).PlayerAvatar = p.Avatar; + ((PlayerStatePacket)SendToPlayerFromPlayers[1]).PlayerState = p.State; + ((MpPlayerData)SendToPlayerFromPlayers[2]).PlatformID = p.PlatformUserId; + ((MpPlayerData)SendToPlayerFromPlayers[2]).Platform = (byte)p.Platform; + ((MpPlayerData)SendToPlayerFromPlayers[2]).ClientVersion = p.ClientVersion; + p.PlayerAccessSemaphore.Release(); + // Send all player avatars and states to just joined player + await Task.WhenAny(_packetDispatcher.SendFromPlayerToPlayerAndAwait(p, player, SendToPlayerFromPlayers, DeliveryMethod.ReliableOrdered), Task.Delay(50)); + //Sends them one by one to avoid server lag + } + } + //End of sending avatars and states to new player + + foreach (IPlayer p in PlayersAtJoin) + { if (p.ConnectionId != player.ConnectionId) { - ConnectionTasks[1] = _packetDispatcher.SendFromPlayerToPlayerAndAwait(player, p, new MpPlayerData + await Task.WhenAny( + _packetDispatcher.SendFromPlayerToPlayerAndAwait(player, p, new MpPlayerData { PlatformID = player.PlatformUserId!, Platform = (byte)player.Platform, ClientVersion = player.ClientVersion! - }, DeliveryMethod.ReliableOrdered); + }, DeliveryMethod.ReliableOrdered), + Task.Delay(50)); } - else + } + + await player.PlayerAccessSemaphore.WaitAsync(); + var packet = new MpcTextChatPacket { Text = player.UserName + " Joined, Platform: " + player.Platform.ToString() + " Version: " + player.ClientVersion }; + player.PlayerAccessSemaphore.Release(); + foreach (var p in PlayersAtJoin) + { + if (p.CanTextChat) { - ConnectionTasks[1] = Task.CompletedTask; + await Task.WhenAny(_packetDispatcher.SendToPlayerAndAwait(p, packet, DeliveryMethod.ReliableOrdered), Task.Delay(50)); } - ConnectionTasks[2] = _packetDispatcher.SendToPlayerAndAwait(p, new MpNodePoseSyncStatePacket - { - fullStateUpdateFrequency = 0.1f, - deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f - }, DeliveryMethod.ReliableOrdered); - ConnectionTasks[3] = _packetDispatcher.SendToPlayerAndAwait(p, new MpcTextChatPacket() - { - Text = "Player joined: " + player.UserName + " Platform: " + player.Platform.ToString() + " Game version: " + player.ClientVersion - }, DeliveryMethod.ReliableOrdered); - await Task.WhenAll(ConnectionTasks).WaitAsync(TimeSpan.FromMilliseconds(100)); } - ConnectDisconnectSemaphore.Release(); - PlayerConnectedEvent?.Invoke(player); + } - public void DisconnectPlayer(string UserId) //Used my master server kick player event + public void DisconnectPlayer(string UserId) //Used my master servers kick player event { if(_playerRegistry.TryGetPlayer(UserId, out var player)) @@ -573,11 +644,12 @@ public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reas if (_playerRegistry.TryGetPlayer(endPoint, out var player)) { //Sends to all players that they have disconnected + _packetDispatcher.SendFromPlayer(player, new PlayerDisconnectedPacket { DisconnectedReason = DisconnectedReason.ClientConnectionClosed }, DeliveryMethod.ReliableOrdered); - + if (_configuration.ServerOwnerId == player.UserId) _configuration.ServerOwnerId = ""; diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 33acaf33..63dbb755 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -124,12 +124,15 @@ public void Update() if (player.UpdateEntitlement) { if (player.BeatmapIdentifier != null) + { _packetDispatcher.SendToPlayer(player, new SetPlayersMissingEntitlementsToLevelPacket { PlayersWithoutEntitlements = _playerRegistry.Players .Where(p => p.GetEntitlement(player.BeatmapIdentifier.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) .Select(p => p.UserId).ToArray() }, DeliveryMethod.ReliableOrdered); + _logger.Information("Sent missing entitlement packet"); + } player.UpdateEntitlement = false; } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs index f908cbbd..f6785509 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs @@ -4,7 +4,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Linq; using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -33,19 +32,32 @@ public override Task Handle(IPlayer sender, GetPlayersPermissionConfigurationPac $"(SenderId={sender.ConnectionId})." ); + bool HasManager = (_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var ServerOwner) && !sender.IsServerOwner); + PlayerPermissionConfiguration[] playerPermissionConfigurations = new PlayerPermissionConfiguration[HasManager ? 2 : 1]; + playerPermissionConfigurations[0] = new PlayerPermissionConfiguration + { + UserId = sender.UserId, + IsServerOwner = sender.IsServerOwner, + HasRecommendBeatmapsPermission = sender.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = sender.CanRecommendModifiers, + HasKickVotePermission = sender.CanKickVote, + HasInvitePermission = sender.CanInvite + }; + if (HasManager) + playerPermissionConfigurations[1] = new PlayerPermissionConfiguration + { + UserId = ServerOwner!.UserId, + IsServerOwner = ServerOwner!.IsServerOwner, + HasRecommendBeatmapsPermission = ServerOwner!.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = ServerOwner!.CanRecommendModifiers, + HasKickVotePermission = ServerOwner!.CanKickVote, + HasInvitePermission = ServerOwner!.CanInvite + }; _packetDispatcher.SendToPlayer(sender, new SetPlayersPermissionConfigurationPacket { PermissionConfiguration = new PlayersPermissionConfiguration { - PlayersPermission = _playerRegistry.Players.Select(x => new PlayerPermissionConfiguration - { - UserId = x.UserId, - IsServerOwner = x.IsServerOwner, - HasRecommendBeatmapsPermission = x.CanRecommendBeatmaps, - HasRecommendGameplayModifiersPermission = x.CanRecommendModifiers, - HasKickVotePermission = x.CanKickVote, - HasInvitePermission = x.CanInvite - }).ToArray() + PlayersPermission = playerPermissionConfigurations } }, DeliveryMethod.ReliableOrdered); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs index 9e48ca4e..c25facad 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs @@ -24,7 +24,7 @@ public RequestKickPlayerPacketHandler( public override async Task Handle(IPlayer sender, RequestKickPlayerPacket packet) { - _logger.Information( + _logger.Debug( $"Handling packet of type '{nameof(RequestKickPlayerPacket)}' " + $"(SenderId={sender.ConnectionId}, KickedPlayerId={packet.KickedPlayerId})." ); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs index 62ccd00f..737f9bf3 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs @@ -43,7 +43,10 @@ public override async Task Handle(IPlayer sender, SetIsInLobbyPacket packet) await sender.PlayerAccessSemaphore.WaitAsync(); bool InLobby = sender.InLobby; if (packet.IsInLobby == sender.InLobby) + { + sender.PlayerAccessSemaphore.Release(); return; + } sender.InLobby = packet.IsInLobby; sender.PlayerAccessSemaphore.Release(); if (InLobby) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs index f9519424..fbe4d865 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs @@ -22,13 +22,16 @@ public override async Task Handle(IPlayer sender, PlayerSortOrderPacket packet) $"Handling packet of type '{nameof(PlayerSortOrderPacket)}' " + $"(SenderId={sender.ConnectionId})." ); + bool Send = false; await sender.PlayerAccessSemaphore.WaitAsync(); if (sender.UserId == packet.UserId && sender.SortIndex != packet.SortIndex) //If they send themselves as being in the wrong place, correct them. Although this probably shouldnt have a handler - { - packet.SortIndex = sender.SortIndex; - _packetDispatcher.SendToPlayer(sender, packet, DeliveryMethod.ReliableOrdered); - } + { + packet.SortIndex = sender.SortIndex; + Send = true; + } sender.PlayerAccessSemaphore.Release(); + if(Send) + _packetDispatcher.SendToPlayer(sender, packet, DeliveryMethod.ReliableOrdered); return; } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index 76a0d17f..8154f71a 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -1,6 +1,5 @@ using System; using System.Net; -using System.Reflection.Emit; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession; diff --git a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj index f9de374d..754dba28 100644 --- a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj +++ b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj @@ -9,7 +9,7 @@ - + diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs index 3d93a80a..2d3aaf9e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs @@ -43,8 +43,8 @@ public void ReadFrom(ref SpanBuffer reader) return; // Rewind, try to read as basic request - reader.SkipBytes(initialOffset - reader.Offset); - + //reader.SkipBytes(initialOffset - reader.Offset); + reader.SetOffset(initialOffset); Secret = reader.ReadString(); UserId = reader.ReadString(); UserName = reader.ReadString(); @@ -71,56 +71,5 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteBool(IsConnectionOwner); } } - - public void ReadFrom(ref MemoryBuffer reader) - { - Secret = null; - PlayerSessionId = null; - - var initialOffset = reader.Offset; - - // Try to read as a GameLift connection request - try - { - UserId = reader.ReadString(); - UserName = reader.ReadString(); - IsConnectionOwner = reader.ReadBool(); - PlayerSessionId = reader.ReadString(); - } - catch (EndOfBufferException) { } - - if (PlayerSessionId != null && PlayerSessionId.StartsWith(SessionIdPrefix)) - // Read OK, valid session identifier - return; - - // Rewind, try to read as basic request - reader.SkipBytes(initialOffset - reader.Offset); - - Secret = reader.ReadString(); - UserId = reader.ReadString(); - UserName = reader.ReadString(); - IsConnectionOwner = reader.ReadBool(); - PlayerSessionId = null; - } - - public void WriteTo(ref MemoryBuffer writer) - { - if (!string.IsNullOrEmpty(PlayerSessionId)) - { - // GameLift - writer.WriteString(UserId); - writer.WriteString(UserName); - writer.WriteBool(IsConnectionOwner); - writer.WriteString(PlayerSessionId); - } - else - { - // Basic - writer.WriteString(Secret ?? ""); - writer.WriteString(UserId); - writer.WriteString(UserName); - writer.WriteBool(IsConnectionOwner); - } - } } } From 64e9836b106e99a0a7de2c3c6c1f4a013e7fd687 Mon Sep 17 00:00:00 2001 From: cubic Date: Sat, 20 May 2023 20:56:45 +0100 Subject: [PATCH 015/120] Added mpc voice chat packet for testing purposes --- .../DedicatedInstance.cs | 9 ++------- .../MPChatPackets/MpcVoicePacket.cs | 18 ++++++++++++++++++ .../MultiplayerCorePacketRegistry.cs | 1 + 3 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcVoicePacket.cs diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 1186fed5..73422fb6 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -386,14 +386,10 @@ public async Task ShouldDenyConnection(EndPoint endPoint, byte[] additiona } ConnectDisconnectSemaphore.Release(); - //Send to all other players that they are connected, before sending to the new player that they have connected + //Send to all other players that they have connected, so that they can recieve the routed avatar packet await player.PlayerAccessSemaphore.WaitAsync(); var SendToOtherPlayers = new INetSerializable[] { - new SyncTimePacket - { - SyncTime = RunTime - }, new PlayerConnectedPacket { RemoteConnectionId = player.ConnectionId, @@ -562,7 +558,7 @@ public override async void OnConnect(EndPoint endPoint) }, DeliveryMethod.ReliableOrdered); } - //Start of sending player avatars and states to new player + //Start of sending player avatars and states of other players to new player INetSerializable[] SendToPlayerFromPlayers = new INetSerializable[3]; SendToPlayerFromPlayers[0] = new PlayerAvatarPacket(); SendToPlayerFromPlayers[1] = new PlayerStatePacket(); @@ -613,7 +609,6 @@ await Task.WhenAny( await Task.WhenAny(_packetDispatcher.SendToPlayerAndAwait(p, packet, DeliveryMethod.ReliableOrdered), Task.Delay(50)); } } - } public void DisconnectPlayer(string UserId) //Used my master servers kick player event diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcVoicePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcVoicePacket.cs new file mode 100644 index 00000000..fcd44571 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcVoicePacket.cs @@ -0,0 +1,18 @@ +using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets +{ + public class MpcVoicePacket : INetSerializable + { + public void ReadFrom(ref SpanBuffer bufferReader) + { + } + + public void WriteTo(ref SpanBuffer bufferWriter) + { + } + } +} + + diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs index 69bd7c4d..75dcc0ef 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs @@ -17,6 +17,7 @@ public override void Register() AddPacket(); AddPacket(); AddPacket(); + AddPacket(); AddPacket(); AddPacket(); AddPacket(); From 74fbd2b84b619dcb69265aa19e91bba531d607e5 Mon Sep 17 00:00:00 2001 From: Roy de Jong Date: Thu, 6 Jul 2023 01:17:38 +0200 Subject: [PATCH 016/120] wip(1.31): add Ignorance/ENet library --- ...tTogether.DedicatedServer.Ignorance.csproj | 22 + .../ENet/ENet.cs | 1415 +++++++++++++++++ .../IgnoranceCore/IgnoranceDefinitions.cs | 108 ++ .../IgnoranceCore/IgnoranceServer.cs | 435 +++++ .../IgnoranceThirdparty/RingBuffer.cs | 278 ++++ .../LICENSES.md | 56 + .../NativePlugins/enet.dll | Bin 0 -> 124928 bytes .../NativePlugins/libenet.so | Bin 0 -> 73744 bytes .../README.md | 5 + .../Util/IgnoranceDebug.cs | 20 + BeatTogether.DedicatedServer.sln | 6 + 11 files changed, 2345 insertions(+) create mode 100644 BeatTogether.DedicatedServer.Ignorance/BeatTogether.DedicatedServer.Ignorance.csproj create mode 100644 BeatTogether.DedicatedServer.Ignorance/ENet/ENet.cs create mode 100644 BeatTogether.DedicatedServer.Ignorance/IgnoranceCore/IgnoranceDefinitions.cs create mode 100644 BeatTogether.DedicatedServer.Ignorance/IgnoranceCore/IgnoranceServer.cs create mode 100644 BeatTogether.DedicatedServer.Ignorance/IgnoranceThirdparty/RingBuffer.cs create mode 100644 BeatTogether.DedicatedServer.Ignorance/LICENSES.md create mode 100644 BeatTogether.DedicatedServer.Ignorance/NativePlugins/enet.dll create mode 100644 BeatTogether.DedicatedServer.Ignorance/NativePlugins/libenet.so create mode 100644 BeatTogether.DedicatedServer.Ignorance/README.md create mode 100644 BeatTogether.DedicatedServer.Ignorance/Util/IgnoranceDebug.cs diff --git a/BeatTogether.DedicatedServer.Ignorance/BeatTogether.DedicatedServer.Ignorance.csproj b/BeatTogether.DedicatedServer.Ignorance/BeatTogether.DedicatedServer.Ignorance.csproj new file mode 100644 index 00000000..5c05fc32 --- /dev/null +++ b/BeatTogether.DedicatedServer.Ignorance/BeatTogether.DedicatedServer.Ignorance.csproj @@ -0,0 +1,22 @@ + + + + net6.0 + enable + enable + + + + + Always + + + Always + + + + + + + + diff --git a/BeatTogether.DedicatedServer.Ignorance/ENet/ENet.cs b/BeatTogether.DedicatedServer.Ignorance/ENet/ENet.cs new file mode 100644 index 00000000..3be96392 --- /dev/null +++ b/BeatTogether.DedicatedServer.Ignorance/ENet/ENet.cs @@ -0,0 +1,1415 @@ +/* + * Managed C# wrapper for an extended version of ENet + * This is a fork from upstream and is available at http://github.com/SoftwareGuy/ENet-CSharp + * + * Copyright (c) 2019 Matt Coburn (SoftwareGuy/Coburn64), Chris Burns (c6burns) + * Copyright (c) 2013 James Bellinger, 2016 Nate Shoffner, 2018 Stanislav Denisov + * + * 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. + */ + +using System.Runtime.InteropServices; +using System.Security; +using System.Text; + +namespace BeatTogether.DedicatedServer.Ignorance.ENet +{ + [Flags] + public enum PacketFlags + { + None = 0, + Reliable = 1 << 0, + Unsequenced = 1 << 1, + NoAllocate = 1 << 2, + UnreliableFragmented = 1 << 3, + Instant = 1 << 4, + Unthrottled = 1 << 5, + Sent = 1 << 8 + } + + public enum EventType + { + None = 0, + Connect = 1, + Disconnect = 2, + Receive = 3, + Timeout = 4 + } + + public enum PeerState + { + Uninitialized = -1, + Disconnected = 0, + Connecting = 1, + AcknowledgingConnect = 2, + ConnectionPending = 3, + ConnectionSucceeded = 4, + Connected = 5, + DisconnectLater = 6, + Disconnecting = 7, + AcknowledgingDisconnect = 8, + Zombie = 9 + } + + [StructLayout(LayoutKind.Explicit, Size = 18)] + internal struct ENetAddress + { + [FieldOffset(16)] + public ushort port; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct ENetEvent + { + public EventType type; + public IntPtr peer; + public byte channelID; + public uint data; + public IntPtr packet; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct ENetCallbacks + { + public AllocCallback malloc; + public FreeCallback free; + public NoMemoryCallback noMemory; + } + + public delegate IntPtr AllocCallback(IntPtr size); + public delegate void FreeCallback(IntPtr memory); + public delegate void NoMemoryCallback(); + public delegate void PacketFreeCallback(Packet packet); + public delegate int InterceptCallback(ref Event @event, ref Address address, IntPtr receivedData, int receivedDataLength); + public delegate ulong ChecksumCallback(IntPtr buffers, int bufferCount); + + internal static class ArrayPool + { + [ThreadStatic] + private static byte[] byteBuffer; + [ThreadStatic] + private static IntPtr[] pointerBuffer; + + public static byte[] GetByteBuffer() + { + if (byteBuffer == null) + byteBuffer = new byte[64]; + + return byteBuffer; + } + + public static IntPtr[] GetPointerBuffer() + { + if (pointerBuffer == null) + pointerBuffer = new IntPtr[Library.maxPeers]; + + return pointerBuffer; + } + } + + public struct Address + { + private ENetAddress nativeAddress; + + internal ENetAddress NativeData + { + get + { + return nativeAddress; + } + + set + { + nativeAddress = value; + } + } + + internal Address(ENetAddress address) + { + nativeAddress = address; + } + + public ushort Port + { + get + { + return nativeAddress.port; + } + + set + { + nativeAddress.port = value; + } + } + + public string GetIP() + { + StringBuilder ip = new StringBuilder(1025); + + if (Native.enet_address_get_ip(ref nativeAddress, ip, (IntPtr)ip.Capacity) != 0) + return String.Empty; + + return ip.ToString(); + } + + public bool SetIP(string ip) + { + if (ip == null) + throw new ArgumentNullException("ip"); + + return Native.enet_address_set_ip(ref nativeAddress, ip) == 0; + } + + public string GetHost() + { + StringBuilder hostName = new StringBuilder(1025); + + if (Native.enet_address_get_hostname(ref nativeAddress, hostName, (IntPtr)hostName.Capacity) != 0) + return String.Empty; + + return hostName.ToString(); + } + + public bool SetHost(string hostName) + { + if (hostName == null) + throw new ArgumentNullException("hostName"); + + return Native.enet_address_set_hostname(ref nativeAddress, hostName) == 0; + } + } + + public struct Event + { + private ENetEvent nativeEvent; + + internal ENetEvent NativeData + { + get + { + return nativeEvent; + } + + set + { + nativeEvent = value; + } + } + + internal Event(ENetEvent @event) + { + nativeEvent = @event; + } + + public EventType Type + { + get + { + return nativeEvent.type; + } + } + + public Peer Peer + { + get + { + return new Peer(nativeEvent.peer); + } + } + + public byte ChannelID + { + get + { + return nativeEvent.channelID; + } + } + + public uint Data + { + get + { + return nativeEvent.data; + } + } + + public Packet Packet + { + get + { + return new Packet(nativeEvent.packet); + } + } + } + + public class Callbacks + { + private ENetCallbacks nativeCallbacks; + + internal ENetCallbacks NativeData + { + get + { + return nativeCallbacks; + } + + set + { + nativeCallbacks = value; + } + } + + public Callbacks(AllocCallback allocCallback, FreeCallback freeCallback, NoMemoryCallback noMemoryCallback) + { + nativeCallbacks.malloc = allocCallback; + nativeCallbacks.free = freeCallback; + nativeCallbacks.noMemory = noMemoryCallback; + } + } + + public struct Packet : IDisposable + { + private IntPtr nativePacket; + + internal IntPtr NativeData + { + get + { + return nativePacket; + } + + set + { + nativePacket = value; + } + } + + internal Packet(IntPtr packet) + { + nativePacket = packet; + } + + public void Dispose() + { + if (nativePacket != IntPtr.Zero) + { + Native.enet_packet_dispose(nativePacket); + nativePacket = IntPtr.Zero; + } + } + + public bool IsSet + { + get + { + return nativePacket != IntPtr.Zero; + } + } + + public IntPtr Data + { + get + { + ThrowIfNotCreated(); + + return Native.enet_packet_get_data(nativePacket); + } + } + + public IntPtr UserData + { + get + { + ThrowIfNotCreated(); + + return Native.enet_packet_get_user_data(nativePacket); + } + + set + { + ThrowIfNotCreated(); + + Native.enet_packet_set_user_data(nativePacket, value); + } + } + + public int Length + { + get + { + ThrowIfNotCreated(); + + return Native.enet_packet_get_length(nativePacket); + } + } + + public bool HasReferences + { + get + { + ThrowIfNotCreated(); + + return Native.enet_packet_check_references(nativePacket) != 0; + } + } + + internal void ThrowIfNotCreated() + { + if (nativePacket == IntPtr.Zero) + throw new InvalidOperationException("Packet not created"); + } + + public void SetFreeCallback(IntPtr callback) + { + ThrowIfNotCreated(); + + Native.enet_packet_set_free_callback(nativePacket, callback); + } + + public void SetFreeCallback(PacketFreeCallback callback) + { + ThrowIfNotCreated(); + + Native.enet_packet_set_free_callback(nativePacket, Marshal.GetFunctionPointerForDelegate(callback)); + } + + public void Create(byte[] data) + { + if (data == null) + throw new ArgumentNullException("data"); + + Create(data, data.Length); + } + + public void Create(byte[] data, int length) + { + Create(data, length, PacketFlags.None); + } + + public void Create(byte[] data, PacketFlags flags) + { + Create(data, data.Length, flags); + } + + public void Create(byte[] data, int length, PacketFlags flags) + { + if (data == null) + throw new ArgumentNullException("data"); + + if (length < 0 || length > data.Length) + throw new ArgumentOutOfRangeException("length"); + + nativePacket = Native.enet_packet_create(data, (IntPtr)length, flags); + } + + public void Create(IntPtr data, int length, PacketFlags flags) + { + if (data == IntPtr.Zero) + throw new ArgumentNullException("data"); + + if (length < 0) + throw new ArgumentOutOfRangeException("length"); + + nativePacket = Native.enet_packet_create(data, (IntPtr)length, flags); + } + + public void Create(byte[] data, int offset, int length, PacketFlags flags) + { + if (data == null) + throw new ArgumentNullException("data"); + + if (offset < 0) + throw new ArgumentOutOfRangeException("offset"); + + if (length < 0 || length > data.Length) + throw new ArgumentOutOfRangeException("length"); + + nativePacket = Native.enet_packet_create_offset(data, (IntPtr)length, (IntPtr)offset, flags); + } + + public void Create(IntPtr data, int offset, int length, PacketFlags flags) + { + if (data == IntPtr.Zero) + throw new ArgumentNullException("data"); + + if (offset < 0) + throw new ArgumentOutOfRangeException("offset"); + + if (length < 0) + throw new ArgumentOutOfRangeException("length"); + + nativePacket = Native.enet_packet_create_offset(data, (IntPtr)length, (IntPtr)offset, flags); + } + + public void CopyTo(byte[] destination, int startPos = 0) + { + if (destination == null) + throw new ArgumentNullException("destination"); + + // Fix by katori, prevents trying to copy a NULL + // from native world (ie. disconnect a client) + if (Data == null) + { + return; + } + + Marshal.Copy(Data, destination, startPos, Length); + } + } + + public class Host : IDisposable + { + private IntPtr nativeHost; + + internal IntPtr NativeData + { + get + { + return nativeHost; + } + + set + { + nativeHost = value; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (nativeHost != IntPtr.Zero) + { + Native.enet_host_destroy(nativeHost); + nativeHost = IntPtr.Zero; + } + } + + ~Host() + { + Dispose(false); + } + + public bool IsSet + { + get + { + return nativeHost != IntPtr.Zero; + } + } + + public uint PeersCount + { + get + { + ThrowIfNotCreated(); + + return Native.enet_host_get_peers_count(nativeHost); + } + } + + public uint PacketsSent + { + get + { + ThrowIfNotCreated(); + + return Native.enet_host_get_packets_sent(nativeHost); + } + } + + public uint PacketsReceived + { + get + { + ThrowIfNotCreated(); + + return Native.enet_host_get_packets_received(nativeHost); + } + } + + public uint BytesSent + { + get + { + ThrowIfNotCreated(); + + return Native.enet_host_get_bytes_sent(nativeHost); + } + } + + public uint BytesReceived + { + get + { + ThrowIfNotCreated(); + + return Native.enet_host_get_bytes_received(nativeHost); + } + } + + internal void ThrowIfNotCreated() + { + if (nativeHost == IntPtr.Zero) + throw new InvalidOperationException("Host not created"); + } + + private static void ThrowIfChannelsExceeded(int channelLimit) + { + if (channelLimit < 0 || channelLimit > Library.maxChannelCount) + throw new ArgumentOutOfRangeException("channelLimit"); + } + + public void Create() + { + Create(null, 1, 0); + } + + public void Create(int bufferSize) + { + Create(null, 1, 0, 0, 0, bufferSize); + } + + public void Create(Address? address, int peerLimit) + { + Create(address, peerLimit, 0); + } + + public void Create(Address? address, int peerLimit, int channelLimit) + { + Create(address, peerLimit, channelLimit, 0, 0, 0); + } + + public void Create(int peerLimit, int channelLimit) + { + Create(null, peerLimit, channelLimit, 0, 0, 0); + } + + public void Create(int peerLimit, int channelLimit, uint incomingBandwidth, uint outgoingBandwidth) + { + Create(null, peerLimit, channelLimit, incomingBandwidth, outgoingBandwidth, 0); + } + + public void Create(Address? address, int peerLimit, int channelLimit, uint incomingBandwidth, uint outgoingBandwidth) + { + Create(address, peerLimit, channelLimit, incomingBandwidth, outgoingBandwidth, 0); + } + + public void Create(Address? address, int peerLimit, int channelLimit, uint incomingBandwidth, uint outgoingBandwidth, int bufferSize) + { + if (nativeHost != IntPtr.Zero) + throw new InvalidOperationException("Host already created"); + + if (peerLimit < 0 || peerLimit > Library.maxPeers) + throw new ArgumentOutOfRangeException("peerLimit"); + + ThrowIfChannelsExceeded(channelLimit); + + if (address != null) + { + var nativeAddress = address.Value.NativeData; + + nativeHost = Native.enet_host_create(ref nativeAddress, (IntPtr)peerLimit, (IntPtr)channelLimit, incomingBandwidth, outgoingBandwidth, bufferSize); + } + else + { + nativeHost = Native.enet_host_create(IntPtr.Zero, (IntPtr)peerLimit, (IntPtr)channelLimit, incomingBandwidth, outgoingBandwidth, bufferSize); + } + + if (nativeHost == IntPtr.Zero) + throw new InvalidOperationException("Host creation call failed"); + } + + public void PreventConnections(bool state) + { + ThrowIfNotCreated(); + + Native.enet_host_prevent_connections(nativeHost, (byte)(state ? 1 : 0)); + } + + public void Broadcast(byte channelID, ref Packet packet) + { + ThrowIfNotCreated(); + + packet.ThrowIfNotCreated(); + Native.enet_host_broadcast(nativeHost, channelID, packet.NativeData); + packet.NativeData = IntPtr.Zero; + } + + public void Broadcast(byte channelID, ref Packet packet, Peer excludedPeer) + { + ThrowIfNotCreated(); + + packet.ThrowIfNotCreated(); + Native.enet_host_broadcast_exclude(nativeHost, channelID, packet.NativeData, excludedPeer.NativeData); + packet.NativeData = IntPtr.Zero; + } + + public void Broadcast(byte channelID, ref Packet packet, Peer[] peers) + { + if (peers == null) + throw new ArgumentNullException("peers"); + + ThrowIfNotCreated(); + + packet.ThrowIfNotCreated(); + + if (peers.Length > 0) + { + IntPtr[] nativePeers = ArrayPool.GetPointerBuffer(); + int nativeCount = 0; + + for (int i = 0; i < peers.Length; i++) + { + if (peers[i].NativeData != IntPtr.Zero) + { + nativePeers[nativeCount] = peers[i].NativeData; + nativeCount++; + } + } + + Native.enet_host_broadcast_selective(nativeHost, channelID, packet.NativeData, nativePeers, (IntPtr)nativeCount); + } + + packet.NativeData = IntPtr.Zero; + } + + public int CheckEvents(out Event @event) + { + ThrowIfNotCreated(); + + ENetEvent nativeEvent; + + var result = Native.enet_host_check_events(nativeHost, out nativeEvent); + + if (result <= 0) + { + @event = default(Event); + + return result; + } + + @event = new Event(nativeEvent); + + return result; + } + + public Peer Connect(Address address) + { + return Connect(address, 0, 0); + } + + public Peer Connect(Address address, int channelLimit) + { + return Connect(address, channelLimit, 0); + } + + public Peer Connect(Address address, int channelLimit, uint data) + { + ThrowIfNotCreated(); + ThrowIfChannelsExceeded(channelLimit); + + var nativeAddress = address.NativeData; + var peer = new Peer(Native.enet_host_connect(nativeHost, ref nativeAddress, (IntPtr)channelLimit, data)); + + if (peer.NativeData == IntPtr.Zero) + throw new InvalidOperationException("Host connect call failed"); + + return peer; + } + + public int Service(int timeout, out Event @event) + { + if (timeout < 0) + throw new ArgumentOutOfRangeException("timeout"); + + ThrowIfNotCreated(); + + ENetEvent nativeEvent; + + var result = Native.enet_host_service(nativeHost, out nativeEvent, (uint)timeout); + + if (result <= 0) + { + @event = default(Event); + + return result; + } + + @event = new Event(nativeEvent); + + return result; + } + + public void SetBandwidthLimit(uint incomingBandwidth, uint outgoingBandwidth) + { + ThrowIfNotCreated(); + + Native.enet_host_bandwidth_limit(nativeHost, incomingBandwidth, outgoingBandwidth); + } + + public void SetChannelLimit(int channelLimit) + { + ThrowIfNotCreated(); + ThrowIfChannelsExceeded(channelLimit); + + Native.enet_host_channel_limit(nativeHost, (IntPtr)channelLimit); + } + + public void SetMaxDuplicatePeers(ushort number) + { + ThrowIfNotCreated(); + + Native.enet_host_set_max_duplicate_peers(nativeHost, number); + } + + public void SetInterceptCallback(IntPtr callback) + { + ThrowIfNotCreated(); + + Native.enet_host_set_intercept_callback(nativeHost, callback); + } + + public void SetInterceptCallback(InterceptCallback callback) + { + ThrowIfNotCreated(); + + Native.enet_host_set_intercept_callback(nativeHost, Marshal.GetFunctionPointerForDelegate(callback)); + } + + public void SetChecksumCallback(IntPtr callback) + { + ThrowIfNotCreated(); + + Native.enet_host_set_checksum_callback(nativeHost, callback); + } + + public void SetChecksumCallback(ChecksumCallback callback) + { + ThrowIfNotCreated(); + + Native.enet_host_set_checksum_callback(nativeHost, Marshal.GetFunctionPointerForDelegate(callback)); + } + + public void Flush() + { + ThrowIfNotCreated(); + + Native.enet_host_flush(nativeHost); + } + } + + public struct Peer + { + private IntPtr nativePeer; + private uint nativeID; + + internal IntPtr NativeData + { + get + { + return nativePeer; + } + + set + { + nativePeer = value; + } + } + + internal Peer(IntPtr peer) + { + nativePeer = peer; + nativeID = nativePeer != IntPtr.Zero ? Native.enet_peer_get_id(nativePeer) : 0; + } + + public bool IsSet + { + get + { + return nativePeer != IntPtr.Zero; + } + } + + public uint ID + { + get + { + return nativeID; + } + } + + public string IP + { + get + { + ThrowIfNotCreated(); + + byte[] ip = ArrayPool.GetByteBuffer(); + + if (Native.enet_peer_get_ip(nativePeer, ip, (IntPtr)ip.Length) == 0) + return Encoding.ASCII.GetString(ip, 0, ip.StringLength()); + else + return String.Empty; + } + } + + public ushort Port + { + get + { + ThrowIfNotCreated(); + + return Native.enet_peer_get_port(nativePeer); + } + } + + public uint MTU + { + get + { + ThrowIfNotCreated(); + + return Native.enet_peer_get_mtu(nativePeer); + } + } + + public PeerState State + { + get + { + return nativePeer == IntPtr.Zero ? PeerState.Uninitialized : Native.enet_peer_get_state(nativePeer); + } + } + + public uint RoundTripTime + { + get + { + ThrowIfNotCreated(); + + return Native.enet_peer_get_rtt(nativePeer); + } + } + + public uint LastRoundTripTime + { + get + { + ThrowIfNotCreated(); + + return Native.enet_peer_get_last_rtt(nativePeer); + } + } + + public uint LastSendTime + { + get + { + ThrowIfNotCreated(); + + return Native.enet_peer_get_lastsendtime(nativePeer); + } + } + + public uint LastReceiveTime + { + get + { + ThrowIfNotCreated(); + + return Native.enet_peer_get_lastreceivetime(nativePeer); + } + } + + public ulong PacketsSent + { + get + { + ThrowIfNotCreated(); + + return Native.enet_peer_get_packets_sent(nativePeer); + } + } + + public ulong PacketsLost + { + get + { + ThrowIfNotCreated(); + + return Native.enet_peer_get_packets_lost(nativePeer); + } + } + + public float PacketsThrottle + { + get + { + ThrowIfNotCreated(); + + return Native.enet_peer_get_packets_throttle(nativePeer); + } + } + + public ulong BytesSent + { + get + { + ThrowIfNotCreated(); + + return Native.enet_peer_get_bytes_sent(nativePeer); + } + } + + public ulong BytesReceived + { + get + { + ThrowIfNotCreated(); + + return Native.enet_peer_get_bytes_received(nativePeer); + } + } + + public IntPtr Data + { + get + { + ThrowIfNotCreated(); + + return Native.enet_peer_get_data(nativePeer); + } + + set + { + ThrowIfNotCreated(); + + Native.enet_peer_set_data(nativePeer, value); + } + } + + internal void ThrowIfNotCreated() + { + if (nativePeer == IntPtr.Zero) + throw new InvalidOperationException("Peer not created"); + } + + public void ConfigureThrottle(uint interval, uint acceleration, uint deceleration, uint threshold) + { + ThrowIfNotCreated(); + + Native.enet_peer_throttle_configure(nativePeer, interval, acceleration, deceleration, threshold); + } + + public int Send(byte channelID, ref Packet packet) + { + ThrowIfNotCreated(); + + packet.ThrowIfNotCreated(); + + return Native.enet_peer_send(nativePeer, channelID, packet.NativeData); + } + + public bool Receive(out byte channelID, out Packet packet) + { + ThrowIfNotCreated(); + + IntPtr nativePacket = Native.enet_peer_receive(nativePeer, out channelID); + + if (nativePacket != IntPtr.Zero) + { + packet = new Packet(nativePacket); + + return true; + } + + packet = default(Packet); + + return false; + } + + public void Ping() + { + ThrowIfNotCreated(); + + Native.enet_peer_ping(nativePeer); + } + + public void PingInterval(uint interval) + { + ThrowIfNotCreated(); + + Native.enet_peer_ping_interval(nativePeer, interval); + } + + public void Timeout(uint timeoutLimit, uint timeoutMinimum, uint timeoutMaximum) + { + ThrowIfNotCreated(); + + Native.enet_peer_timeout(nativePeer, timeoutLimit, timeoutMinimum, timeoutMaximum); + } + + public void Disconnect(uint data) + { + ThrowIfNotCreated(); + + Native.enet_peer_disconnect(nativePeer, data); + } + + public void DisconnectNow(uint data) + { + ThrowIfNotCreated(); + + Native.enet_peer_disconnect_now(nativePeer, data); + } + + public void DisconnectLater(uint data) + { + ThrowIfNotCreated(); + + Native.enet_peer_disconnect_later(nativePeer, data); + } + + public void Reset() + { + ThrowIfNotCreated(); + + Native.enet_peer_reset(nativePeer); + } + } + + public static class Extensions + { + public static int StringLength(this byte[] data) + { + if (data == null) + throw new ArgumentNullException("data"); + + int i; + + for (i = 0; i < data.Length && data[i] != 0; i++) ; + + return i; + } + } + + public static class Library + { + public const uint maxChannelCount = 0xFF; + public const uint maxPeers = 0xFFF; + public const uint maxPacketSize = 32 * 1024 * 1024; + public const uint throttleThreshold = 40; + public const uint throttleScale = 32; + public const uint throttleAcceleration = 2; + public const uint throttleDeceleration = 2; + public const uint throttleInterval = 5000; + public const uint timeoutLimit = 32; + public const uint timeoutMinimum = 5000; + public const uint timeoutMaximum = 30000; + public const uint version = (2 << 16) | (4 << 8) | (7); + + public static uint Time + { + get + { + return Native.enet_time_get(); + } + } + + public static bool Initialize() + { + if (Native.enet_linked_version() != version) + throw new InvalidOperationException("ENet native is out of date. Download the latest release from https://github.com/SoftwareGuy/ENet-CSharp/releases"); + + return Native.enet_initialize() == 0; + } + + public static bool Initialize(Callbacks callbacks) + { + if (callbacks == null) + throw new ArgumentNullException("callbacks"); + + if (Native.enet_linked_version() != version) + throw new InvalidOperationException("ENet native is out of date. Download the latest release from https://github.com/SoftwareGuy/ENet-CSharp/releases"); + + ENetCallbacks nativeCallbacks = callbacks.NativeData; + + return Native.enet_initialize_with_callbacks(version, ref nativeCallbacks) == 0; + } + + public static void Deinitialize() + { + Native.enet_deinitialize(); + } + + public static ulong CRC64(IntPtr buffers, int bufferCount) + { + return Native.enet_crc64(buffers, bufferCount); + } + } + + [SuppressUnmanagedCodeSecurity] + internal static class Native + { + // This should address Unity usage and bug #66: Platform specific Enet / libenet + // https://github.com/SoftwareGuy/Ignorance/issues/66 + + #region Editor Specific Native Library Names +#if UNITY_EDITOR +#if UNITY_EDITOR_OSX + // Unity Editor on macOS needs to use libenet. + private const string nativeLibrary = "libenet"; +#else + // All other platforms should be using "enet". + private const string nativeLibrary = "enet"; +#endif +#endif + #endregion + + + #region Standalone Specific Native Library Names +#if !UNITY_EDITOR +#if __APPLE__ && !(__IOS__ || UNITY_IOS) + // Use libenet on macOS. + private const string nativeLibrary = "libenet"; +#elif __IOS__ || UNITY_IOS + // We're building for a certain mobile fruity OS. + private const string nativeLibrary = "__Internal"; +#else + // Assume everything else, Windows et al. + private const string nativeLibrary = "enet"; +#endif +#endif + #endregion + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_initialize(); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_initialize_with_callbacks(uint version, ref ENetCallbacks inits); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_deinitialize(); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_linked_version(); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_time_get(); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern ulong enet_crc64(IntPtr buffers, int bufferCount); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_address_set_ip(ref ENetAddress address, string ip); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_address_set_hostname(ref ENetAddress address, string hostName); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_address_get_ip(ref ENetAddress address, StringBuilder ip, IntPtr ipLength); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_address_get_hostname(ref ENetAddress address, StringBuilder hostName, IntPtr nameLength); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_create(byte[] data, IntPtr dataLength, PacketFlags flags); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_create(IntPtr data, IntPtr dataLength, PacketFlags flags); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_create_offset(byte[] data, IntPtr dataLength, IntPtr dataOffset, PacketFlags flags); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_create_offset(IntPtr data, IntPtr dataLength, IntPtr dataOffset, PacketFlags flags); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_packet_check_references(IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_get_data(IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_get_user_data(IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_set_user_data(IntPtr packet, IntPtr userData); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_packet_get_length(IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_packet_set_free_callback(IntPtr packet, IntPtr callback); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_packet_dispose(IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_host_create(ref ENetAddress address, IntPtr peerLimit, IntPtr channelLimit, uint incomingBandwidth, uint outgoingBandwidth, int bufferSize); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_host_create(IntPtr address, IntPtr peerLimit, IntPtr channelLimit, uint incomingBandwidth, uint outgoingBandwidth, int bufferSize); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_host_connect(IntPtr host, ref ENetAddress address, IntPtr channelCount, uint data); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_broadcast(IntPtr host, byte channelID, IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_broadcast_exclude(IntPtr host, byte channelID, IntPtr packet, IntPtr excludedPeer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_broadcast_selective(IntPtr host, byte channelID, IntPtr packet, IntPtr[] peers, IntPtr peersLength); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_host_service(IntPtr host, out ENetEvent @event, uint timeout); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_host_check_events(IntPtr host, out ENetEvent @event); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_channel_limit(IntPtr host, IntPtr channelLimit); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_bandwidth_limit(IntPtr host, uint incomingBandwidth, uint outgoingBandwidth); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_host_get_peers_count(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_host_get_packets_sent(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_host_get_packets_received(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_host_get_bytes_sent(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_host_get_bytes_received(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_set_max_duplicate_peers(IntPtr host, ushort number); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_set_intercept_callback(IntPtr host, IntPtr callback); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_set_checksum_callback(IntPtr host, IntPtr callback); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_flush(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_destroy(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_prevent_connections(IntPtr host, byte state); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_throttle_configure(IntPtr peer, uint interval, uint acceleration, uint deceleration, uint threshold); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_peer_get_id(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_peer_get_ip(IntPtr peer, byte[] ip, IntPtr ipLength); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern ushort enet_peer_get_port(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_peer_get_mtu(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern PeerState enet_peer_get_state(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_peer_get_rtt(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_peer_get_last_rtt(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_peer_get_lastsendtime(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_peer_get_lastreceivetime(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern ulong enet_peer_get_packets_sent(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern ulong enet_peer_get_packets_lost(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern float enet_peer_get_packets_throttle(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern ulong enet_peer_get_bytes_sent(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern ulong enet_peer_get_bytes_received(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_peer_get_data(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_set_data(IntPtr peer, IntPtr data); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_peer_send(IntPtr peer, byte channelID, IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_peer_receive(IntPtr peer, out byte channelID); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_ping(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_ping_interval(IntPtr peer, uint pingInterval); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_timeout(IntPtr peer, uint timeoutLimit, uint timeoutMinimum, uint timeoutMaximum); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_disconnect(IntPtr peer, uint data); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_disconnect_now(IntPtr peer, uint data); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_disconnect_later(IntPtr peer, uint data); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_reset(IntPtr peer); + +#if UNITY_EDITOR + public static string nativeLibraryName { get { return nativeLibrary; } } +#endif + + } +} diff --git a/BeatTogether.DedicatedServer.Ignorance/IgnoranceCore/IgnoranceDefinitions.cs b/BeatTogether.DedicatedServer.Ignorance/IgnoranceCore/IgnoranceDefinitions.cs new file mode 100644 index 00000000..ebf25d19 --- /dev/null +++ b/BeatTogether.DedicatedServer.Ignorance/IgnoranceCore/IgnoranceDefinitions.cs @@ -0,0 +1,108 @@ +// Ignorance 1.4.x LTS (Long Term Support) +// https://github.com/SoftwareGuy/Ignorance +// ----------------- +// Copyright (c) 2019 - 2021 Matt Coburn (SoftwareGuy/Coburn64) +// Ignorance is licensed under the MIT license. Refer +// to the LICENSE file for more information. + +using BeatTogether.DedicatedServer.Ignorance.ENet; + +namespace BeatTogether.DedicatedServer.Ignorance.IgnoranceCore +{ + // Snipped from the transport files, as this will help + // me keep things up to date. + [Serializable] + public enum IgnoranceChannelTypes + { + Reliable = PacketFlags.Reliable, // Reliable UDP (TCP-like emulation) + ReliableUnsequenced = PacketFlags.Reliable | PacketFlags.Unsequenced, // Reliable UDP (TCP-like emulation w/o sequencing) + Unreliable = PacketFlags.Unsequenced, // Pure UDP, high velocity packet action. + UnreliableFragmented = PacketFlags.UnreliableFragmented, // Pure UDP, but fragmented. + UnreliableSequenced = PacketFlags.None, // Pure UDP, but sequenced. + Unthrottled = PacketFlags.Unthrottled, // Pure UDP. Literally turbo mode. + } + + public class IgnoranceInternals + { + public const string Version = "1.4.0r2 (LTS)"; + public const string Scheme = "enet"; + public const string BindAnyAddress = "::0"; + } + + public enum IgnoranceLogType + { + Quiet, + Standard, + Verbose + } + + public struct IgnoranceIncomingPacket + { + public byte Channel; + public uint NativePeerId; + public Packet Payload; + } + + public struct IgnoranceOutgoingPacket + { + public byte Channel; + public uint NativePeerId; + public Packet Payload; + } + + public struct IgnoranceConnectionEvent + { + public byte EventType; + public ushort Port; + public uint NativePeerId; + public string IP; + } + + public struct IgnoranceCommandPacket + { + public IgnoranceCommandType Type; + public uint PeerId; + } + + // Stats only - may not always be used! + public struct IgnoranceClientStats + { + + public uint RTT; + public ulong BytesReceived; + public ulong BytesSent; + public ulong PacketsReceived; + public ulong PacketsSent; + public ulong PacketsLost; + } + + public enum IgnoranceCommandType + { + // Client + ClientWantsToStop, + ClientStatusRequest, + // Server + ServerKickPeer, + ServerStatusRequest + } + + // Stats only - may not always be used! + public struct IgnoranceServerStats + { + + public ulong BytesReceived; + public ulong BytesSent; + public ulong PacketsReceived; + public ulong PacketsSent; + public ulong PeersCount; + + public Dictionary PeerStats; + } + + public struct PeerConnectionData + { + public ushort Port; + public uint NativePeerId; + public string IP; + } +} diff --git a/BeatTogether.DedicatedServer.Ignorance/IgnoranceCore/IgnoranceServer.cs b/BeatTogether.DedicatedServer.Ignorance/IgnoranceCore/IgnoranceServer.cs new file mode 100644 index 00000000..91fad905 --- /dev/null +++ b/BeatTogether.DedicatedServer.Ignorance/IgnoranceCore/IgnoranceServer.cs @@ -0,0 +1,435 @@ +// Ignorance 1.4.x LTS (Long Term Support) +// https://github.com/SoftwareGuy/Ignorance +// ----------------- +// Copyright (c) 2019 - 2021 Matt Coburn (SoftwareGuy/Coburn64) +// Ignorance is licensed under the MIT license. Refer +// to the LICENSE file for more information. + +using BeatTogether.DedicatedServer.Ignorance.ENet; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceThirdparty; +using Event = BeatTogether.DedicatedServer.Ignorance.ENet.Event; +using EventType = BeatTogether.DedicatedServer.Ignorance.ENet.EventType; +using Object = System.Object; +using Debug = BeatTogether.DedicatedServer.Ignorance.Util.IgnoranceDebug; + +namespace BeatTogether.DedicatedServer.Ignorance.IgnoranceCore +{ + public class IgnoranceServer + { + // Server Properties + // - Bind Settings + public string BindAddress = "127.0.0.1"; + public int BindPort = 7777; + // - Maximum allowed channels, peers, etc. + public int MaximumChannels = 2; + public int MaximumPeers = 100; + public int MaximumPacketSize = 33554432; // ENet.cs: uint maxPacketSize = 32 * 1024 * 1024 = 33554432 + // - Native poll waiting time + public int PollTime = 1; + // - Verbosity. + public int Verbosity = 1; + // - Queue Sizing + public int IncomingOutgoingBufferSize = 5000; + public int ConnectionEventBufferSize = 100; + // - Fruity devices + public bool IsFruityDevice; + public bool BindAllInterfaces; + + public bool IsAlive => WorkerThread != null && WorkerThread.IsAlive; + + private volatile bool CeaseOperation = false; + + // Queues + // v1.4.0b9: Replace the queues with RingBuffers. + public RingBuffer Incoming; + public RingBuffer Outgoing; + public RingBuffer Commands; + public RingBuffer ConnectionEvents; + public RingBuffer DisconnectionEvents; + public RingBuffer StatusUpdates; + + public RingBuffer RecycledServerStatBlocks = new RingBuffer(100); + + // Thread + private Thread WorkerThread; + + public void Start() + { + if (WorkerThread != null && WorkerThread.IsAlive) + { + // Cannot do that. + Debug.LogError("Ignorance Server: A worker thread is already running. Cannot start another."); + return; + } + + // Setup the ring buffers. + SetupRingBuffersIfNull(); + + CeaseOperation = false; + ThreadParamInfo threadParams = new ThreadParamInfo() + { + IsFruityDevice = IsFruityDevice, + BindAllInterfaces = BindAllInterfaces, + Address = BindAddress, + Port = BindPort, + Peers = MaximumPeers, + Channels = MaximumChannels, + PollTime = PollTime, + PacketSizeLimit = MaximumPacketSize, + Verbosity = Verbosity + }; + + // Drain queues. + if (Incoming != null) while (Incoming.TryDequeue(out _)) ; + if (Outgoing != null) while (Outgoing.TryDequeue(out _)) ; + if (Commands != null) while (Commands.TryDequeue(out _)) ; + if (ConnectionEvents != null) while (ConnectionEvents.TryDequeue(out _)) ; + if (DisconnectionEvents != null) while (DisconnectionEvents.TryDequeue(out _)) ; + if (StatusUpdates != null) while (StatusUpdates.TryDequeue(out _)) ; + + WorkerThread = new Thread(ThreadWorker); + WorkerThread.Start(threadParams); + + // Announce + if (Verbosity > 0) + Debug.Log("Ignorance Server: Dispatched worker thread."); + } + + public void Stop() + { + // v1.4.0b7: Mirror may call this; if the worker thread isn't alive then don't announce it. + if (WorkerThread != null && WorkerThread.IsAlive) + { + if (Verbosity > 0) + Debug.Log("Ignorance Server: Server stop acknowledged. Depending on network load, this may take a moment or two..."); + + CeaseOperation = true; + } + } + + #region The meat and potatoes. + private void ThreadWorker(Object parameters) + { + if (Verbosity > 0) + Debug.Log("Ignorance: Server instance worker thread is initializing. Please stand by..."); + + // Thread cache items + ThreadParamInfo setupInfo; + Address serverAddress = new Address(); + Host serverENetHost; + Event serverENetEvent; + + Peer[] serverPeerArray; + IgnoranceClientStats peerStats = default; + + // Grab the setup information. + if (parameters.GetType() == typeof(ThreadParamInfo)) + { + setupInfo = (ThreadParamInfo)parameters; + } + else + { + Debug.LogError("Ignorance: Server instance worker thread reports startup failure; Invalid thread parameters. Aborting."); + return; + } + + // Attempt to initialize ENet inside the thread. + if (Library.Initialize()) + { + Debug.Log("Ignorance: Server instance worker thread successfully initialized ENet."); + } + else + { + Debug.LogError("Ignorance Server: Failed to initialize ENet Native. Aborting."); + return; + } + + // Configure the server address. + // So... if we're running on a Mac, we have an issue where if we attempt to bind to all devices which usually is either + // 0.0.0.0 or ::0. In older versions of Mac OS, this worked since those addresses are "broadcast" or "listen all"... + // but on newer versions this broke the server functionality. So the fix was rather easy but the debugging was not. + // The fix was to NOT set any IP/Host if we're binding to all addresses on MacOS. Apparently that works. Go figure. + // Afterthought: Maybe it's something funky in ENet...? + + if (setupInfo.IsFruityDevice) + { + if (!setupInfo.BindAllInterfaces) + serverAddress.SetHost(setupInfo.Address); + } + else + { + if (setupInfo.BindAllInterfaces) + serverAddress.SetIP(IgnoranceInternals.BindAnyAddress); + else + serverAddress.SetHost(setupInfo.Address); + } + + // Set the port too. + serverAddress.Port = (ushort)setupInfo.Port; + serverPeerArray = new Peer[setupInfo.Peers]; + + using (serverENetHost = new Host()) + { + // Create the server object. + try + { + serverENetHost.Create(serverAddress, setupInfo.Peers, setupInfo.Channels); + } + catch (Exception ex) + { + Debug.LogError($"Ignorance: Server instance worker thread reports that something went wrong. While attempting to create server host object, we caught an exception:\n{ex.Message}"); + Debug.LogError($"If you are getting a \"Host creation call failed\" exception, please ensure you don't have a server already running on the same IP and Port.\n" + + $"Multiple server instances running on the same port are not supported. Also check to see if ports are not in-use by another application. In the worse case scenario, " + + $"restart your device to ensure no random background ENet threads are active that haven't been cleaned up correctly. If problems persist, please file a support ticket."); + + Library.Deinitialize(); + return; + } + + // Loop until we're told to cease operations. + while (!CeaseOperation) + { + // Intermission: Command Handling + while (Commands.TryDequeue(out IgnoranceCommandPacket commandPacket)) + { + switch (commandPacket.Type) + { + default: + break; + + // Boot a Peer off the Server. + case IgnoranceCommandType.ServerKickPeer: + uint targetPeer = commandPacket.PeerId; + + if (!serverPeerArray[targetPeer].IsSet) continue; + + if (setupInfo.Verbosity > 0) + Debug.Log($"Ignorance: Server instance is disconnecting peer {targetPeer}."); + + IgnoranceConnectionEvent iced = new IgnoranceConnectionEvent + { + EventType = 0x01, + NativePeerId = targetPeer + }; + + DisconnectionEvents.Enqueue(iced); + + // Disconnect and reset the peer array's entry for that peer. + serverPeerArray[targetPeer].DisconnectNow(0); + serverPeerArray[targetPeer] = default; + break; + + case IgnoranceCommandType.ServerStatusRequest: + IgnoranceServerStats serverStats; + if (!RecycledServerStatBlocks.TryDequeue(out serverStats)) + serverStats.PeerStats = new Dictionary(setupInfo.Peers); + + serverStats.PeerStats.Clear(); + + serverStats.BytesReceived = serverENetHost.BytesReceived; + serverStats.BytesSent = serverENetHost.BytesSent; + + serverStats.PacketsReceived = serverENetHost.PacketsReceived; + serverStats.PacketsSent = serverENetHost.PacketsSent; + + serverStats.PeersCount = serverENetHost.PeersCount; + + for (int i = 0; i < serverPeerArray.Length; i++) + { + if (!serverPeerArray[i].IsSet) continue; + + peerStats.RTT = serverPeerArray[i].RoundTripTime; + + peerStats.BytesReceived = serverPeerArray[i].BytesReceived; + peerStats.BytesSent = serverPeerArray[i].BytesSent; + + peerStats.PacketsSent = serverPeerArray[i].PacketsSent; + peerStats.PacketsLost = serverPeerArray[i].PacketsLost; + + serverStats.PeerStats.Add(i, peerStats); + } + + StatusUpdates.Enqueue(serverStats); + break; + } + } + + // Step One: + // ---> Sending to peers + while (Outgoing.TryDequeue(out IgnoranceOutgoingPacket outgoingPacket)) + { + // Only create a packet if the server knows the peer. + if (serverPeerArray[outgoingPacket.NativePeerId].IsSet) + { + int ret = serverPeerArray[outgoingPacket.NativePeerId].Send(outgoingPacket.Channel, ref outgoingPacket.Payload); + + if (ret < 0 && setupInfo.Verbosity > 0) + Debug.LogWarning($"Ignorance: Server instance ENet error {ret} while sending packet to Peer {outgoingPacket.NativePeerId}."); + } + else + { + // A peer might have disconnected, this is OK - just log the packet if set to paranoid. + if (setupInfo.Verbosity > 1) + Debug.LogWarning("Ignorance: Server instance can't send packet, a native peer object is not set. This may be normal if the Peer has disconnected before this send cycle."); + } + + } + + // Step 2 + // <--- Receiving from peers + bool pollComplete = false; + + while (!pollComplete) + { + Packet incomingPacket; + Peer incomingPeer; + int incomingPacketLength; + + // Any events happening? + if (serverENetHost.CheckEvents(out serverENetEvent) <= 0) + { + // If service time is met, break out of it. + if (serverENetHost.Service(setupInfo.PollTime, out serverENetEvent) <= 0) break; + + pollComplete = true; + } + + // Setup the packet references. + incomingPeer = serverENetEvent.Peer; + + // What type are you? + switch (serverENetEvent.Type) + { + // Idle. + case EventType.None: + default: + break; + + // Connection Event. + case EventType.Connect: + if (setupInfo.Verbosity > 1) + Debug.Log($"Ignorance: Server instance says that Peer {incomingPeer.ID} says Hi."); + + IgnoranceConnectionEvent ice = new IgnoranceConnectionEvent() + { + NativePeerId = incomingPeer.ID, + IP = incomingPeer.IP, + Port = incomingPeer.Port + }; + + ConnectionEvents.Enqueue(ice); + + // Assign a reference to the Peer. + serverPeerArray[incomingPeer.ID] = incomingPeer; + break; + + // Disconnect/Timeout. Mirror doesn't care if it's either, so we lump them together. + case EventType.Disconnect: + case EventType.Timeout: + if (!serverPeerArray[incomingPeer.ID].IsSet) break; + + if (setupInfo.Verbosity > 1) + Debug.Log($"Ignorance: Server instance says that Peer {incomingPeer.ID} has disconnected."); + + IgnoranceConnectionEvent iced = new IgnoranceConnectionEvent + { + EventType = 0x01, + NativePeerId = incomingPeer.ID + }; + + DisconnectionEvents.Enqueue(iced); + + // Reset the peer array's entry for that peer. + serverPeerArray[incomingPeer.ID] = default; + break; + + case EventType.Receive: + // Receive event type usually includes a packet; so cache its reference. + incomingPacket = serverENetEvent.Packet; + if (!incomingPacket.IsSet) + { + if (setupInfo.Verbosity > 0) + Debug.LogWarning($"Ignorance: Server instance receive event did not supply us with a packet to work with. This should never happen."); + break; + } + + incomingPacketLength = incomingPacket.Length; + + // Firstly check if the packet is too big. If it is, do not process it - drop it. + if (incomingPacketLength > setupInfo.PacketSizeLimit) + { + if (setupInfo.Verbosity > 0) + Debug.LogWarning($"Ignorance: Server incoming packet is too big. My limit is {setupInfo.PacketSizeLimit} byte(s) whilest this packet is {incomingPacketLength} bytes."); + + incomingPacket.Dispose(); + break; + } + + IgnoranceIncomingPacket incomingQueuePacket = new IgnoranceIncomingPacket + { + Channel = serverENetEvent.ChannelID, + NativePeerId = incomingPeer.ID, + Payload = incomingPacket, + }; + + // Enqueue. + Incoming.Enqueue(incomingQueuePacket); + break; + } + } + } + + if (Verbosity > 0) + Debug.Log("Ignorance: Server instance thread shutdown commencing. Flushing connections."); + + // Cleanup and flush everything. + serverENetHost.Flush(); + + // Kick everyone. + for (int i = 0; i < serverPeerArray.Length; i++) + { + if (!serverPeerArray[i].IsSet) continue; + serverPeerArray[i].DisconnectNow(0); + } + } + + if (setupInfo.Verbosity > 0) + Debug.Log("Ignorance: Server instance thread shutdown complete."); + + Library.Deinitialize(); + } + #endregion + + private void SetupRingBuffersIfNull() + { + Debug.Log($"Ignorance: Setting up ring buffers if they're not already created. " + + $"If they are already, this step will be skipped."); + + if (Incoming == null) + Incoming = new RingBuffer(IncomingOutgoingBufferSize); + if (Outgoing == null) + Outgoing = new RingBuffer(IncomingOutgoingBufferSize); + if (Commands == null) + Commands = new RingBuffer(100); + if (ConnectionEvents == null) + ConnectionEvents = new RingBuffer(ConnectionEventBufferSize); + if (DisconnectionEvents == null) + DisconnectionEvents = new RingBuffer(ConnectionEventBufferSize); + if (StatusUpdates == null) + StatusUpdates = new RingBuffer(10); + } + + private struct ThreadParamInfo + { + public bool IsFruityDevice; + public bool BindAllInterfaces; + public int Channels; + public int Peers; + public int PollTime; + public int Port; + public int PacketSizeLimit; + public int Verbosity; + public string Address; + } + } +} diff --git a/BeatTogether.DedicatedServer.Ignorance/IgnoranceThirdparty/RingBuffer.cs b/BeatTogether.DedicatedServer.Ignorance/IgnoranceThirdparty/RingBuffer.cs new file mode 100644 index 00000000..fd39f7f0 --- /dev/null +++ b/BeatTogether.DedicatedServer.Ignorance/IgnoranceThirdparty/RingBuffer.cs @@ -0,0 +1,278 @@ +// The following dependency was taken from https://github.com/dave-hillier/disruptor-unity3d +// The Apache License 2.0 this dependency follows is located at https://github.com/dave-hillier/disruptor-unity3d/blob/master/LICENSE. +// Modifications were made by SoftwareGuy (Coburn). + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace BeatTogether.DedicatedServer.Ignorance.IgnoranceThirdparty +{ + /// + /// Implementation of the Disruptor pattern + /// + /// the type of item to be stored + public class RingBuffer + { + private readonly T[] _entries; + private readonly int _modMask; + private Volatile.PaddedLong _consumerCursor = new Volatile.PaddedLong(); + private Volatile.PaddedLong _producerCursor = new Volatile.PaddedLong(); + + /// + /// Creates a new RingBuffer with the given capacity + /// + /// The capacity of the buffer + /// Only a single thread may attempt to consume at any one time + public RingBuffer(int capacity) + { + capacity = NextPowerOfTwo(capacity); + _modMask = capacity - 1; + _entries = new T[capacity]; + } + + /// + /// The maximum number of items that can be stored + /// + public int Capacity + { + get { return _entries.Length; } + } + + public T this[long index] + { + get { unchecked { return _entries[index & _modMask]; } } + set { unchecked { _entries[index & _modMask] = value; } } + } + + /// + /// Removes an item from the buffer. + /// + /// The next available item + public T Dequeue() + { + var next = _consumerCursor.ReadAcquireFence() + 1; + while (_producerCursor.ReadAcquireFence() < next) // makes sure we read the data from _entries after we have read the producer cursor + { + Thread.SpinWait(1); + } + var result = this[next]; + _consumerCursor.WriteReleaseFence(next); // makes sure we read the data from _entries before we update the consumer cursor + return result; + } + + /// + /// Attempts to remove an items from the queue + /// + /// the items + /// True if successful + public bool TryDequeue(out T obj) + { + var next = _consumerCursor.ReadAcquireFence() + 1; + + if (_producerCursor.ReadAcquireFence() < next) + { + obj = default(T); + return false; + } + obj = Dequeue(); + return true; + } + + /// + /// Add an item to the buffer + /// + /// + public void Enqueue(T item) + { + var next = _producerCursor.ReadAcquireFence() + 1; + + long wrapPoint = next - _entries.Length; + long min = _consumerCursor.ReadAcquireFence(); + + while (wrapPoint > min) + { + min = _consumerCursor.ReadAcquireFence(); + Thread.SpinWait(1); + } + + this[next] = item; + _producerCursor.WriteReleaseFence(next); // makes sure we write the data in _entries before we update the producer cursor + } + + /// + /// The number of items in the buffer + /// + /// for indicative purposes only, may contain stale data + public int Count { get { return (int)(_producerCursor.ReadFullFence() - _consumerCursor.ReadFullFence()); } } + + private static int NextPowerOfTwo(int x) + { + var result = 2; + while (result < x) + { + result <<= 1; + } + return result; + } + + + } + public static class Volatile + { + private const int CacheLineSize = 64; + + [StructLayout(LayoutKind.Explicit, Size = CacheLineSize * 2)] + public struct PaddedLong + { + [FieldOffset(CacheLineSize)] + private long _value; + + /// + /// Create a new with the given initial value. + /// + /// Initial value + public PaddedLong(long value) + { + _value = value; + } + + /// + /// Read the value without applying any fence + /// + /// The current value + public long ReadUnfenced() + { + return _value; + } + + /// + /// Read the value applying acquire fence semantic + /// + /// The current value + public long ReadAcquireFence() + { + var value = _value; + Thread.MemoryBarrier(); + return value; + } + + /// + /// Read the value applying full fence semantic + /// + /// The current value + public long ReadFullFence() + { + Thread.MemoryBarrier(); + return _value; + } + + /// + /// Read the value applying a compiler only fence, no CPU fence is applied + /// + /// The current value + [MethodImpl(MethodImplOptions.NoOptimization)] + public long ReadCompilerOnlyFence() + { + return _value; + } + + /// + /// Write the value applying release fence semantic + /// + /// The new value + public void WriteReleaseFence(long newValue) + { + Thread.MemoryBarrier(); + _value = newValue; + } + + /// + /// Write the value applying full fence semantic + /// + /// The new value + public void WriteFullFence(long newValue) + { + Thread.MemoryBarrier(); + _value = newValue; + } + + /// + /// Write the value applying a compiler fence only, no CPU fence is applied + /// + /// The new value + [MethodImpl(MethodImplOptions.NoOptimization)] + public void WriteCompilerOnlyFence(long newValue) + { + _value = newValue; + } + + /// + /// Write without applying any fence + /// + /// The new value + public void WriteUnfenced(long newValue) + { + _value = newValue; + } + + /// + /// Atomically set the value to the given updated value if the current value equals the comparand + /// + /// The new value + /// The comparand (expected value) + /// + public bool AtomicCompareExchange(long newValue, long comparand) + { + return Interlocked.CompareExchange(ref _value, newValue, comparand) == comparand; + } + + /// + /// Atomically set the value to the given updated value + /// + /// The new value + /// The original value + public long AtomicExchange(long newValue) + { + return Interlocked.Exchange(ref _value, newValue); + } + + /// + /// Atomically add the given value to the current value and return the sum + /// + /// The value to be added + /// The sum of the current value and the given value + public long AtomicAddAndGet(long delta) + { + return Interlocked.Add(ref _value, delta); + } + + /// + /// Atomically increment the current value and return the new value + /// + /// The incremented value. + public long AtomicIncrementAndGet() + { + return Interlocked.Increment(ref _value); + } + + /// + /// Atomically increment the current value and return the new value + /// + /// The decremented value. + public long AtomicDecrementAndGet() + { + return Interlocked.Decrement(ref _value); + } + + /// + /// Returns the string representation of the current value. + /// + /// the string representation of the current value. + public override string ToString() + { + var value = ReadFullFence(); + return value.ToString(); + } + } + } +} diff --git a/BeatTogether.DedicatedServer.Ignorance/LICENSES.md b/BeatTogether.DedicatedServer.Ignorance/LICENSES.md new file mode 100644 index 00000000..7456c4fc --- /dev/null +++ b/BeatTogether.DedicatedServer.Ignorance/LICENSES.md @@ -0,0 +1,56 @@ +# Ignorance +MIT License + +Copyright (c) 2019 - 2021 Matt Coburn (Coburn, SoftwareGuy) +This software uses dependencies (Mirror, ENet-C#) that are also licensed under +the MIT License. + +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. + +# ENet-CSharp +MIT License + +Copyright (c) 2018 Stanislav Denisov (nxrighthere@gmail.com) + +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. + +# ENet +Copyright (c) 2002-2020 Lee Salzman + +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. \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Ignorance/NativePlugins/enet.dll b/BeatTogether.DedicatedServer.Ignorance/NativePlugins/enet.dll new file mode 100644 index 0000000000000000000000000000000000000000..f75351bb69b3ce12b0691bf2644e54abdce77810 GIT binary patch literal 124928 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

vf|%ztV8BRoU22vRl& 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 a0KVt(UMgS3kzCAwYd>k(C*TnHX#6ji1*aSU literal 0 HcmV?d00001 diff --git a/BeatTogether.DedicatedServer.Ignorance/README.md b/BeatTogether.DedicatedServer.Ignorance/README.md new file mode 100644 index 00000000..b9b233b8 --- /dev/null +++ b/BeatTogether.DedicatedServer.Ignorance/README.md @@ -0,0 +1,5 @@ +# BeatTogether.DedicatedServer.Ignorance +This library wraps ENet for use with the BeatTogether dedicated server. + +**Based on Ignorance [1.4.0r2 (LTS)](https://github.com/SoftwareGuy/Ignorance/releases/tag/v1.4.0r2).** + diff --git a/BeatTogether.DedicatedServer.Ignorance/Util/IgnoranceDebug.cs b/BeatTogether.DedicatedServer.Ignorance/Util/IgnoranceDebug.cs new file mode 100644 index 00000000..1406fe2c --- /dev/null +++ b/BeatTogether.DedicatedServer.Ignorance/Util/IgnoranceDebug.cs @@ -0,0 +1,20 @@ + +// ReSharper disable TemplateIsNotCompileTimeConstantProblem + +using Serilog; + +namespace BeatTogether.DedicatedServer.Ignorance.Util; + +public static class IgnoranceDebug +{ + public static ILogger? Logger = null; + + public static void Log(string message) => + Logger?.Verbose(message); + + public static void LogWarning(string message) => + Logger?.Warning(message); + + public static void LogError(string message) => + Logger?.Error(message); +} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.sln b/BeatTogether.DedicatedServer.sln index be9c0639..ed19c0a4 100644 --- a/BeatTogether.DedicatedServer.sln +++ b/BeatTogether.DedicatedServer.sln @@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BeatTogether.DedicatedServe EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BeatTogether.DedicatedServer.Node", "BeatTogether.DedicatedServer.Node\BeatTogether.DedicatedServer.Node.csproj", "{D2B3DC3B-FECD-4E06-8B20-7A60A0BE3C2E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeatTogether.DedicatedServer.Ignorance", "BeatTogether.DedicatedServer.Ignorance\BeatTogether.DedicatedServer.Ignorance.csproj", "{775C10CC-FE88-41DD-A9E3-7F66CBA87470}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -39,6 +41,10 @@ Global {D2B3DC3B-FECD-4E06-8B20-7A60A0BE3C2E}.Debug|Any CPU.Build.0 = Debug|Any CPU {D2B3DC3B-FECD-4E06-8B20-7A60A0BE3C2E}.Release|Any CPU.ActiveCfg = Release|Any CPU {D2B3DC3B-FECD-4E06-8B20-7A60A0BE3C2E}.Release|Any CPU.Build.0 = Release|Any CPU + {775C10CC-FE88-41DD-A9E3-7F66CBA87470}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {775C10CC-FE88-41DD-A9E3-7F66CBA87470}.Debug|Any CPU.Build.0 = Debug|Any CPU + {775C10CC-FE88-41DD-A9E3-7F66CBA87470}.Release|Any CPU.ActiveCfg = Release|Any CPU + {775C10CC-FE88-41DD-A9E3-7F66CBA87470}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 66fb399a60c90c6667fbbf581e1cdff4eb9471f9 Mon Sep 17 00:00:00 2001 From: Roy de Jong Date: Fri, 7 Jul 2023 22:13:34 +0200 Subject: [PATCH 017/120] wip(1.31): interface 1.7 - create server response - ENet endpoint --- .../BeatTogether.DedicatedServer.Interface.csproj | 2 +- .../Responses/CreateMatchmakingServerResponse.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj b/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj index ec8bfa1c..b4e0e97a 100644 --- a/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj +++ b/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj @@ -7,7 +7,7 @@ BeatTogether Team BeatTogether https://github.com/beattogether/BeatTogether.DedicatedServer - 1.6.0 + 1.7.0 enable diff --git a/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs b/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs index 3a122e1f..b80ad625 100644 --- a/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs +++ b/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs @@ -11,7 +11,8 @@ public record CreateMatchmakingServerResponse( CreateMatchmakingServerError Error, string? RemoteEndPoint = null, byte[]? Random = null, - byte[]? PublicKey = null) + byte[]? PublicKey = null, + string? RemoteEndPointENet = null) { public bool Success => Error == default; } From 8aedf66db89a0af3553526cfe9b06ed4ad433309 Mon Sep 17 00:00:00 2001 From: Roy de Jong Date: Fri, 7 Jul 2023 22:31:37 +0200 Subject: [PATCH 018/120] nuget action: run on dev-1.31.0 branch (cherry picked from commit c342ba4e5173d1303a8fb1f0924095a6ef4a0468) --- .github/workflows/nuget.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index ce8f7c53..e82de237 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -6,6 +6,7 @@ on: - dev - dev-1.29 - dev-1.29-Net6.0 + - dev-1.31.0 jobs: nuget-1: From fa271cdca51052190f7471fde805e462bf1eff9a Mon Sep 17 00:00:00 2001 From: Roy de Jong Date: Fri, 7 Jul 2023 23:38:42 +0200 Subject: [PATCH 019/120] wip(1.31): enet companion socket / basic connectivity --- ...tTogether.DedicatedServer.Ignorance.csproj | 4 +- .../{NativePlugins => }/enet.dll | Bin .../{NativePlugins => }/libenet.so | Bin .../Abstractions/IDedicatedInstance.cs | 3 +- ...BeatTogether.DedicatedServer.Kernel.csproj | 1 + .../Configuration/InstanceConfiguration.cs | 3 +- .../DedicatedInstance.cs | 46 ++-- .../ENet/ENetConnection.cs | 30 +++ .../ENet/ENetServer.cs | 227 ++++++++++++++++++ .../InstanceFactory.cs | 16 +- .../NodeService.cs | 17 +- 11 files changed, 311 insertions(+), 36 deletions(-) rename BeatTogether.DedicatedServer.Ignorance/{NativePlugins => }/enet.dll (100%) rename BeatTogether.DedicatedServer.Ignorance/{NativePlugins => }/libenet.so (100%) create mode 100644 BeatTogether.DedicatedServer.Kernel/ENet/ENetConnection.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs diff --git a/BeatTogether.DedicatedServer.Ignorance/BeatTogether.DedicatedServer.Ignorance.csproj b/BeatTogether.DedicatedServer.Ignorance/BeatTogether.DedicatedServer.Ignorance.csproj index 5c05fc32..4b847eb4 100644 --- a/BeatTogether.DedicatedServer.Ignorance/BeatTogether.DedicatedServer.Ignorance.csproj +++ b/BeatTogether.DedicatedServer.Ignorance/BeatTogether.DedicatedServer.Ignorance.csproj @@ -7,10 +7,10 @@ - + Always - + Always diff --git a/BeatTogether.DedicatedServer.Ignorance/NativePlugins/enet.dll b/BeatTogether.DedicatedServer.Ignorance/enet.dll similarity index 100% rename from BeatTogether.DedicatedServer.Ignorance/NativePlugins/enet.dll rename to BeatTogether.DedicatedServer.Ignorance/enet.dll diff --git a/BeatTogether.DedicatedServer.Ignorance/NativePlugins/libenet.so b/BeatTogether.DedicatedServer.Ignorance/libenet.so similarity index 100% rename from BeatTogether.DedicatedServer.Ignorance/NativePlugins/libenet.so rename to BeatTogether.DedicatedServer.Ignorance/libenet.so diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs index 0c7c2386..737ba85a 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs @@ -28,7 +28,8 @@ public interface IDedicatedInstance InstanceConfiguration _configuration { get; } bool IsRunning { get; } float RunTime { get; } - int Port { get; } + public int LiteNetPort { get; } + public int ENetPort { get; } MultiplayerGameState State { get; } float NoPlayersTime { get; } diff --git a/BeatTogether.DedicatedServer.Kernel/BeatTogether.DedicatedServer.Kernel.csproj b/BeatTogether.DedicatedServer.Kernel/BeatTogether.DedicatedServer.Kernel.csproj index a7f9ea63..b5a15957 100644 --- a/BeatTogether.DedicatedServer.Kernel/BeatTogether.DedicatedServer.Kernel.csproj +++ b/BeatTogether.DedicatedServer.Kernel/BeatTogether.DedicatedServer.Kernel.csproj @@ -21,6 +21,7 @@ + diff --git a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs index dd9c69ff..aae810d8 100644 --- a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs +++ b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs @@ -4,7 +4,8 @@ namespace BeatTogether.DedicatedServer.Kernel.Configuration { public sealed class InstanceConfiguration { - public int Port { get; set; } + public int LiteNetPort { get; set; } + public int ENetPort { get; set; } public string Secret { get; set; } = string.Empty; public string ServerOwnerId { get; set; } = string.Empty; public string ServerId { get; set; } = "ziuMSceapEuNN7wRGQXrZg"; diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index e835f9c6..4d4c0b1a 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -2,12 +2,12 @@ using System.Collections.Concurrent; using System.Linq; using System.Net; -using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Kernel.Encryption; +using BeatTogether.DedicatedServer.Kernel.ENet; using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; @@ -32,6 +32,8 @@ public sealed class DedicatedInstance : LiteNetServer, IDedicatedInstance public const int SyncTimeDelay = 5000; public InstanceConfiguration _configuration { get; private set; } + public int LiteNetPort => _configuration.LiteNetPort; + public int ENetPort => _configuration.ENetPort; public bool IsRunning => IsStarted; public float RunTime => (DateTime.UtcNow.Ticks - _startTime) / 10000000.0f; public float NoPlayersTime { get; private set; } = -1; //tracks the instance time once there are 0 players in the lobby @@ -59,6 +61,8 @@ public sealed class DedicatedInstance : LiteNetServer, IDedicatedInstance private CancellationTokenSource? _stopServerCts; private IPacketDispatcher _packetDispatcher = null!; + private ENetServer _eNetServer; + public DedicatedInstance( InstanceConfiguration configuration, IHandshakeSessionRegistry handshakeSessionRegistry, @@ -69,7 +73,7 @@ public DedicatedInstance( IPacketLayer packetLayer, PacketEncryptionLayer packetEncryptionLayer) : base ( - new IPEndPoint(IPAddress.Any, configuration.Port), + new IPEndPoint(IPAddress.Any, configuration.LiteNetPort), liteNetConfiguration, registry, serviceProvider, @@ -81,6 +85,8 @@ public DedicatedInstance( _playerRegistry = playerRegistry; _serviceProvider = serviceProvider; _packetEncryptionLayer = packetEncryptionLayer; + + _eNetServer = new(this, configuration.ENetPort); } #region Public Methods @@ -99,17 +105,17 @@ public IServiceProvider GetServiceProvider() return _serviceProvider; } - public Task Start(CancellationToken cancellationToken = default) + public async Task Start(CancellationToken cancellationToken = default) { if (IsRunning) - return Task.CompletedTask; + return; _packetDispatcher = _serviceProvider.GetRequiredService(); _startTime = DateTime.UtcNow.Ticks; _logger.Information( "Starting dedicated server " + - $"(Port={Port}," + + "(Endpoint={Endpoint}," + $"ServerName='{_configuration.ServerName}', " + $"Secret='{_configuration.Secret}', " + $"ManagerId='{_configuration.ServerOwnerId}', " + @@ -118,16 +124,19 @@ public Task Start(CancellationToken cancellationToken = default) $"InvitePolicy={_configuration.InvitePolicy}, " + $"GameplayServerMode={_configuration.GameplayServerMode}, " + $"SongSelectionMode={_configuration.SongSelectionMode}, " + - $"GameplayServerControlSettings={_configuration.GameplayServerControlSettings})." + $"GameplayServerControlSettings={_configuration.GameplayServerControlSettings})", + Endpoint ); _stopServerCts = new CancellationTokenSource(); - - - - if (_configuration.DestroyInstanceTimeout != -1) + + if (_configuration.DestroyInstanceTimeout >= 0) { _waitForPlayerCts = new CancellationTokenSource(); - Task.Delay((WaitForPlayerTimeLimit + (int)(_configuration.DestroyInstanceTimeout * 1000)), _waitForPlayerCts.Token).ContinueWith(t => + + var waitTimeLimit = (WaitForPlayerTimeLimit + (int)(_configuration.DestroyInstanceTimeout * 1000)); + + _ = Task.Delay(waitTimeLimit, _waitForPlayerCts.Token) + .ContinueWith(t => { if (!t.IsCanceled) { @@ -141,17 +150,16 @@ public Task Start(CancellationToken cancellationToken = default) }, cancellationToken); } - //StartEvent?.Invoke(this); - base.Start(); - Task.Run(() => SendSyncTime(_stopServerCts.Token), cancellationToken); - return Task.CompletedTask; + await _eNetServer.Start(); + + _ = Task.Run(() => SendSyncTime(_stopServerCts.Token), cancellationToken); } - public Task Stop(CancellationToken cancellationToken = default) + public async Task Stop(CancellationToken cancellationToken = default) { if (!IsRunning) - return Task.CompletedTask; + return; _logger.Information( "Stopping dedicated server " + @@ -172,10 +180,12 @@ public Task Stop(CancellationToken cancellationToken = default) }, DeliveryMethod.ReliableOrdered); _stopServerCts!.Cancel(); + _waitForPlayerCts!.Cancel(); + StopEvent?.Invoke(this); base.Stop(); - return Task.CompletedTask; + await _eNetServer.Stop(); } object SortIndexLock = new(); diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetConnection.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetConnection.cs new file mode 100644 index 00000000..d3922732 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetConnection.cs @@ -0,0 +1,30 @@ +using System.Net; + +namespace BeatTogether.DedicatedServer.Kernel.ENet +{ + public class ENetConnection + { + public ENetServer ENetServer { get; private set; } + public uint NativePeerId { get; private set; } + public IPEndPoint EndPoint { get; private set; } + public ENetConnectionState State { get; set; } + + public ENetConnection(ENetServer eNetServer, uint nativePeerId, string ip, int port) + { + ENetServer = eNetServer; + NativePeerId = nativePeerId; + EndPoint = new IPEndPoint(IPAddress.Parse(ip), port); + State = ENetConnectionState.Pending; + } + + public void Disconnect(bool clientInitiated = false) + => ENetServer.KickPeer(NativePeerId, sendKick: !clientInitiated); + } + + public enum ENetConnectionState + { + Pending = 0, + Accepted = 1, + Disconnected = 2 + } +} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs new file mode 100644 index 00000000..56bbe4e7 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs @@ -0,0 +1,227 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Ignorance.Util; +using BeatTogether.LiteNetLib.Extensions; +using Krypton.Buffers; +using Serilog; + +namespace BeatTogether.DedicatedServer.Kernel.ENet +{ + ///

+ /// Temporary secondary server/socket for ENet (1.31+) connectivity. + /// + public class ENetServer : IDisposable + { + public readonly DedicatedInstance DedicatedInstance; + public readonly int Port; + + private readonly IgnoranceServer _ignorance; + private readonly ILogger _logger; + private CancellationTokenSource _runtimeCts; + private readonly Thread _workerThread; + private readonly Dictionary _connections; + private readonly byte[] _receiveBufferMemory; + + public IPEndPoint EndPoint => new(IPAddress.Any, Port); + public bool IsAlive => _ignorance.IsAlive; + + public ENetServer(DedicatedInstance dedicatedInstance, int port) + { + DedicatedInstance = dedicatedInstance; + Port = port; + + _ignorance = new IgnoranceServer(); + _logger = Log.ForContext(); + _runtimeCts = new(); + _workerThread = new(ThreadWorker); + _connections = new(); + _receiveBufferMemory = GC.AllocateArray(length: _ignorance.IncomingOutgoingBufferSize, pinned: true); + + IgnoranceDebug.Logger = _logger; + } + + #region Start / Stop + + public async Task Start() + { + await Stop(); + + _runtimeCts = new(); + + _logger.Information("Starting companion ENet socket (Endpoint={Endpoint})", EndPoint); + + _ignorance.BindPort = Port; + _ignorance.BindAddress = IPAddress.Any.ToString(); + _ignorance.BindAllInterfaces = true; + _ignorance.Start(); + + _workerThread.Start(); + } + + public async Task Stop() + { + _runtimeCts.Cancel(); + _ignorance.Stop(); + + while (_ignorance.IsAlive) + await Task.Delay(1); + } + + public void Dispose() + { + _runtimeCts.Cancel(); + _ignorance.Stop(); + } + + #endregion + + private void ThreadWorker() + { + _connections.Clear(); + + while (!_runtimeCts!.IsCancellationRequested) + { + HandleConnectionEvents(); + HandleDisconnectionEvents(); + HandleIncomingEvents(); + + Thread.Sleep(1); + } + } + + #region Ignorance event queues + + private void HandleConnectionEvents() + { + var ctsToken = _runtimeCts!.Token; + + while (!ctsToken.IsCancellationRequested + && (_ignorance.ConnectionEvents?.TryDequeue(out var e) ?? false)) + { + CreateConnection(e); + } + } + + private void HandleDisconnectionEvents() + { + var ctsToken = _runtimeCts!.Token; + + while (!ctsToken.IsCancellationRequested + && (_ignorance.DisconnectionEvents?.TryDequeue(out var e) ?? false)) + { + if (_connections.TryGetValue(e.NativePeerId, out var connection)) + connection.Disconnect(true); + } + } + + private void HandleIncomingEvents() + { + var ctsToken = _runtimeCts!.Token; + + while (!ctsToken.IsCancellationRequested + && (_ignorance.Incoming?.TryDequeue(out var e) ?? false)) + { + if (!_connections.TryGetValue(e.NativePeerId, out var connection) || connection.State == ENetConnectionState.Disconnected) + { + // Connection not established, ignore incoming + e.Payload.Dispose(); + continue; + } + + // Read incoming into buffer + var receiveLength = e.Payload.Length; + e.Payload.CopyTo(_receiveBufferMemory, 0); + e.Payload.Dispose(); + + var bufferReader = new SpanBufferReader(_receiveBufferMemory.AsSpan(..receiveLength)); + + // If pending, try to accept connection (IgnCon request) + if (connection.State == ENetConnectionState.Pending) + { + if (!TryAcceptConnection(connection, ref bufferReader)) + { + connection.Disconnect(); + continue; + } + } + + // Read actual payload... + // TODO + } + } + + #endregion + + #region Connections + + private ENetConnection CreateConnection(IgnoranceConnectionEvent e) + { + KickPeer(e.NativePeerId); // clean up any previous use of peer ID + + var connection = new ENetConnection(this, e.NativePeerId, e.IP, e.Port); + _connections[e.NativePeerId] = connection; + + _logger.Information("Incoming ENet connection (PeerId={PeerId}, EndPoint={EndPoint})", + connection.NativePeerId, connection.EndPoint); + + return connection; + } + + private bool TryAcceptConnection(ENetConnection connection, ref SpanBufferReader reader) + { + try + { + // First packet from pending connection: should be IgnCon request + var requestPrefix = reader.ReadString(); + + if (requestPrefix != "IgnCon") + { + _logger.Warning("Invalid first ENet msg: bad prefix string"); + return false; + } + + // Continue with regular accept flow (remainder is regular GameLift connection request) + if (DedicatedInstance.ShouldAcceptConnection(connection.EndPoint, ref reader)) + { + connection.State = ENetConnectionState.Accepted; + return true; + } + } + catch (EndOfBufferException) + { + // Invalid connection request - read/length error + _logger.Warning("Invalid first ENet msg: length read error"); + } + + return false; + } + + public void KickPeer(uint peerId, bool sendKick = true) + { + if (!_connections.TryGetValue(peerId, out var connection) || !_connections.Remove(peerId)) + // Connection not established + return; + + _logger.Information("Closing ENet connection (PeerId={PeerId}, EndPoint={Port})", + connection.NativePeerId, connection.EndPoint); + + connection.State = ENetConnectionState.Disconnected; + + if (!IsAlive || !sendKick) + // Can't or won't send kick + return; + + _ignorance.Commands.Enqueue(new IgnoranceCommandPacket() + { + Type = IgnoranceCommandType.ServerKickPeer, + PeerId = peerId + }); + } + + #endregion + } +} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs index 00b6d410..45ed2245 100644 --- a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs +++ b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs @@ -1,10 +1,10 @@ -using BeatTogether.DedicatedServer.Interface.Models; +using System; +using BeatTogether.DedicatedServer.Interface.Models; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Node.Abstractions; using Microsoft.Extensions.DependencyInjection; -using System; namespace BeatTogether.DedicatedServer.Node { @@ -41,14 +41,17 @@ public InstanceFactory( bool AllowNE ) { - var port = _portAllocator.AcquirePort(); - if (!port.HasValue) + var liteNetPort = _portAllocator.AcquirePort(); + var eNetPort = _portAllocator.AcquirePort(); + + if (!liteNetPort.HasValue || !eNetPort.HasValue) return null; var scope = _serviceProvider.CreateScope(); var instanceConfig = scope.ServiceProvider.GetRequiredService(); - instanceConfig.Port = (int)port!; + instanceConfig.LiteNetPort = (int)liteNetPort!; + instanceConfig.ENetPort = (int)eNetPort!; instanceConfig.Secret = secret; instanceConfig.ServerOwnerId = managerId; instanceConfig.MaxPlayerCount = Math.Min(config.MaxPlayerCount,250); //max size of 254, id 127 routes packets to all, max is 250, last 4 ID's will be reserved for future features @@ -81,7 +84,8 @@ bool AllowNE private void HandleStopEvent(IDedicatedInstance Instance) { _instanceRegistry.RemoveInstance(Instance); - _portAllocator.ReleasePort(Instance.Port); + _portAllocator.ReleasePort(Instance.LiteNetPort); + _portAllocator.ReleasePort(Instance.ENetPort); } } } diff --git a/BeatTogether.DedicatedServer.Node/NodeService.cs b/BeatTogether.DedicatedServer.Node/NodeService.cs index 2ec32121..ac6f1af4 100644 --- a/BeatTogether.DedicatedServer.Node/NodeService.cs +++ b/BeatTogether.DedicatedServer.Node/NodeService.cs @@ -1,17 +1,17 @@ -using Autobus; +using System; +using System.Net; +using System.Threading.Tasks; +using Autobus; using BeatTogether.DedicatedServer.Interface; using BeatTogether.DedicatedServer.Interface.Events; using BeatTogether.DedicatedServer.Interface.Requests; using BeatTogether.DedicatedServer.Interface.Responses; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Encryption; +using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Node.Abstractions; using BeatTogether.DedicatedServer.Node.Configuration; -using BeatTogether.DedicatedServer.Kernel.Abstractions; using Serilog; -using System; -using System.Threading.Tasks; -using System.Net; -using BeatTogether.DedicatedServer.Messaging.Models; namespace BeatTogether.DedicatedServer.Node { @@ -80,9 +80,10 @@ public async Task CreateMatchmakingServer(Creat await matchmakingServer.Start(); return new CreateMatchmakingServerResponse( CreateMatchmakingServerError.None, - $"{_configuration.HostName}:{matchmakingServer.Port}", + $"{_configuration.HostName}:{matchmakingServer.LiteNetPort}", _packetEncryptionLayer.Random, - _packetEncryptionLayer.KeyPair.PublicKey + _packetEncryptionLayer.KeyPair.PublicKey, + $"{_configuration.HostName}:{matchmakingServer.ENetPort}" ); } From 5a79092c7e01d311bdbbb8b6fcfe86ff9bf14411 Mon Sep 17 00:00:00 2001 From: Roy de Jong Date: Sat, 8 Jul 2023 23:16:25 +0200 Subject: [PATCH 020/120] wip(1.31): enet - resize buffer, attach peerid to player --- .../Abstractions/IPlayer.cs | 9 +++- .../DedicatedInstance.cs | 28 +++++++---- .../ENet/ENetServer.cs | 46 ++++++++++++++++--- BeatTogether.DedicatedServer.Kernel/Player.cs | 9 +++- 4 files changed, 74 insertions(+), 18 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index a89c49f1..e4619bc1 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -1,7 +1,7 @@ -using BeatTogether.DedicatedServer.Kernel.Types; +using System.Net; +using BeatTogether.DedicatedServer.Kernel.Types; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; -using System.Net; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { @@ -14,8 +14,13 @@ public interface IPlayer string Secret { get; } string UserId { get; } string UserName { get; } + string? PlayerSessionId { get; } + byte[]? Random { get; set; } byte[]? PublicEncryptionKey { get; set; } + + uint? ENetPeerId { get; set; } + bool IsENetConnection => ENetPeerId.HasValue; object LatencyLock { get; set; } RollingAverage Latency { get; } diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 4d4c0b1a..24e71c74 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -242,19 +242,29 @@ public void SetState(MultiplayerGameState state) object AcceptConnectionLock = new(); + /// + /// LiteNetServer call for filtering incoming connections. + /// public override bool ShouldAcceptConnection(EndPoint endPoint, ref SpanBufferReader additionalData) { + var player = TryAcceptConnection(endPoint, ref additionalData); - if (ShouldDenyConnection(endPoint, ref additionalData)) + if (player == null) { PlayerDisconnectBeforeJoining?.Invoke(_configuration.Secret, endPoint, _playerRegistry.GetPlayerCount()); return false; } + return true; } - public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBufferReader additionalData) + + /// + /// Attempts to accept an incoming connection into a player, parsing a connection request from the game. + /// + public Player? TryAcceptConnection(EndPoint endPoint, ref SpanBufferReader additionalData) { var connectionRequestData = new ConnectionRequestData(); + try { connectionRequestData.ReadFrom(ref additionalData); @@ -265,7 +275,7 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBufferReader additio "Failed to deserialize connection request data " + $"(RemoteEndPoint='{endPoint}')." ); - return true; + return null; } _logger.Debug( @@ -289,19 +299,21 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBufferReader additio $"UserName='{connectionRequestData.UserName}', " + $"IsConnectionOwner={connectionRequestData.IsConnectionOwner})." ); - return true; + return null; } + + Player player; lock (AcceptConnectionLock) { if (_playerRegistry.GetPlayerCount() >= _configuration.MaxPlayerCount) { - return true; + return null; } int sortIndex = GetNextSortIndex(); byte connectionId = GetNextConnectionId(); - var player = new Player( + player = new Player( endPoint, this, connectionId, @@ -318,7 +330,7 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBufferReader additio { ReleaseSortIndex(player.SortIndex); ReleaseConnectionId(player.ConnectionId); - return true; + return null; } _logger.Information( "Player joined dedicated server " + @@ -347,7 +359,7 @@ public bool ShouldDenyConnection(EndPoint endPoint, ref SpanBufferReader additio } } - return false; + return player; } public override void OnLatencyUpdate(EndPoint endPoint, int latency) diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs index 56bbe4e7..dec24c86 100644 --- a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.Collections.Generic; using System.Net; using System.Threading; @@ -24,7 +25,8 @@ public class ENetServer : IDisposable private CancellationTokenSource _runtimeCts; private readonly Thread _workerThread; private readonly Dictionary _connections; - private readonly byte[] _receiveBufferMemory; + + private byte[]? _receiveBuffer; public IPEndPoint EndPoint => new(IPAddress.Any, Port); public bool IsAlive => _ignorance.IsAlive; @@ -39,7 +41,8 @@ public ENetServer(DedicatedInstance dedicatedInstance, int port) _runtimeCts = new(); _workerThread = new(ThreadWorker); _connections = new(); - _receiveBufferMemory = GC.AllocateArray(length: _ignorance.IncomingOutgoingBufferSize, pinned: true); + + EnsureReceiveBufferSize(_ignorance.IncomingOutgoingBufferSize); IgnoranceDebug.Logger = _logger; } @@ -134,10 +137,11 @@ private void HandleIncomingEvents() // Read incoming into buffer var receiveLength = e.Payload.Length; - e.Payload.CopyTo(_receiveBufferMemory, 0); + EnsureReceiveBufferSize(receiveLength); + e.Payload.CopyTo(_receiveBuffer, 0); e.Payload.Dispose(); - var bufferReader = new SpanBufferReader(_receiveBufferMemory.AsSpan(..receiveLength)); + var bufferReader = new SpanBufferReader(_receiveBuffer.AsSpan(..receiveLength)); // If pending, try to accept connection (IgnCon request) if (connection.State == ENetConnectionState.Pending) @@ -145,7 +149,7 @@ private void HandleIncomingEvents() if (!TryAcceptConnection(connection, ref bufferReader)) { connection.Disconnect(); - continue; + return; } } @@ -185,8 +189,12 @@ private bool TryAcceptConnection(ENetConnection connection, ref SpanBufferReader } // Continue with regular accept flow (remainder is regular GameLift connection request) - if (DedicatedInstance.ShouldAcceptConnection(connection.EndPoint, ref reader)) + var player = DedicatedInstance.TryAcceptConnection(connection.EndPoint, ref reader); + + if (player != null) { + // Accept success + player.ENetPeerId = connection.NativePeerId; connection.State = ENetConnectionState.Accepted; return true; } @@ -223,5 +231,31 @@ public void KickPeer(uint peerId, bool sendKick = true) } #endregion + + #region Buffer + + private void EnsureReceiveBufferSize(int length) + { + if (length >= _ignorance.MaximumPacketSize) + throw new ArgumentException("Receive buffer size should never exceed MaximumPacketSize"); + + if (_receiveBuffer != null && _receiveBuffer.Length >= length) + // Buffer does not need adjusting + return; + + ReturnReceiveBuffer(); + _receiveBuffer = ArrayPool.Shared.Rent(length); + } + + private void ReturnReceiveBuffer() + { + if (_receiveBuffer != null) + { + ArrayPool.Shared.Return(_receiveBuffer); + _receiveBuffer = null; + } + } + + #endregion } } \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index edc3f743..64ba100d 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -18,6 +18,13 @@ public sealed class Player : IPlayer public string UserId { get; } public string UserName { get; } public string? PlayerSessionId { get; } + + public byte[]? Random { get; set; } + public byte[]? PublicEncryptionKey { get; set; } + + public uint? ENetPeerId { get; set; } + public bool IsENetConnection => ENetPeerId.HasValue; + public object LatencyLock { get; set; } = new(); public RollingAverage Latency { get; } = new(30); public float SyncTime => @@ -25,8 +32,6 @@ public sealed class Player : IPlayer Instance.RunTime); public object SortLock { get; set; } = new(); public int SortIndex { get; set; } - public byte[]? Random { get; set; } - public byte[]? PublicEncryptionKey { get; set; } public object PlayerIdentityLock { get; set; } = new(); public AvatarData Avatar { get; set; } = new(); public object ReadyLock { get; set; } = new(); From e46d241d335d05201febd7ced588627b82354bd9 Mon Sep 17 00:00:00 2001 From: Roy de Jong Date: Sun, 9 Jul 2023 00:25:54 +0200 Subject: [PATCH 021/120] wip(1.31): enet - packet receive, join/leave events --- .../DedicatedInstance.cs | 39 +++++++++++-------- .../ENet/ENetServer.cs | 22 +++++++---- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 24e71c74..6b23120c 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -17,6 +17,7 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Configuration; using BeatTogether.LiteNetLib.Enums; +using BeatTogether.LiteNetLib.Sources; using Krypton.Buffers; using Microsoft.Extensions.DependencyInjection; using Serilog; @@ -59,7 +60,9 @@ public sealed class DedicatedInstance : LiteNetServer, IDedicatedInstance private int _lastSortIndex = -1; private CancellationTokenSource? _waitForPlayerCts = null; private CancellationTokenSource? _stopServerCts; - private IPacketDispatcher _packetDispatcher = null!; + + public IPacketDispatcher PacketDispatcher { get; private set; } + public ConnectedMessageSource ConnectedMessageSource { get; private set; } private ENetServer _eNetServer; @@ -110,7 +113,9 @@ public async Task Start(CancellationToken cancellationToken = default) if (IsRunning) return; - _packetDispatcher = _serviceProvider.GetRequiredService(); + PacketDispatcher = _serviceProvider.GetRequiredService(); + ConnectedMessageSource = _serviceProvider.GetRequiredService(); + _startTime = DateTime.UtcNow.Ticks; _logger.Information( @@ -140,7 +145,8 @@ public async Task Start(CancellationToken cancellationToken = default) { if (!t.IsCanceled) { - _logger.Warning("Stopping instance: " + _configuration.ServerName); + _logger.Warning("Stopping instance (no players joined timeout): {Instance}", + _configuration.ServerName); _ = Stop(CancellationToken.None); } else @@ -174,7 +180,7 @@ public async Task Stop(CancellationToken cancellationToken = default) $"SongSelectionMode={_configuration.SongSelectionMode}, " + $"GameplayServerControlSettings={_configuration.GameplayServerControlSettings})." ); - _packetDispatcher.SendToNearbyPlayers(new KickPlayerPacket + PacketDispatcher.SendToNearbyPlayers(new KickPlayerPacket { DisconnectedReason = DisconnectedReason.ServerTerminated }, DeliveryMethod.ReliableOrdered); @@ -229,7 +235,7 @@ public void ReleaseConnectionId(byte connectionId) => public void SetState(MultiplayerGameState state) { State = state; - _packetDispatcher.SendToNearbyPlayers(new SetMultiplayerGameStatePacket() + PacketDispatcher.SendToNearbyPlayers(new SetMultiplayerGameStatePacket() { State = state }, DeliveryMethod.ReliableOrdered); @@ -383,7 +389,7 @@ public override void OnConnect(EndPoint endPoint) } //Send to existing players that a new player has joined - _packetDispatcher.SendExcludingPlayer(player, new INetSerializable[] + PacketDispatcher.SendExcludingPlayer(player, new INetSerializable[] { new SyncTimePacket { @@ -405,7 +411,7 @@ public override void OnConnect(EndPoint endPoint) ,DeliveryMethod.ReliableOrdered); //Send new player their sort order and other data - _packetDispatcher.SendToPlayer(player, new INetSerializable[] + PacketDispatcher.SendToPlayer(player, new INetSerializable[] { new SyncTimePacket { @@ -436,7 +442,7 @@ public override void OnConnect(EndPoint endPoint) if (p.ConnectionId != player.ConnectionId) { // Send all player connection data packets to new player - _packetDispatcher.SendToPlayer(player,new INetSerializable[]{ + PacketDispatcher.SendToPlayer(player,new INetSerializable[]{ new PlayerConnectedPacket { RemoteConnectionId = p.ConnectionId, @@ -452,7 +458,7 @@ public override void OnConnect(EndPoint endPoint) }, DeliveryMethod.ReliableOrdered); // Send all player identity packets to new player - _packetDispatcher.SendFromPlayerToPlayer(p, player, new PlayerIdentityPacket + PacketDispatcher.SendFromPlayerToPlayer(p, player, new PlayerIdentityPacket { PlayerState = p.State, PlayerAvatar = p.Avatar, @@ -468,7 +474,7 @@ public override void OnConnect(EndPoint endPoint) _configuration.ServerOwnerId = player.UserId; } - _packetDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket + PacketDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket { PermissionConfiguration = new PlayersPermissionConfiguration { @@ -494,7 +500,7 @@ public void DisconnectPlayer(string UserId) lock (DisconnectplayerLock) { if(_playerRegistry.TryGetPlayer(UserId, out var player)) - _packetDispatcher.SendToPlayer(player, new KickPlayerPacket + PacketDispatcher.SendToPlayer(player, new KickPlayerPacket { DisconnectedReason = DisconnectedReason.Kicked }, DeliveryMethod.ReliableOrdered); @@ -522,7 +528,7 @@ public override void OnDisconnect(EndPoint endPoint, DisconnectReason reason) { if (_playerRegistry.TryGetPlayer(endPoint, out var player)) { - _packetDispatcher.SendFromPlayer(player, new PlayerDisconnectedPacket + PacketDispatcher.SendFromPlayer(player, new PlayerDisconnectedPacket { DisconnectedReason = DisconnectedReason.ClientConnectionClosed }, DeliveryMethod.ReliableOrdered); @@ -548,7 +554,8 @@ public override void OnDisconnect(EndPoint endPoint, DisconnectReason reason) { if (!t.IsCanceled && _playerRegistry.GetPlayerCount() == 0) { - _logger.Information("No players joined within the closing timeout, stopping lobby now"); + _logger.Warning("Stopping instance (all players left timeout): {Instance}", + _configuration.ServerName); _ = Stop(CancellationToken.None); } else @@ -568,13 +575,13 @@ public override void OnDisconnect(EndPoint endPoint, DisconnectReason reason) // Disable start button if they are server owner without selected song if (serverOwner.BeatmapIdentifier == null) - _packetDispatcher.SendToPlayer(serverOwner, new SetIsStartButtonEnabledPacket + PacketDispatcher.SendToPlayer(serverOwner, new SetIsStartButtonEnabledPacket { Reason = CannotStartGameReason.NoSongSelected }, DeliveryMethod.ReliableOrdered); // Update permissions - _packetDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket + PacketDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket { PermissionConfiguration = new PlayersPermissionConfiguration { @@ -601,7 +608,7 @@ private async void SendSyncTime(CancellationToken cancellationToken) { foreach (IPlayer player in _playerRegistry.Players) { - _packetDispatcher.SendToPlayer(player, new SyncTimePacket() + PacketDispatcher.SendToPlayer(player, new SyncTimePacket() { SyncTime = player.SyncTime }, DeliveryMethod.ReliableOrdered); diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs index dec24c86..13817280 100644 --- a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Ignorance.Util; +using BeatTogether.LiteNetLib.Enums; using BeatTogether.LiteNetLib.Extensions; using Krypton.Buffers; using Serilog; @@ -78,6 +79,8 @@ public void Dispose() { _runtimeCts.Cancel(); _ignorance.Stop(); + + ReturnReceiveBuffer(); } #endregion @@ -138,23 +141,24 @@ private void HandleIncomingEvents() // Read incoming into buffer var receiveLength = e.Payload.Length; EnsureReceiveBufferSize(receiveLength); - e.Payload.CopyTo(_receiveBuffer, 0); + e.Payload.CopyTo(_receiveBuffer!, 0); e.Payload.Dispose(); var bufferReader = new SpanBufferReader(_receiveBuffer.AsSpan(..receiveLength)); - // If pending, try to accept connection (IgnCon request) + // If pending: first packet should be connection request only (IgnCon) if (connection.State == ENetConnectionState.Pending) { if (!TryAcceptConnection(connection, ref bufferReader)) - { connection.Disconnect(); - return; - } + + return; } - - // Read actual payload... - // TODO + + // Process actual payload + var deliveryMethod = e.Channel == 0 ? DeliveryMethod.ReliableOrdered : DeliveryMethod.Unreliable; + DedicatedInstance.ConnectedMessageSource.OnReceive(connection.EndPoint, ref bufferReader, deliveryMethod); + _logger.Verbose("TEST RECEIVE OK"); } } @@ -196,6 +200,7 @@ private bool TryAcceptConnection(ENetConnection connection, ref SpanBufferReader // Accept success player.ENetPeerId = connection.NativePeerId; connection.State = ENetConnectionState.Accepted; + DedicatedInstance.OnConnect(connection.EndPoint); return true; } } @@ -218,6 +223,7 @@ public void KickPeer(uint peerId, bool sendKick = true) connection.NativePeerId, connection.EndPoint); connection.State = ENetConnectionState.Disconnected; + DedicatedInstance.OnDisconnect(connection.EndPoint, DisconnectReason.DisconnectPeerCalled); if (!IsAlive || !sendKick) // Can't or won't send kick From e3117bd8361d7917f96151b1e44a01f745e99c11 Mon Sep 17 00:00:00 2001 From: Roy de Jong Date: Sun, 9 Jul 2023 00:53:27 +0200 Subject: [PATCH 022/120] wip(1.31): enet - packet send --- .../DedicatedInstance.cs | 11 ++- .../ENet/ENetServer.cs | 51 ++++++++++++- .../PacketDispatcher.cs | 73 ++++++++----------- 3 files changed, 87 insertions(+), 48 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 6b23120c..82e58104 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -64,7 +64,7 @@ public sealed class DedicatedInstance : LiteNetServer, IDedicatedInstance public IPacketDispatcher PacketDispatcher { get; private set; } public ConnectedMessageSource ConnectedMessageSource { get; private set; } - private ENetServer _eNetServer; + public readonly ENetServer ENetServer; public DedicatedInstance( InstanceConfiguration configuration, @@ -89,7 +89,7 @@ public DedicatedInstance( _serviceProvider = serviceProvider; _packetEncryptionLayer = packetEncryptionLayer; - _eNetServer = new(this, configuration.ENetPort); + ENetServer = new(this, configuration.ENetPort); } #region Public Methods @@ -157,7 +157,7 @@ public async Task Start(CancellationToken cancellationToken = default) } base.Start(); - await _eNetServer.Start(); + await ENetServer.Start(); _ = Task.Run(() => SendSyncTime(_stopServerCts.Token), cancellationToken); } @@ -180,18 +180,21 @@ public async Task Stop(CancellationToken cancellationToken = default) $"SongSelectionMode={_configuration.SongSelectionMode}, " + $"GameplayServerControlSettings={_configuration.GameplayServerControlSettings})." ); + PacketDispatcher.SendToNearbyPlayers(new KickPlayerPacket { DisconnectedReason = DisconnectedReason.ServerTerminated }, DeliveryMethod.ReliableOrdered); + ENetServer.KickAllPeers(); + _stopServerCts!.Cancel(); _waitForPlayerCts!.Cancel(); StopEvent?.Invoke(this); base.Stop(); - await _eNetServer.Stop(); + await ENetServer.Stop(); } object SortIndexLock = new(); diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs index 13817280..9a001277 100644 --- a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs @@ -4,8 +4,10 @@ using System.Net; using System.Threading; using System.Threading.Tasks; +using BeatTogether.DedicatedServer.Ignorance.ENet; using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Ignorance.Util; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.LiteNetLib.Enums; using BeatTogether.LiteNetLib.Extensions; using Krypton.Buffers; @@ -158,7 +160,6 @@ private void HandleIncomingEvents() // Process actual payload var deliveryMethod = e.Channel == 0 ? DeliveryMethod.ReliableOrdered : DeliveryMethod.Unreliable; DedicatedInstance.ConnectedMessageSource.OnReceive(connection.EndPoint, ref bufferReader, deliveryMethod); - _logger.Verbose("TEST RECEIVE OK"); } } @@ -236,6 +237,54 @@ public void KickPeer(uint peerId, bool sendKick = true) }); } + public void KickAllPeers() + { + foreach (var connection in _connections.Values) + KickPeer(connection.NativePeerId, true); + } + + #endregion + + #region Send + + public void Send(IPlayer player, ReadOnlySpan message, DeliveryMethod deliveryMethod) + { + if (!player.ENetPeerId.HasValue) + // Not an ENet peer + return; + + Send(player.ENetPeerId.Value, message, deliveryMethod); + } + + public void Send(uint peerId, ReadOnlySpan message, DeliveryMethod deliveryMethod) + { + if (!_connections.TryGetValue(peerId, out var connection)) + // Invalid peer + return; + + Send(connection, message, deliveryMethod); + } + + public void Send(ENetConnection connection, ReadOnlySpan message, DeliveryMethod deliveryMethod) + { + if (!IsAlive) + return; + + if (connection.State != ENetConnectionState.Accepted) + // Do not send if pending/disconnected + return; + + var eNetPacket = default(Packet); + eNetPacket.Create(message.ToArray(), message.Length); + + _ignorance.Outgoing.Enqueue(new IgnoranceOutgoingPacket() + { + Channel = (byte)(deliveryMethod == DeliveryMethod.ReliableOrdered ? 0 : 1), // 1 = Unreliable + NativePeerId = connection.NativePeerId, + Payload = eNetPacket + }); + } + #endregion #region Buffer diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index d7d36723..8c960413 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -1,14 +1,12 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using System; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Configuration; using BeatTogether.LiteNetLib.Dispatchers; using BeatTogether.LiteNetLib.Enums; using Krypton.Buffers; using Serilog; -using System; -using System.Net; namespace BeatTogether.DedicatedServer.Kernel { @@ -20,21 +18,36 @@ public sealed class PacketDispatcher : ConnectedMessageDispatcher, IPacketDispat private readonly IPacketRegistry _packetRegistry; private readonly IPlayerRegistry _playerRegistry; + private readonly DedicatedInstance _dedicatedInstance; private readonly ILogger _logger = Log.ForContext(); public PacketDispatcher( IPacketRegistry packetRegistry, IPlayerRegistry playerRegistry, LiteNetConfiguration configuration, - LiteNetServer server) + DedicatedInstance dedicatedInstance) : base ( configuration, - server) + dedicatedInstance) { _packetRegistry = packetRegistry; _playerRegistry = playerRegistry; + _dedicatedInstance = dedicatedInstance; } + private void SendInternal(IPlayer player, ref SpanBufferWriter writer, DeliveryMethod deliveryMethod) + { + if (player.IsENetConnection) + { + // ENet send + _dedicatedInstance.ENetServer.Send(player.ENetPeerId!.Value, writer.Data, deliveryMethod); + return; + } + + // LiteNet send + Send(player.Endpoint, writer.Data, deliveryMethod); + } + public void SendToNearbyPlayers(INetSerializable packet, DeliveryMethod deliveryMethod) { _logger.Debug( @@ -47,7 +60,8 @@ public void SendToNearbyPlayers(INetSerializable packet, DeliveryMethod delivery WriteOne(ref writer, packet); _logger.Verbose("Packet: " + packet.GetType().Name + " Was entered into the spanbuffer correctly, now sending once to each player"); foreach (var player in _playerRegistry.Players) - Send(player.Endpoint, writer.Data, deliveryMethod); + SendInternal(player, ref writer, deliveryMethod); + } public void SendToNearbyPlayers(INetSerializable[] packets, DeliveryMethod deliveryMethod) { @@ -61,7 +75,7 @@ public void SendToNearbyPlayers(INetSerializable[] packets, DeliveryMethod deliv WriteMany(ref writer, packets); _logger.Verbose("Packets were entered into the spanbuffer correctly, now sending once to each player"); foreach (var player in _playerRegistry.Players) - Send(player.Endpoint, writer.Data, deliveryMethod); + SendInternal(player, ref writer, deliveryMethod); } public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) @@ -77,7 +91,7 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, foreach (IPlayer player in _playerRegistry.Players) if (player.ConnectionId != excludedPlayer.ConnectionId) - Send(player.Endpoint, writer.Data, deliveryMethod); + SendInternal(player, ref writer, deliveryMethod); } public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) { @@ -92,34 +106,7 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packe foreach (IPlayer player in _playerRegistry.Players) if (player.ConnectionId != excludedPlayer.ConnectionId) - Send(player.Endpoint, writer.Data, deliveryMethod); - } - - public void SendToEndpoint(EndPoint endpoint, INetSerializable packet, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending packet of type '{packet.GetType().Name}' " + - $"(To endpoint ={endpoint})" - ); - - var writer = new SpanBufferWriter(stackalloc byte[412]); - writer.WriteRoutingHeader(ServerId, LocalConnectionId); - WriteOne(ref writer, packet); - - Send(endpoint, writer.Data, deliveryMethod); - } - public void SendToEndpoint(EndPoint endpoint, INetSerializable[] packets, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending MultiPacket " + - $"(To endpoint ={endpoint})" - ); - - var writer = new SpanBufferWriter(stackalloc byte[412]); - writer.WriteRoutingHeader(ServerId, LocalConnectionId); - WriteMany(ref writer, packets); - - Send(endpoint, writer.Data, deliveryMethod); + SendInternal(player, ref writer, deliveryMethod); } public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) @@ -134,7 +121,7 @@ public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, Delivery WriteOne(ref writer, packet); foreach (var player in _playerRegistry.Players) - Send(player.Endpoint, writer.Data, deliveryMethod); + SendInternal(player, ref writer, deliveryMethod); } public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) { @@ -148,7 +135,7 @@ public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, Deliv WriteMany(ref writer, packets); foreach (var player in _playerRegistry.Players) - Send(player.Endpoint, writer.Data, deliveryMethod); + SendInternal(player, ref writer, deliveryMethod); } public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) @@ -161,7 +148,7 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer var writer = new SpanBufferWriter(stackalloc byte[412]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteOne(ref writer, packet); - Send(toPlayer.Endpoint, writer.Data, deliveryMethod); + SendInternal(toPlayer, ref writer, deliveryMethod); } public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) @@ -174,7 +161,7 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer var writer = new SpanBufferWriter(stackalloc byte[412]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteMany(ref writer, packets); - Send(toPlayer.Endpoint, writer.Data, deliveryMethod); + SendInternal(toPlayer, ref writer, deliveryMethod); } public void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod deliveryMethod) @@ -187,7 +174,7 @@ public void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod var writer = new SpanBufferWriter(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); - Send(player.Endpoint, writer, deliveryMethod); + SendInternal(player, ref writer, deliveryMethod); } public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMethod deliveryMethod) @@ -200,7 +187,7 @@ public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMet var writer = new SpanBufferWriter(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); - Send(player.Endpoint, writer, deliveryMethod); + SendInternal(player, ref writer, deliveryMethod); } public void WriteOne(ref SpanBufferWriter writer, INetSerializable packet) From 1cdb6c99a4cbd4548a5d818c6778c9e55cdb7005 Mon Sep 17 00:00:00 2001 From: Roy de Jong Date: Sun, 9 Jul 2023 01:03:17 +0200 Subject: [PATCH 023/120] wip(1.31): bump node version to 1.4 --- .../Configuration/NodeConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs index a7d8b419..4dcab520 100644 --- a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs +++ b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs @@ -3,7 +3,7 @@ public sealed class NodeConfiguration { public string HostName { get; set; } = "127.0.0.1"; - public string NodeVersion { get; } = "1.3.0"; + public string NodeVersion { get; } = "1.4.0"; public int BasePort { get; set; } = 30000; public int MaximumSlots { get; set; } = 10000; } From b851bc587f1520fc14ff93c7e7b9cc7a70bb397b Mon Sep 17 00:00:00 2001 From: Roy de Jong Date: Sun, 9 Jul 2023 01:51:44 +0200 Subject: [PATCH 024/120] wip(1.31): reduce logging verbosity --- BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs | 2 +- BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 82e58104..93e4726a 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -379,7 +379,7 @@ public override void OnConnect(EndPoint endPoint) { lock (ConnectionLock) { - _logger.Information($"Endpoint connected (RemoteEndPoint='{endPoint}')"); + _logger.Verbose($"Endpoint connected (RemoteEndPoint='{endPoint}')"); if (!_playerRegistry.TryGetPlayer(endPoint, out var player)) { diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs index 9a001277..1264e789 100644 --- a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs @@ -174,7 +174,7 @@ private ENetConnection CreateConnection(IgnoranceConnectionEvent e) var connection = new ENetConnection(this, e.NativePeerId, e.IP, e.Port); _connections[e.NativePeerId] = connection; - _logger.Information("Incoming ENet connection (PeerId={PeerId}, EndPoint={EndPoint})", + _logger.Verbose("Incoming ENet connection (PeerId={PeerId}, EndPoint={EndPoint})", connection.NativePeerId, connection.EndPoint); return connection; @@ -220,7 +220,7 @@ public void KickPeer(uint peerId, bool sendKick = true) // Connection not established return; - _logger.Information("Closing ENet connection (PeerId={PeerId}, EndPoint={Port})", + _logger.Verbose("Closing ENet connection (PeerId={PeerId}, EndPoint={Port})", connection.NativePeerId, connection.EndPoint); connection.State = ENetConnectionState.Disconnected; From 00cd38aa2cfbbe9b9c2a8bf2adb4d2300f5b830f Mon Sep 17 00:00:00 2001 From: Pink <62712899+ModdingPink@users.noreply.github.com> Date: Thu, 17 Aug 2023 22:58:50 +0100 Subject: [PATCH 025/120] Update DedicatedInstance.cs --- .../DedicatedInstance.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 73422fb6..49247a90 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -559,24 +559,25 @@ public override async void OnConnect(EndPoint endPoint) } //Start of sending player avatars and states of other players to new player - INetSerializable[] SendToPlayerFromPlayers = new INetSerializable[3]; - SendToPlayerFromPlayers[0] = new PlayerAvatarPacket(); - SendToPlayerFromPlayers[1] = new PlayerStatePacket(); - SendToPlayerFromPlayers[2] = new MpPlayerData(); + INetSerializable[] SendToPlayerFromPlayers = new INetSerializable[2]; + SendToPlayerFromPlayers[0] = new PlayerIdentityPacket(); + SendToPlayerFromPlayers[1] = new MpPlayerData(); foreach (IPlayer p in PlayersAtJoin) { if (p.ConnectionId != player.ConnectionId) { - // Send all player connection data packets to new player - //No need to await for players to have sent avatar data or state as the client will share it with them on connect anyway + // Send player to player data to new player await p.PlayerAccessSemaphore.WaitAsync(); - ((PlayerAvatarPacket)SendToPlayerFromPlayers[0]).PlayerAvatar = p.Avatar; - ((PlayerStatePacket)SendToPlayerFromPlayers[1]).PlayerState = p.State; + + ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PlayerState = p.State; + ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PlayerAvatar = p.Avatar; + ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).Random = new ByteArray { Data = p.Random }; + ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PublicEncryptionKey = new ByteArray { Data = p.PublicEncryptionKey }; ((MpPlayerData)SendToPlayerFromPlayers[2]).PlatformID = p.PlatformUserId; ((MpPlayerData)SendToPlayerFromPlayers[2]).Platform = (byte)p.Platform; ((MpPlayerData)SendToPlayerFromPlayers[2]).ClientVersion = p.ClientVersion; - p.PlayerAccessSemaphore.Release(); + // Send all player avatars and states to just joined player await Task.WhenAny(_packetDispatcher.SendFromPlayerToPlayerAndAwait(p, player, SendToPlayerFromPlayers, DeliveryMethod.ReliableOrdered), Task.Delay(50)); //Sends them one by one to avoid server lag From 620f6ab8e9462928299de33e89d47dc108ce0c9b Mon Sep 17 00:00:00 2001 From: Pink <62712899+ModdingPink@users.noreply.github.com> Date: Sat, 19 Aug 2023 23:52:04 +0100 Subject: [PATCH 026/120] Update DedicatedInstance.cs --- BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 49247a90..76386668 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -577,7 +577,9 @@ public override async void OnConnect(EndPoint endPoint) ((MpPlayerData)SendToPlayerFromPlayers[2]).PlatformID = p.PlatformUserId; ((MpPlayerData)SendToPlayerFromPlayers[2]).Platform = (byte)p.Platform; ((MpPlayerData)SendToPlayerFromPlayers[2]).ClientVersion = p.ClientVersion; - + + p.PlayerAccessSemaphore.Release(); + // Send all player avatars and states to just joined player await Task.WhenAny(_packetDispatcher.SendFromPlayerToPlayerAndAwait(p, player, SendToPlayerFromPlayers, DeliveryMethod.ReliableOrdered), Task.Delay(50)); //Sends them one by one to avoid server lag From ebf7772b73003b77b87d8d15412b44655372da90 Mon Sep 17 00:00:00 2001 From: Kevin Hammett Date: Sun, 20 Aug 2023 09:52:06 -0400 Subject: [PATCH 027/120] Update DedicatedInstance.cs --- BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 76386668..ad0dffa1 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -574,9 +574,9 @@ public override async void OnConnect(EndPoint endPoint) ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PlayerAvatar = p.Avatar; ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).Random = new ByteArray { Data = p.Random }; ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PublicEncryptionKey = new ByteArray { Data = p.PublicEncryptionKey }; - ((MpPlayerData)SendToPlayerFromPlayers[2]).PlatformID = p.PlatformUserId; - ((MpPlayerData)SendToPlayerFromPlayers[2]).Platform = (byte)p.Platform; - ((MpPlayerData)SendToPlayerFromPlayers[2]).ClientVersion = p.ClientVersion; + ((MpPlayerData)SendToPlayerFromPlayers[1]).PlatformID = p.PlatformUserId; + ((MpPlayerData)SendToPlayerFromPlayers[1]).Platform = (byte)p.Platform; + ((MpPlayerData)SendToPlayerFromPlayers[1]).ClientVersion = p.ClientVersion; p.PlayerAccessSemaphore.Release(); From 3e71f3ed94d06a87f9978ce5ce7bbb131b862ced Mon Sep 17 00:00:00 2001 From: cubic <79692655+cubicgraphics@users.noreply.github.com> Date: Mon, 21 Aug 2023 21:53:07 +0100 Subject: [PATCH 028/120] Update PlayerIdentityPacketHandler.cs --- .../PacketHandlers/PlayerIdentityPacketHandler.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs index dc5c4d0b..b355707d 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs @@ -33,6 +33,7 @@ public override async Task Handle(IPlayer sender, PlayerIdentityPacket packet) if (!sender.PlayerInitialised.Task.IsCompleted) sender.PlayerInitialised.SetResult(); sender.PlayerAccessSemaphore.Release(); + _packetDispatcher.SendFromPlayer(sender, packet, DeliveryMethod.ReliableOrdered); } } } From 8d40f0e4378a565b6cd19b96c082f745af05b548 Mon Sep 17 00:00:00 2001 From: cubic <79692655+cubicgraphics@users.noreply.github.com> Date: Mon, 21 Aug 2023 21:56:38 +0100 Subject: [PATCH 029/120] Update PlayerIdentityPacketHandler.cs --- .../PacketHandlers/PlayerIdentityPacketHandler.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs index b355707d..815e6b96 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets; +using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers From 67cf36424fec70f37968eecdc0c67f634e7e82c1 Mon Sep 17 00:00:00 2001 From: cubic <79692655+cubicgraphics@users.noreply.github.com> Date: Mon, 21 Aug 2023 22:07:22 +0100 Subject: [PATCH 030/120] Update LobbyManager.cs --- BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 63dbb755..45099cd4 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -148,10 +148,9 @@ public void Update() }, DeliveryMethod.ReliableOrdered); } } + _AllOwnMap = allPlayersOwnBeatmap; if (SelectedBeatmap != null) { - _AllOwnMap = allPlayersOwnBeatmap; - switch (_configuration.SongSelectionMode) //server modes { case SongSelectionMode.ServerOwnerPicks: @@ -481,4 +480,4 @@ public CannotStartGameReason GetCannotStartGameReason(IPlayer player, bool DoesE return CannotStartGameReason.None; } } -} \ No newline at end of file +} From a69f0f5f55a21206e834ab6756363dd8f81e3897 Mon Sep 17 00:00:00 2001 From: cubic Date: Thu, 24 Aug 2023 00:32:38 +0100 Subject: [PATCH 031/120] Server now runs again, player joining and etc needs testing --- .../Abstractions/IPlayer.cs | 4 +- .../DedicatedInstance.cs | 196 ++++++++++++++++-- .../ENet/ENetServer.cs | 6 +- .../PacketDispatcher.cs | 83 ++++++-- .../PlayerAvatarPacketHandler.cs | 2 - .../PlayerIdentityPacketHandler.cs | 2 - BeatTogether.DedicatedServer.Kernel/Player.cs | 3 +- .../PlayerRegistry.cs | 2 +- .../TextCommandRepository.cs | 1 - .../Configuration/NodeConfiguration.cs | 2 +- 10 files changed, 248 insertions(+), 53 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index 8cb4d621..5c807161 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -3,13 +3,14 @@ using BeatTogether.DedicatedServer.Kernel.Types; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; +using System.Threading; +using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { public interface IPlayer { SemaphoreSlim PlayerAccessSemaphore { get; set; } - TaskCompletionSource PlayerInitialised { get; set; } EndPoint Endpoint { get; } IDedicatedInstance Instance { get; } byte ConnectionId { get; } @@ -28,7 +29,6 @@ public interface IPlayer uint? ENetPeerId { get; set; } bool IsENetConnection => ENetPeerId.HasValue; - object LatencyLock { get; set; } RollingAverage Latency { get; } float SyncTime { get; } int SortIndex { get; set; } diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index de38aaa5..c4e40563 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -21,7 +21,6 @@ using BeatTogether.LiteNetLib.Enums; using BeatTogether.LiteNetLib.Util; using BeatTogether.LiteNetLib.Sources; -using Krypton.Buffers; using Microsoft.Extensions.DependencyInjection; using Serilog; @@ -271,8 +270,170 @@ public void SetState(MultiplayerGameState state) #endregion + #region EnetCompat + + public IPlayer? TryAcceptConnection(IPEndPoint endPoint, ref SpanBuffer Data) + { + bool PlayerNoJoin = false; + + ConnectionRequestData connectionRequestData = new(); + try + { + connectionRequestData.ReadFrom(ref Data); + } + catch (Exception ex) + { + _logger.Warning(ex + + "Failed to deserialize connection request data" + + $"(RemoteEndPoint='{endPoint}')." + ); + PlayerNoJoin = true; + goto EndOfTryAccept; + } + + _logger.Debug( + "Handling connection request though Enet" + + $"(RemoteEndPoint='{endPoint}', " + + $"Secret='{connectionRequestData.Secret}', " + + $"UserId='{connectionRequestData.UserId}', " + + $"UserName='{connectionRequestData.UserName}', " + ); + + if (string.IsNullOrEmpty(connectionRequestData.UserId) || + string.IsNullOrEmpty(connectionRequestData.UserName)) + { + _logger.Warning( + "Received a connection request with invalid data " + + $"(RemoteEndPoint='{endPoint}', " + + $"UserId='{connectionRequestData.UserId}', " + + $"UserName='{connectionRequestData.UserName}', " + + $"IsConnectionOwner={connectionRequestData.IsConnectionOwner})." + ); + PlayerNoJoin = true; + goto EndOfTryAccept; + } + ConnectDisconnectSemaphore.Wait(); //Will fix joining issues, and although it will block any Enet recieving, hopefully its not that bad + if (_playerRegistry.GetPlayerCount() >= _configuration.MaxPlayerCount) + { + ConnectDisconnectSemaphore.Release(); + _logger.Warning("Master server sent a player to a full server"); + PlayerNoJoin = true; + goto EndOfTryAccept; + } + if (connectionRequestData.UserName == "IGGAMES" || connectionRequestData.UserName == "IGGGAMES") + { + ConnectDisconnectSemaphore.Release(); + _logger.Information("an IGG player just tried joining after passing master auth"); + PlayerNoJoin = true; + goto EndOfTryAccept; + } + int sortIndex = GetNextSortIndex(); + byte connectionId = GetNextConnectionId(); + + var player = new Player( + endPoint, + this, + connectionId, + _configuration.Secret, + connectionRequestData.UserId, + connectionRequestData.UserName, + connectionRequestData.PlayerSessionId + ) + { + SortIndex = sortIndex + }; + if (!_playerRegistry.AddPlayer(player)) + { + ReleaseSortIndex(player.SortIndex); + ReleaseConnectionId(player.ConnectionId); + ConnectDisconnectSemaphore.Release(); + PlayerNoJoin = true; + goto EndOfTryAccept; + } + + if (_configuration.ServerName == string.Empty) + { + _logger.Information("About to update servers name" + _configuration.ServerName); + _configuration.ServerName = player.UserName + "'s server"; + InstanceConfigUpdated(); + _logger.Information("Updated servers name to: " + _configuration.ServerName); + } + _logger.Information( + "Player joined dedicated server " + + $"(RemoteEndPoint='{player.Endpoint}', " + + $"ConnectionId={player.ConnectionId}, " + + $"Secret='{player.Secret}', " + + $"UserId='{player.UserId}', " + + $"UserName='{player.UserName}', " + + $"SortIndex={player.SortIndex})." + ); + + if (_waitForPlayerCts != null) + _waitForPlayerCts.Cancel(); + + // Retrieve encryption params and platform data from handshake process by player session token, if provided + if (!string.IsNullOrEmpty(connectionRequestData.PlayerSessionId)) + { + var handshakeSession = + _handshakeSessionRegistry.TryGetByPlayerSessionId(connectionRequestData.PlayerSessionId); + _handshakeSessionRegistry.RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out var ClientVer, out var Platform, out var PlayerPlatformUserId); + player.ClientVersion = ClientVer; + player.Platform = (Platform)Platform; + player.PlatformUserId = PlayerPlatformUserId; + if (handshakeSession != null && handshakeSession.EncryptionParameters != null) + { + _packetEncryptionLayer.AddEncryptedEndPoint((IPEndPoint)endPoint, + handshakeSession.EncryptionParameters, true); + } + } + + ConnectDisconnectSemaphore.Release(); + Task.Run(() => SendPlayerDataInBackgroundAsync(player)); + return player; + EndOfTryAccept: + if (PlayerNoJoin) + { + string[] Players = _playerRegistry.Players.Select(p => p.UserId).ToArray(); + PlayerDisconnectBeforeJoining?.Invoke(_configuration.Secret, endPoint, Players); + return null; + } + return null; + } + + private async void SendPlayerDataInBackgroundAsync(IPlayer player) + { + await player.PlayerAccessSemaphore.WaitAsync(); + var SendToOtherPlayers = new INetSerializable[] + { + new PlayerConnectedPacket + { + RemoteConnectionId = player.ConnectionId, + UserId = player.UserId, + UserName = player.UserName, + IsConnectionOwner = false + }, + new PlayerSortOrderPacket + { + UserId = player.UserId, + SortIndex = player.SortIndex + }, + new MpNodePoseSyncStatePacket + { + fullStateUpdateFrequency = 0.1f, + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f + }, + }; + player.PlayerAccessSemaphore.Release(); + + PacketDispatcher.SendExcludingPlayer(player, SendToOtherPlayers, DeliveryMethod.ReliableOrdered); + } + + #endregion + + #region LiteNetServer + public override async Task ShouldAcceptConnection(EndPoint endPoint, byte[] additionalData) { @@ -314,7 +475,7 @@ public async Task ShouldDenyConnection(EndPoint endPoint, byte[] additiona "Failed to deserialize connection request data " + $"(RemoteEndPoint='{endPoint}')." ); - return null; + return true; } _logger.Debug( "Handling connection request " + @@ -334,7 +495,7 @@ public async Task ShouldDenyConnection(EndPoint endPoint, byte[] additiona $"UserName='{connectionRequestData.UserName}', " + $"IsConnectionOwner={connectionRequestData.IsConnectionOwner})." ); - return null; + return true; } await ConnectDisconnectSemaphore.WaitAsync(); if (_playerRegistry.GetPlayerCount() >= _configuration.MaxPlayerCount) @@ -433,11 +594,12 @@ public async Task ShouldDenyConnection(EndPoint endPoint, byte[] additiona }; player.PlayerAccessSemaphore.Release(); - _packetDispatcher.SendExcludingPlayer(player, SendToOtherPlayers, DeliveryMethod.ReliableOrdered); + PacketDispatcher.SendExcludingPlayer(player, SendToOtherPlayers, DeliveryMethod.ReliableOrdered); return false; } + public override void OnLatencyUpdate(EndPoint endPoint, int latency) => _logger.Verbose($"Latency updated (RemoteEndPoint='{endPoint}', Latency={0.001f * latency})."); @@ -495,7 +657,7 @@ public override async void OnConnect(EndPoint endPoint) }; player.PlayerAccessSemaphore.Release(); - await _packetDispatcher.SendToPlayerAndAwait(player, Player_ConnectPacket, DeliveryMethod.ReliableOrdered); + await PacketDispatcher.SendToPlayerAndAwait(player, Player_ConnectPacket, DeliveryMethod.ReliableOrdered); List MakeBigPacketToSendToPlayer = new(); foreach (IPlayer p in PlayersAtJoin) @@ -520,7 +682,7 @@ public override async void OnConnect(EndPoint endPoint) } foreach (var SubPacket in MakeBigPacketToSendToPlayer.Chunk(20)) { - await _packetDispatcher.SendToPlayerAndAwait(player, SubPacket.ToArray(), DeliveryMethod.ReliableOrdered); + await PacketDispatcher.SendToPlayerAndAwait(player, SubPacket.ToArray(), DeliveryMethod.ReliableOrdered); } //End of sending other players to player @@ -529,7 +691,7 @@ public override async void OnConnect(EndPoint endPoint) if ((_configuration.SetConstantManagerFromUserId == player.UserId || _playerRegistry.GetPlayerCount() == 1) && _configuration.GameplayServerMode == GameplayServerMode.Managed) { _configuration.ServerOwnerId = player.UserId; - _packetDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket //Sends updated value to all players.//TODO Make a function for updating players permissions as there will be commands for it soon + PacketDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket //Sends updated value to all players.//TODO Make a function for updating players permissions as there will be commands for it soon { PermissionConfiguration = new PlayersPermissionConfiguration { @@ -572,7 +734,7 @@ public override async void OnConnect(EndPoint endPoint) HasKickVotePermission = ServerOwner!.CanKickVote, HasInvitePermission = ServerOwner!.CanInvite }; - _packetDispatcher.SendToPlayer(player, new SetPlayersPermissionConfigurationPacket + PacketDispatcher.SendToPlayer(player, new SetPlayersPermissionConfigurationPacket { PermissionConfiguration = new PlayersPermissionConfiguration { @@ -604,7 +766,7 @@ public override async void OnConnect(EndPoint endPoint) p.PlayerAccessSemaphore.Release(); // Send all player avatars and states to just joined player - await Task.WhenAny(_packetDispatcher.SendFromPlayerToPlayerAndAwait(p, player, SendToPlayerFromPlayers, DeliveryMethod.ReliableOrdered), Task.Delay(50)); + await Task.WhenAny(PacketDispatcher.SendFromPlayerToPlayerAndAwait(p, player, SendToPlayerFromPlayers, DeliveryMethod.ReliableOrdered), Task.Delay(50)); //Sends them one by one to avoid server lag } } @@ -615,7 +777,7 @@ public override async void OnConnect(EndPoint endPoint) if (p.ConnectionId != player.ConnectionId) { await Task.WhenAny( - _packetDispatcher.SendFromPlayerToPlayerAndAwait(player, p, new MpPlayerData + PacketDispatcher.SendFromPlayerToPlayerAndAwait(player, p, new MpPlayerData { PlatformID = player.PlatformUserId!, Platform = (byte)player.Platform, @@ -632,7 +794,7 @@ await Task.WhenAny( { if (p.CanTextChat) { - await Task.WhenAny(_packetDispatcher.SendToPlayerAndAwait(p, packet, DeliveryMethod.ReliableOrdered), Task.Delay(50)); + await Task.WhenAny(PacketDispatcher.SendToPlayerAndAwait(p, packet, DeliveryMethod.ReliableOrdered), Task.Delay(50)); } } } @@ -641,7 +803,7 @@ public void DisconnectPlayer(string UserId) //Used my master servers kick player { if(_playerRegistry.TryGetPlayer(UserId, out var player)) - _packetDispatcher.SendToPlayer(player, new KickPlayerPacket + PacketDispatcher.SendToPlayer(player, new KickPlayerPacket { DisconnectedReason = DisconnectedReason.Kicked }, DeliveryMethod.ReliableOrdered); @@ -666,7 +828,7 @@ public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reas { //Sends to all players that they have disconnected - _packetDispatcher.SendFromPlayer(player, new PlayerDisconnectedPacket + PacketDispatcher.SendFromPlayer(player, new PlayerDisconnectedPacket { DisconnectedReason = DisconnectedReason.ClientConnectionClosed }, DeliveryMethod.ReliableOrdered); @@ -688,7 +850,7 @@ public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reas _configuration.ServerOwnerId = serverOwner.UserId; // Update permissions - _packetDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket + PacketDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket { PermissionConfiguration = new PlayersPermissionConfiguration { @@ -709,14 +871,14 @@ public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reas // Disable start button if they are server owner without selected song if (serverOwner.BeatmapIdentifier == null) - _packetDispatcher.SendToPlayer(serverOwner, new SetIsStartButtonEnabledPacket + PacketDispatcher.SendToPlayer(serverOwner, new SetIsStartButtonEnabledPacket { Reason = CannotStartGameReason.NoSongSelected }, DeliveryMethod.ReliableOrdered); } - _packetDispatcher.SendToNearbyPlayers(new MpNodePoseSyncStatePacket + PacketDispatcher.SendToNearbyPlayers(new MpNodePoseSyncStatePacket { fullStateUpdateFrequency = 0.1f, deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f @@ -753,7 +915,7 @@ private async void SendSyncTime(CancellationToken cancellationToken) { foreach (IPlayer player in _playerRegistry.Players) { - _packetDispatcher.SendToPlayer(player, new SyncTimePacket() + PacketDispatcher.SendToPlayer(player, new SyncTimePacket() { SyncTime = player.SyncTime }, DeliveryMethod.ReliableOrdered); diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs index 1264e789..9956726b 100644 --- a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs @@ -10,6 +10,7 @@ using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.LiteNetLib.Enums; using BeatTogether.LiteNetLib.Extensions; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; using Serilog; @@ -146,7 +147,7 @@ private void HandleIncomingEvents() e.Payload.CopyTo(_receiveBuffer!, 0); e.Payload.Dispose(); - var bufferReader = new SpanBufferReader(_receiveBuffer.AsSpan(..receiveLength)); + var bufferReader = new SpanBuffer(_receiveBuffer.AsSpan(..receiveLength)); // If pending: first packet should be connection request only (IgnCon) if (connection.State == ENetConnectionState.Pending) @@ -156,7 +157,6 @@ private void HandleIncomingEvents() return; } - // Process actual payload var deliveryMethod = e.Channel == 0 ? DeliveryMethod.ReliableOrdered : DeliveryMethod.Unreliable; DedicatedInstance.ConnectedMessageSource.OnReceive(connection.EndPoint, ref bufferReader, deliveryMethod); @@ -180,7 +180,7 @@ private ENetConnection CreateConnection(IgnoranceConnectionEvent e) return connection; } - private bool TryAcceptConnection(ENetConnection connection, ref SpanBufferReader reader) + private bool TryAcceptConnection(ENetConnection connection, ref SpanBuffer reader) { try { diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index 64e36f03..3c5d7795 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -38,7 +38,7 @@ public PacketDispatcher( _dedicatedInstance = dedicatedInstance; } - private void SendInternal(IPlayer player, ref SpanBufferWriter writer, DeliveryMethod deliveryMethod) + private void SendInternal(IPlayer player, ref SpanBuffer writer, DeliveryMethod deliveryMethod) { if (player.IsENetConnection) { @@ -51,8 +51,6 @@ private void SendInternal(IPlayer player, ref SpanBufferWriter writer, DeliveryM Send(player.Endpoint, writer.Data, deliveryMethod); } - } - #region Sends public void SendToNearbyPlayers(INetSerializable packet, DeliveryMethod deliveryMethod) { @@ -115,10 +113,6 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packe SendInternal(player, ref writer, deliveryMethod); } - public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending packet of type '{packet.GetType().Name}' " + public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) { _logger.Debug( @@ -131,7 +125,7 @@ public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, Delivery WriteOne(ref writer, packet); foreach (var player in _playerRegistry.Players) - Send(player.Endpoint, writer.Data, deliveryMethod); + SendInternal(player, ref writer, deliveryMethod); } public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) { @@ -145,7 +139,7 @@ public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, Deliv WriteMany(ref writer, packets); foreach (var player in _playerRegistry.Players) - Send(player.Endpoint, writer.Data, deliveryMethod); + SendInternal(player, ref writer, deliveryMethod); } public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) @@ -158,7 +152,7 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteOne(ref writer, packet); - Send(toPlayer.Endpoint, writer.Data, deliveryMethod); + SendInternal(toPlayer, ref writer, deliveryMethod); } public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) { @@ -170,7 +164,7 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteMany(ref writer, packets); - Send(toPlayer.Endpoint, writer.Data, deliveryMethod); + SendInternal(toPlayer, ref writer, deliveryMethod); } public void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod deliveryMethod) @@ -183,7 +177,7 @@ public void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); - Send(player.Endpoint, writer.Data, deliveryMethod); + SendInternal(player, ref writer, deliveryMethod); } public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMethod deliveryMethod) { @@ -215,7 +209,15 @@ public Task SendToNearbyPlayersAndAwait(INetSerializable packet, DeliveryMethod var players = _playerRegistry.Players; Task[] tasks = new Task[players.Length]; for (int i = 0; i < players.Length; i++) + { + if (players[i].IsENetConnection) + { + tasks[i] = Task.CompletedTask; + SendInternal(players[i], ref writer, deliveryMethod); + continue; + } tasks[i] = Send(players[i].Endpoint, writer.Data, deliveryMethod); + } return Task.WhenAll(tasks); } public Task SendToNearbyPlayersAndAwait(INetSerializable[] packets, DeliveryMethod deliveryMethod) @@ -232,7 +234,15 @@ public Task SendToNearbyPlayersAndAwait(INetSerializable[] packets, DeliveryMeth var players = _playerRegistry.Players; Task[] tasks = new Task[players.Length]; for (int i = 0; i < players.Length; i++) + { + if (players[i].IsENetConnection) + { + tasks[i] = Task.CompletedTask; + SendInternal(players[i], ref writer, deliveryMethod); + continue; + } tasks[i] = Send(players[i].Endpoint, writer.Data, deliveryMethod); + } return Task.WhenAll(tasks); } @@ -253,7 +263,15 @@ public Task SendExcludingPlayerAndAwait(IPlayer excludedPlayer, INetSerializable foreach (var player in players) if (player.ConnectionId != excludedPlayer.ConnectionId) { - tasks[i] = Send(player.Endpoint, writer.Data, deliveryMethod); + if (!player.IsENetConnection) + { + tasks[i] = Send(player.Endpoint, writer.Data, deliveryMethod); + } + else + { + tasks[i] = Task.CompletedTask; + SendInternal(player, ref writer, deliveryMethod); + } i++; } return Task.WhenAll(tasks); @@ -274,12 +292,18 @@ public Task SendExcludingPlayerAndAwait(IPlayer excludedPlayer, INetSerializable foreach (var player in players) if (player.ConnectionId != excludedPlayer.ConnectionId) { - tasks[i] = Send(player.Endpoint, writer.Data, deliveryMethod); + if (!player.IsENetConnection) + { + tasks[i] = Send(player.Endpoint, writer.Data, deliveryMethod); + } + else + { + tasks[i] = Task.CompletedTask; + SendInternal(player, ref writer, deliveryMethod); + } i++; } return Task.WhenAll(tasks); - - } public Task SendFromPlayerAndAwait(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) @@ -292,15 +316,18 @@ public Task SendFromPlayerAndAwait(IPlayer fromPlayer, INetSerializable packet, var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteOne(ref writer, packet); - - foreach (var player in _playerRegistry.Players) - SendInternal(player, ref writer, deliveryMethod); - } - public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) var players = _playerRegistry.Players; Task[] tasks = new Task[players.Length]; for (int i = 0; i < players.Length; i++) + { + if (players[i].IsENetConnection) + { + tasks[i] = Task.CompletedTask; + SendInternal(players[i], ref writer, deliveryMethod); + continue; + } tasks[i] = Send(players[i].Endpoint, writer.Data, deliveryMethod); + } return Task.WhenAll(tasks); } public Task SendFromPlayerAndAwait(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) @@ -319,7 +346,15 @@ public Task SendFromPlayerAndAwait(IPlayer fromPlayer, INetSerializable[] packet var players = _playerRegistry.Players; Task[] tasks = new Task[players.Length]; for (int i = 0; i < players.Length; i++) + { + if (players[i].IsENetConnection) + { + tasks[i] = Task.CompletedTask; + SendInternal(players[i], ref writer, deliveryMethod); + continue; + } tasks[i] = Send(players[i].Endpoint, writer.Data, deliveryMethod); + } return Task.WhenAll(tasks); } @@ -333,7 +368,11 @@ public Task SendFromPlayerToPlayerAndAwait(IPlayer fromPlayer, IPlayer toPlayer, var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); WriteOne(ref writer, packet); - SendInternal(toPlayer, ref writer, deliveryMethod); + if (toPlayer.IsENetConnection) + { + SendInternal(toPlayer, ref writer, deliveryMethod); + return Task.CompletedTask; + } return Send(toPlayer.Endpoint, writer.Data, deliveryMethod); } public Task SendFromPlayerToPlayerAndAwait(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerAvatarPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerAvatarPacketHandler.cs index 480e4ad9..b9f4c311 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerAvatarPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerAvatarPacketHandler.cs @@ -26,8 +26,6 @@ public override async Task Handle(IPlayer sender, PlayerAvatarPacket packet) ); await sender.PlayerAccessSemaphore.WaitAsync(); sender.Avatar = packet.PlayerAvatar; - if (!sender.PlayerInitialised.Task.IsCompleted) - sender.PlayerInitialised.SetResult(); sender.PlayerAccessSemaphore.Release(); } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs index 815e6b96..52cf3716 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs @@ -31,8 +31,6 @@ public override async Task Handle(IPlayer sender, PlayerIdentityPacket packet) sender.State = packet.PlayerState; sender.Random = packet.Random.Data ?? Array.Empty(); sender.PublicEncryptionKey = packet.PublicEncryptionKey.Data ?? Array.Empty(); - if (!sender.PlayerInitialised.Task.IsCompleted) - sender.PlayerInitialised.SetResult(); sender.PlayerAccessSemaphore.Release(); _packetDispatcher.SendFromPlayer(sender, packet, DeliveryMethod.ReliableOrdered); } diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index 3a62c260..38afbb91 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -14,7 +14,6 @@ namespace BeatTogether.DedicatedServer.Kernel public sealed class Player : IPlayer { public SemaphoreSlim PlayerAccessSemaphore { get; set; } = new(1); - public TaskCompletionSource PlayerInitialised { get; set; } = new(); public EndPoint Endpoint { get; } public IDedicatedInstance Instance { get; } public byte ConnectionId { get; } @@ -62,7 +61,7 @@ public sealed class Player : IPlayer public bool InMenu => State.Contains("in_menu"); //Should be true while in lobby private const float _syncTimeOffset = 0.06f; - private ConcurrentDictionary _entitlements = new(); + private readonly ConcurrentDictionary _entitlements = new(); public Player(EndPoint endPoint, IDedicatedInstance instance, byte connectionId, string secret, string userId, string userName, string? playerSessionId, AccessLevel accessLevel = AccessLevel.Player) diff --git a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs index 4ebf51c4..fbcded48 100644 --- a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs @@ -11,7 +11,7 @@ public sealed class PlayerRegistry : IPlayerRegistry public IPlayer[] Players { get => GetPlayers(); } - private object PlayerDictionaries_Lock = new(); + private readonly object PlayerDictionaries_Lock = new(); private readonly Dictionary _playersByRemoteEndPoint = new(); private readonly Dictionary _playersByConnectionId = new(); private readonly Dictionary _playersByUserId = new(); diff --git a/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs b/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs index 59e43aab..302cef33 100644 --- a/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs +++ b/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Kernel.Commands; using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Managers; -using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using Serilog; using System; using System.Collections.Concurrent; diff --git a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs index 4dcab520..142cda79 100644 --- a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs +++ b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs @@ -3,7 +3,7 @@ public sealed class NodeConfiguration { public string HostName { get; set; } = "127.0.0.1"; - public string NodeVersion { get; } = "1.4.0"; + public string NodeVersion { get; } = "1.5.0"; public int BasePort { get; set; } = 30000; public int MaximumSlots { get; set; } = 10000; } From 840cff13602c312c859f1e2cc4da3beb4534c2ef Mon Sep 17 00:00:00 2001 From: cubic <79692655+cubicgraphics@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:44:19 +0100 Subject: [PATCH 032/120] Update nuget.yml --- .github/workflows/nuget.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index 868952c1..b092b4d4 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -8,6 +8,7 @@ on: - dev-1.29-Net6.0 - dev-1.29-Net6.0-Faster - dev-1.31.0 + - dev-1.31.0-Merge-Faster-Changes jobs: nuget-1: From 8bb8d65c41912bcdfbce784aaa8f7af89f1c933b Mon Sep 17 00:00:00 2001 From: cubic Date: Thu, 24 Aug 2023 18:57:27 +0100 Subject: [PATCH 033/120] Removed Delay in connection function --- BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index c4e40563..d2942cdf 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -619,7 +619,6 @@ public override async void OnConnect(EndPoint endPoint) return; } PlayerConnectedEvent?.Invoke(player); - await Task.Delay(50); //The player has already been sent to every other player in the should connect function. //Start of sending other players to player From bc8f9bb4258ac18184ac6787d95b393edbb7e2d2 Mon Sep 17 00:00:00 2001 From: cubic <79692655+cubicgraphics@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:59:53 +0100 Subject: [PATCH 034/120] Update nuget.yml --- .github/workflows/nuget.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index b092b4d4..9e0393ac 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -8,7 +8,7 @@ on: - dev-1.29-Net6.0 - dev-1.29-Net6.0-Faster - dev-1.31.0 - - dev-1.31.0-Merge-Faster-Changes + - dev-1.31.0-Merge-faster-changes jobs: nuget-1: From c6a625d1a2cbb915a7a249cdc2958013d6f47cd4 Mon Sep 17 00:00:00 2001 From: cubic Date: Sun, 27 Aug 2023 20:53:37 +0100 Subject: [PATCH 035/120] Force late joins players that fail to send an OK entitlement within the start timeout Spectating players no longer count towards beatmap checks To reduce hangs in the joining logic the lobby manager code will skip instead of awaiting --- .../Abstractions/IPlayer.cs | 2 +- .../Configuration/InstanceConfiguration.cs | 2 +- .../Managers/Abstractions/ILobbyManager.cs | 1 + .../Managers/GameplayManager.cs | 15 ++++- .../Managers/LobbyManager.cs | 61 ++++++++++--------- .../PlayerStatePacketHandler.cs | 10 +++ BeatTogether.DedicatedServer.Kernel/Player.cs | 1 + 7 files changed, 60 insertions(+), 32 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index 5c807161..b3fb1f2a 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -38,7 +38,7 @@ public interface IPlayer BeatmapIdentifier? BeatmapIdentifier { get; set; } GameplayModifiers Modifiers { get; set; } PlayerStateHash State { get; set; } - + public bool ForceLateJoin { get; set; } public bool IsServerOwner { get; } public bool CanRecommendBeatmaps { get; } public bool CanRecommendModifiers { get; } diff --git a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs index 046c2f48..1f47fce1 100644 --- a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs +++ b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs @@ -28,7 +28,7 @@ public sealed class InstanceConfiguration public bool DisableNotes { get; set; } public bool ForceEnableNotes { get; set; } = false; public bool ForceStartMode { get; set; } = false; - public float KickPlayersWithoutEntitlementTimeout { get; set; } = 30f; + public float SendPlayersWithoutEntitlementToSpectateTimeout { get; set; } = 30f; public int MaxLengthCommand { get; set; } = 200; public bool ApplyNoFailModifier { get; set; } = true; } diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs index e422145d..96677bc9 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs @@ -17,6 +17,7 @@ public interface ILobbyManager CountdownState CountDownState { get; } float CountdownEndTime { get; } GameplayModifiers EmptyModifiers {get; } + public bool SpectatingPlayersUpdated { get; set; } void Update(); BeatmapDifficulty[] GetSelectedBeatmapDifficulties(); diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs index 1e5dd837..b4353a8a 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs @@ -97,7 +97,7 @@ public async void StartSong(CancellationToken cancellationToken) State = GameplayManagerState.SceneLoad; foreach (var player in _playerRegistry.Players)//Array of players that are playing at the start { - if (!player.IsSpectating) + if (!player.IsSpectating && !player.ForceLateJoin) PlayersAtStart.Add(player.UserId); } @@ -171,6 +171,19 @@ public async void StartSong(CancellationToken cancellationToken) StartTime = _songStartTime }, DeliveryMethod.ReliableOrdered); + //Initiates the song start process for forced late joiners + foreach(IPlayer p in _playerRegistry.Players) + { + if (p.ForceLateJoin) + { + _packetDispatcher.SendToPlayer(p, new Messaging.Packets.MultiplayerSession.MenuRpc.StartLevelPacket + { + Beatmap = CurrentBeatmap, + Modifiers = CurrentModifiers, + StartTime = _songStartTime + }, DeliveryMethod.ReliableOrdered); + } + } await Task.WhenAll(_levelFinishedTcs.Values.Select(p => p.Task)); diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 45099cd4..90d7b209 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -18,28 +18,23 @@ /*Lobby manager code * Contains the logic code for * - different game modes - * - setting the beatmap - * - setting the modifiers + * - managing the beatmap + * - managing the modifiers * - managing the countdown - * - checking player entitlements - * - when to start gameplay + * - managing player entitlements + * - managing when to start gameplay */ namespace BeatTogether.DedicatedServer.Kernel.Managers { public sealed class LobbyManager : ILobbyManager, IDisposable { - //TODO - todo list below - /* - Players who dont want to play next level should not block current players from being able to play (if spectating then dont beatmap check them) - * - Use per player semaphores instead of locks around handlers as there are locks around packet sends, which is probably causing a few issues - * - basicly re-write the lobby manager stuff and some gameplay manager things - * - */ public bool AllPlayersReady => _playerRegistry.Players.All(p => p.IsReady || !p.WantsToPlayNextLevel); //If all are ready or not playing public bool SomePlayersReady => _playerRegistry.Players.Any(p => p.IsReady); //If anyone is readied public bool NoPlayersReady => _playerRegistry.Players.All(p => !p.IsReady || !p.WantsToPlayNextLevel); //players not ready or are going to spectate public bool AllPlayersNotWantToPlayNextLevel => _playerRegistry.Players.All(p => !p.WantsToPlayNextLevel);//if all are going to be spectating public bool AllPlayersAreInLobby => _playerRegistry.Players.All(p => p.InMenu);//if all are going to be spectating public bool DoesEveryoneOwnBeatmap => SelectedBeatmap == null || !_playerRegistry.Players.Any(p => p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown); + public bool SpectatingPlayersUpdated { get; set; } = false; public BeatmapIdentifier? SelectedBeatmap { get; private set; } = null; public GameplayModifiers SelectedModifiers { get; private set; } = new(); @@ -89,17 +84,20 @@ private void Stop(IDedicatedInstance inst) private async void UpdateLoop(CancellationToken cancellationToken) { - try + while (!cancellationToken.IsCancellationRequested) { - await Task.Delay(LoopTime, cancellationToken); - await _instance.ConnectDisconnectSemaphore.WaitAsync(cancellationToken); - Update(); - _instance.ConnectDisconnectSemaphore.Release(); - UpdateLoop(cancellationToken); - } - catch (TaskCanceledException){} - catch (OperationCanceledException){ - _instance.ConnectDisconnectSemaphore.Release(); + if (_instance.ConnectDisconnectSemaphore.CurrentCount > 0) + { + _instance.ConnectDisconnectSemaphore.Wait(); + Update(); + _instance.ConnectDisconnectSemaphore.Release(); + } + try + { + await Task.Delay(LoopTime, cancellationToken); + } + catch (TaskCanceledException) { continue; } + catch (OperationCanceledException) { continue; } } } @@ -121,21 +119,22 @@ public void Update() foreach (IPlayer player in _playerRegistry.Players) { - if (player.UpdateEntitlement) + if (player.UpdateEntitlement || SpectatingPlayersUpdated) { if (player.BeatmapIdentifier != null) { _packetDispatcher.SendToPlayer(player, new SetPlayersMissingEntitlementsToLevelPacket { PlayersWithoutEntitlements = _playerRegistry.Players - .Where(p => p.GetEntitlement(player.BeatmapIdentifier.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) + .Where(p => (p.GetEntitlement(player.BeatmapIdentifier.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) && !p.IsSpectating) .Select(p => p.UserId).ToArray() }, DeliveryMethod.ReliableOrdered); - _logger.Information("Sent missing entitlement packet"); + _logger.Debug("Sent missing entitlement packet"); } player.UpdateEntitlement = false; } } + SpectatingPlayersUpdated = false; bool allPlayersOwnBeatmap = DoesEveryoneOwnBeatmap; if (_configuration.SongSelectionMode == SongSelectionMode.ServerOwnerPicks) @@ -201,7 +200,7 @@ private void CountingDown(bool isReady, bool NotStartable) { SetCountdown(CountdownState.WaitingForEntitlement); } - if (_playerRegistry.Players.All(p => p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok)) + if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || p.ForceLateJoin)) { //starts beatmap _gameplayManager.SetBeatmap(SelectedBeatmap!, SelectedModifiers); @@ -210,15 +209,19 @@ private void CountingDown(bool isReady, bool NotStartable) SetCountdown(CountdownState.NotCountingDown); return; } - if (CountdownEndTime + _configuration.KickPlayersWithoutEntitlementTimeout <= _instance.RunTime) + if (CountdownEndTime + _configuration.SendPlayersWithoutEntitlementToSpectateTimeout <= _instance.RunTime) //If takes too long to start then players are sent to spectate by telling them the beatmap already started { IPlayer[] MissingEntitlement = _playerRegistry.Players.Where(p => p.GetEntitlement(SelectedBeatmap!.LevelId) is not EntitlementStatus.Ok).ToArray(); foreach (IPlayer p in MissingEntitlement) { - _packetDispatcher.SendToPlayer(p, new KickPlayerPacket() - { - DisconnectedReason = DisconnectedReason.Kicked, - }, DeliveryMethod.ReliableOrdered); + //Force the player to join late + p.ForceLateJoin = true; + _packetDispatcher.SendToPlayer(p, new CancelLevelStartPacket(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToPlayer(p, new SetIsReadyPacket() { IsReady = false }, DeliveryMethod.ReliableOrdered); + /* _packetDispatcher.SendToPlayer(p, new KickPlayerPacket() + { + DisconnectedReason = DisconnectedReason.Kicked, + }, DeliveryMethod.ReliableOrdered);*/ } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs index 7b3b18d0..56fd4510 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs @@ -1,4 +1,5 @@ using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets; using Serilog; using System.Threading.Tasks; @@ -8,6 +9,12 @@ namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers public sealed class PlayerStatePacketHandler : BasePacketHandler { private readonly ILogger _logger = Log.ForContext(); + private readonly ILobbyManager _lobbyManager; + + public PlayerStatePacketHandler(ILobbyManager lobbyManager) + { + _lobbyManager = lobbyManager; + } public override async Task Handle(IPlayer sender, PlayerStatePacket packet) { @@ -19,8 +26,11 @@ public override async Task Handle(IPlayer sender, PlayerStatePacket packet) $"backgrounded={packet.PlayerState.Contains("backgrounded")}, in_gameplay={packet.PlayerState.Contains("in_gameplay")}" + $"was_active_at_level_start={packet.PlayerState.Contains("was_active_at_level_start")}, finished_level={packet.PlayerState.Contains("finished_level")})." ); + await sender.PlayerAccessSemaphore.WaitAsync(); sender.State = packet.PlayerState; + if (packet.PlayerState.Contains("spectating") != sender.State.Contains("spectating")) + _lobbyManager.SpectatingPlayersUpdated = true; sender.PlayerAccessSemaphore.Release(); return; } diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index 38afbb91..8cf10d0a 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -49,6 +49,7 @@ public sealed class Player : IPlayer public bool CanKickVote => UserId == Instance._configuration.ServerOwnerId; public bool CanInvite => Instance._configuration.DiscoveryPolicy is DiscoveryPolicy.WithCode or DiscoveryPolicy.Public; + public bool ForceLateJoin { get; set; } = false; public bool IsPlayer => State.Contains("player"); public bool IsSpectating => State.Contains("spectating"); //True if spectating players in gameplay From 30651708b205bd4bac60b3158fe5904453ab5038 Mon Sep 17 00:00:00 2001 From: cubic Date: Sun, 27 Aug 2023 21:05:45 +0100 Subject: [PATCH 036/120] SHould have fixed start button being clickable with no beatmap And should have fixed the beatmap being startable when it is null. IE: null beatmaps are no longer startable --- .../Managers/LobbyManager.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 90d7b209..ce871ad7 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -33,7 +33,7 @@ public sealed class LobbyManager : ILobbyManager, IDisposable public bool NoPlayersReady => _playerRegistry.Players.All(p => !p.IsReady || !p.WantsToPlayNextLevel); //players not ready or are going to spectate public bool AllPlayersNotWantToPlayNextLevel => _playerRegistry.Players.All(p => !p.WantsToPlayNextLevel);//if all are going to be spectating public bool AllPlayersAreInLobby => _playerRegistry.Players.All(p => p.InMenu);//if all are going to be spectating - public bool DoesEveryoneOwnBeatmap => SelectedBeatmap == null || !_playerRegistry.Players.Any(p => p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown); + public bool DoesEveryoneOwnBeatmap => SelectedBeatmap != null && !_playerRegistry.Players.Any(p => p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown); public bool SpectatingPlayersUpdated { get; set; } = false; public BeatmapIdentifier? SelectedBeatmap { get; private set; } = null; @@ -147,7 +147,7 @@ public void Update() }, DeliveryMethod.ReliableOrdered); } } - _AllOwnMap = allPlayersOwnBeatmap; + _AllOwnMap = allPlayersOwnBeatmap; if (SelectedBeatmap != null) { switch (_configuration.SongSelectionMode) //server modes @@ -218,15 +218,11 @@ private void CountingDown(bool isReady, bool NotStartable) p.ForceLateJoin = true; _packetDispatcher.SendToPlayer(p, new CancelLevelStartPacket(), DeliveryMethod.ReliableOrdered); _packetDispatcher.SendToPlayer(p, new SetIsReadyPacket() { IsReady = false }, DeliveryMethod.ReliableOrdered); - /* _packetDispatcher.SendToPlayer(p, new KickPlayerPacket() - { - DisconnectedReason = DisconnectedReason.Kicked, - }, DeliveryMethod.ReliableOrdered);*/ } } } - // If server owner/all players are no longer ready or not all players own beatmap - if (NotStartable || !_AllOwnMap || AllPlayersNotWantToPlayNextLevel) + // If server owner/all players are no longer ready or not all players own beatmap or beatmap is null + if (NotStartable || !_AllOwnMap || AllPlayersNotWantToPlayNextLevel || ((CountdownEndTime - _instance.RunTime) < _configuration.CountdownConfig.BeatMapStartCountdownTime && SelectedBeatmap == null)) CancelCountdown(); else if (CountDownState == CountdownState.CountingDown && (AllPlayersReady || (CountdownEndTime - _instance.RunTime) < _configuration.CountdownConfig.BeatMapStartCountdownTime)) SetCountdown(CountdownState.StartBeatmapCountdown, _configuration.CountdownConfig.BeatMapStartCountdownTime); From f2a88f3e1ba3e163068edba6dc94722f3644615b Mon Sep 17 00:00:00 2001 From: cubic Date: Sun, 27 Aug 2023 21:31:15 +0100 Subject: [PATCH 037/120] Added a force start command that will ignore all players entitlements and start the beatmap regardless --- .../ForceStartCommandHandler.cs | 24 ++++++++ .../Commands/ForceStartCommand.cs | 15 +++++ .../Commands/SetBeatmapRouting.cs | 2 +- .../Managers/Abstractions/ILobbyManager.cs | 1 + .../Managers/LobbyManager.cs | 55 ++++++++++++++++++- 5 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 BeatTogether.DedicatedServer.Kernel/CommandHandlers/ForceStartCommandHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/Commands/ForceStartCommand.cs diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/ForceStartCommandHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/ForceStartCommandHandler.cs new file mode 100644 index 00000000..9da6d86c --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/ForceStartCommandHandler.cs @@ -0,0 +1,24 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.CommandHandlers; +using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; +using Serilog; + +namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers +{ + class ForceStartCommandHandler : BaseCommandHandler + { + private readonly ILogger _logger = Log.ForContext(); + private readonly ILobbyManager _lobbyManager; + + public ForceStartCommandHandler(ILobbyManager lobbyManager) + { + _lobbyManager = lobbyManager; + } + + public override void Handle(IPlayer player, SetBeatmapStartTime command) + { + _logger.Information(player.UserName + "Has force started a beatmap"); + _lobbyManager.ForceStartSelectedBeatmap = true; + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/ForceStartCommand.cs b/BeatTogether.DedicatedServer.Kernel/Commands/ForceStartCommand.cs new file mode 100644 index 00000000..d106ad44 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Commands/ForceStartCommand.cs @@ -0,0 +1,15 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; + +namespace BeatTogether.DedicatedServer.Kernel.Commands +{ + public class ForceStartCommand : ITextCommand + { + public string CommandName => "forcestart"; + public string ShortHandName => "fs"; + public string Description => "force starts the beatmap ignoring all players entitlements. Could cause players to have issues"; + + public void ReadValues(string[] Values) + { + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/Commands/SetBeatmapRouting.cs b/BeatTogether.DedicatedServer.Kernel/Commands/SetBeatmapRouting.cs index 46c07e74..ae2ca993 100644 --- a/BeatTogether.DedicatedServer.Kernel/Commands/SetBeatmapRouting.cs +++ b/BeatTogether.DedicatedServer.Kernel/Commands/SetBeatmapRouting.cs @@ -4,7 +4,7 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands { public class SetNoteRouting : ITextCommand { - public string CommandName => "setnotesvisible"; + public string CommandName => "snotesvisible"; public string ShortHandName => "n"; public string Description => "disables beatmap notes if set to true. Notes will be disabled automaticly if there are over 14 players, default false"; diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs index 96677bc9..87882bd5 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs @@ -18,6 +18,7 @@ public interface ILobbyManager float CountdownEndTime { get; } GameplayModifiers EmptyModifiers {get; } public bool SpectatingPlayersUpdated { get; set; } + public bool ForceStartSelectedBeatmap { get; set; } void Update(); BeatmapDifficulty[] GetSelectedBeatmapDifficulties(); diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index ce871ad7..69a7a893 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel.Design; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -10,7 +9,6 @@ using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.DedicatedServer.Messaging.Packets; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; @@ -35,6 +33,7 @@ public sealed class LobbyManager : ILobbyManager, IDisposable public bool AllPlayersAreInLobby => _playerRegistry.Players.All(p => p.InMenu);//if all are going to be spectating public bool DoesEveryoneOwnBeatmap => SelectedBeatmap != null && !_playerRegistry.Players.Any(p => p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown); public bool SpectatingPlayersUpdated { get; set; } = false; + public bool ForceStartSelectedBeatmap { get; set; } = false; public BeatmapIdentifier? SelectedBeatmap { get; private set; } = null; public GameplayModifiers SelectedModifiers { get; private set; } = new(); @@ -101,6 +100,52 @@ private async void UpdateLoop(CancellationToken cancellationToken) } } + public void ForceStartBeatmapUpdate() + { + if(SelectedBeatmap != null) + { + SetCountdown(CountdownState.StartBeatmapCountdown, _configuration.CountdownConfig.BeatMapStartCountdownTime); + + if (CountdownEndTime <= _instance.RunTime) + { + if (CountDownState != CountdownState.WaitingForEntitlement) + { + SetCountdown(CountdownState.WaitingForEntitlement); + } + if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || p.ForceLateJoin)) + { + //starts beatmap + _gameplayManager.SetBeatmap(SelectedBeatmap!, SelectedModifiers); + Task.Run(() => _gameplayManager.StartSong(CancellationToken.None)); + //stops countdown + SetCountdown(CountdownState.NotCountingDown); + ForceStartSelectedBeatmap = false; + return; + } + else + { + foreach(IPlayer p in _playerRegistry.Players) + { + if(p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) + { + p.ForceLateJoin = true; + } + } + } + if(CountdownEndTime + _configuration.SendPlayersWithoutEntitlementToSpectateTimeout <= _instance.RunTime) + { + foreach (IPlayer p in _playerRegistry.Players) + { + if (p.GetEntitlement(SelectedBeatmap.LevelId) is not EntitlementStatus.Ok) + { + p.ForceLateJoin = true; + } + } + } + } + } + } + public void Update() { if (_instance.State != MultiplayerGameState.Lobby) @@ -117,6 +162,12 @@ public void Update() Reason = CannotStartGameReason.None }, DeliveryMethod.ReliableOrdered); + if (ForceStartSelectedBeatmap) + { + ForceStartBeatmapUpdate(); + return; + } + foreach (IPlayer player in _playerRegistry.Players) { if (player.UpdateEntitlement || SpectatingPlayersUpdated) From 5bcb35f6d6d40e9f24fc865d812b49a6df60ef20 Mon Sep 17 00:00:00 2001 From: cubic Date: Sun, 27 Aug 2023 21:43:34 +0100 Subject: [PATCH 038/120] Registered command --- BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs b/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs index 302cef33..71092fd3 100644 --- a/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs +++ b/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs @@ -105,6 +105,7 @@ private void RegisterCommands() RegisterCommand(AccessLevel.Manager); RegisterCommand(AccessLevel.Manager); RegisterCommand(AccessLevel.Manager); + RegisterCommand(AccessLevel.Manager); } } } From 1ffeb4457f719a3139feb289821d3db9f8216a14 Mon Sep 17 00:00:00 2001 From: cubic Date: Sun, 27 Aug 2023 22:01:16 +0100 Subject: [PATCH 039/120] Fixed spectating checks and force start command handler --- .../CommandHandlers/ForceStartCommandHandler.cs | 4 ++-- .../Managers/LobbyManager.cs | 6 +++--- .../PacketHandlers/PlayerStatePacketHandler.cs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/ForceStartCommandHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/ForceStartCommandHandler.cs index 9da6d86c..1110c76b 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/ForceStartCommandHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/ForceStartCommandHandler.cs @@ -5,7 +5,7 @@ namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers { - class ForceStartCommandHandler : BaseCommandHandler + class ForceStartCommandHandler : BaseCommandHandler { private readonly ILogger _logger = Log.ForContext(); private readonly ILobbyManager _lobbyManager; @@ -15,7 +15,7 @@ public ForceStartCommandHandler(ILobbyManager lobbyManager) _lobbyManager = lobbyManager; } - public override void Handle(IPlayer player, SetBeatmapStartTime command) + public override void Handle(IPlayer player, ForceStartCommand command) { _logger.Information(player.UserName + "Has force started a beatmap"); _lobbyManager.ForceStartSelectedBeatmap = true; diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 69a7a893..992fccab 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -112,7 +112,7 @@ public void ForceStartBeatmapUpdate() { SetCountdown(CountdownState.WaitingForEntitlement); } - if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || p.ForceLateJoin)) + if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin)) { //starts beatmap _gameplayManager.SetBeatmap(SelectedBeatmap!, SelectedModifiers); @@ -177,7 +177,7 @@ public void Update() _packetDispatcher.SendToPlayer(player, new SetPlayersMissingEntitlementsToLevelPacket { PlayersWithoutEntitlements = _playerRegistry.Players - .Where(p => (p.GetEntitlement(player.BeatmapIdentifier.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) && !p.IsSpectating) + .Where(p => (p.GetEntitlement(player.BeatmapIdentifier.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) && !p.IsSpectating && p.WantsToPlayNextLevel) .Select(p => p.UserId).ToArray() }, DeliveryMethod.ReliableOrdered); _logger.Debug("Sent missing entitlement packet"); @@ -251,7 +251,7 @@ private void CountingDown(bool isReady, bool NotStartable) { SetCountdown(CountdownState.WaitingForEntitlement); } - if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || p.ForceLateJoin)) + if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin)) { //starts beatmap _gameplayManager.SetBeatmap(SelectedBeatmap!, SelectedModifiers); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs index 56fd4510..91e3882a 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs @@ -29,7 +29,7 @@ public override async Task Handle(IPlayer sender, PlayerStatePacket packet) await sender.PlayerAccessSemaphore.WaitAsync(); sender.State = packet.PlayerState; - if (packet.PlayerState.Contains("spectating") != sender.State.Contains("spectating")) + if (packet.PlayerState.Contains("spectating") != sender.State.Contains("spectating") || packet.PlayerState.Contains("wants_to_play_next_level") != sender.State.Contains("wants_to_play_next_level")) _lobbyManager.SpectatingPlayersUpdated = true; sender.PlayerAccessSemaphore.Release(); return; From 8a35148e38051baea6bd03a855f348e504117f9d Mon Sep 17 00:00:00 2001 From: cubic Date: Sun, 27 Aug 2023 22:10:57 +0100 Subject: [PATCH 040/120] Fixed Start button allowing play if player in spectator and does not own map --- BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 992fccab..ddad044b 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -31,7 +31,7 @@ public sealed class LobbyManager : ILobbyManager, IDisposable public bool NoPlayersReady => _playerRegistry.Players.All(p => !p.IsReady || !p.WantsToPlayNextLevel); //players not ready or are going to spectate public bool AllPlayersNotWantToPlayNextLevel => _playerRegistry.Players.All(p => !p.WantsToPlayNextLevel);//if all are going to be spectating public bool AllPlayersAreInLobby => _playerRegistry.Players.All(p => p.InMenu);//if all are going to be spectating - public bool DoesEveryoneOwnBeatmap => SelectedBeatmap != null && !_playerRegistry.Players.Any(p => p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown); + public bool DoesEveryoneOwnBeatmap => SelectedBeatmap != null && !_playerRegistry.Players.Any(p => (p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) && !p.IsSpectating && p.WantsToPlayNextLevel); public bool SpectatingPlayersUpdated { get; set; } = false; public bool ForceStartSelectedBeatmap { get; set; } = false; From e55225d0804e8c1a02420a65dcbdccf8632553a9 Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 28 Aug 2023 18:15:35 +0100 Subject: [PATCH 041/120] Fake player entitlements so that the game starts in forced mode --- .../Managers/LobbyManager.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index ddad044b..b6bbcb43 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -114,6 +114,7 @@ public void ForceStartBeatmapUpdate() } if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin)) { + //The clients need to be sent that all the payers have OK entitlement //starts beatmap _gameplayManager.SetBeatmap(SelectedBeatmap!, SelectedModifiers); Task.Run(() => _gameplayManager.StartSong(CancellationToken.None)); @@ -128,6 +129,11 @@ public void ForceStartBeatmapUpdate() { if(p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) { + _packetDispatcher.SendFromPlayer(p, new SetIsEntitledToLevelPacket() + { + LevelId = SelectedBeatmap.LevelId, + Entitlement = EntitlementStatus.Ok + }, DeliveryMethod.ReliableOrdered); p.ForceLateJoin = true; } } @@ -138,6 +144,11 @@ public void ForceStartBeatmapUpdate() { if (p.GetEntitlement(SelectedBeatmap.LevelId) is not EntitlementStatus.Ok) { + _packetDispatcher.SendFromPlayer(p, new SetIsEntitledToLevelPacket() + { + LevelId = SelectedBeatmap.LevelId, + Entitlement = EntitlementStatus.Ok + }, DeliveryMethod.ReliableOrdered); p.ForceLateJoin = true; } } @@ -267,6 +278,11 @@ private void CountingDown(bool isReady, bool NotStartable) { //Force the player to join late p.ForceLateJoin = true; + _packetDispatcher.SendFromPlayer(p, new SetIsEntitledToLevelPacket() + { + LevelId = SelectedBeatmap!.LevelId, + Entitlement = EntitlementStatus.Ok + }, DeliveryMethod.ReliableOrdered); _packetDispatcher.SendToPlayer(p, new CancelLevelStartPacket(), DeliveryMethod.ReliableOrdered); _packetDispatcher.SendToPlayer(p, new SetIsReadyPacket() { IsReady = false }, DeliveryMethod.ReliableOrdered); } From 2920756c9beef9c5c12be9846b5b4916b74630db Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 28 Aug 2023 21:39:48 +0100 Subject: [PATCH 042/120] Fixing entitlement on force starts --- .../Managers/LobbyManager.cs | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index b6bbcb43..827b4e83 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -114,6 +114,17 @@ public void ForceStartBeatmapUpdate() } if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin)) { + foreach (IPlayer p in _playerRegistry.Players) + { + if (p.GetEntitlement(SelectedBeatmap.LevelId) is not EntitlementStatus.Ok || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin) + { + _packetDispatcher.SendFromPlayer(p, new SetIsEntitledToLevelPacket() + { + LevelId = SelectedBeatmap.LevelId, + Entitlement = EntitlementStatus.Ok + }, DeliveryMethod.ReliableOrdered); + } + } //The clients need to be sent that all the payers have OK entitlement //starts beatmap _gameplayManager.SetBeatmap(SelectedBeatmap!, SelectedModifiers); @@ -127,13 +138,8 @@ public void ForceStartBeatmapUpdate() { foreach(IPlayer p in _playerRegistry.Players) { - if(p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) + if(p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin) { - _packetDispatcher.SendFromPlayer(p, new SetIsEntitledToLevelPacket() - { - LevelId = SelectedBeatmap.LevelId, - Entitlement = EntitlementStatus.Ok - }, DeliveryMethod.ReliableOrdered); p.ForceLateJoin = true; } } @@ -264,6 +270,17 @@ private void CountingDown(bool isReady, bool NotStartable) } if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin)) { + foreach(IPlayer p in _playerRegistry.Players) + { + if (p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin) + { + _packetDispatcher.SendFromPlayer(p, new SetIsEntitledToLevelPacket() + { + LevelId = SelectedBeatmap!.LevelId, + Entitlement = EntitlementStatus.Ok + }, DeliveryMethod.ReliableOrdered); + } + } //starts beatmap _gameplayManager.SetBeatmap(SelectedBeatmap!, SelectedModifiers); Task.Run(() => _gameplayManager.StartSong(CancellationToken.None)); @@ -278,11 +295,6 @@ private void CountingDown(bool isReady, bool NotStartable) { //Force the player to join late p.ForceLateJoin = true; - _packetDispatcher.SendFromPlayer(p, new SetIsEntitledToLevelPacket() - { - LevelId = SelectedBeatmap!.LevelId, - Entitlement = EntitlementStatus.Ok - }, DeliveryMethod.ReliableOrdered); _packetDispatcher.SendToPlayer(p, new CancelLevelStartPacket(), DeliveryMethod.ReliableOrdered); _packetDispatcher.SendToPlayer(p, new SetIsReadyPacket() { IsReady = false }, DeliveryMethod.ReliableOrdered); } From 4790985618c63c1f714bfa401122c3a3d0d500f3 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 12:43:13 +0100 Subject: [PATCH 043/120] Add additional logging, don't log NodePoseSyncState packets --- BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs | 9 +++++++++ BeatTogether.DedicatedServer.Kernel/PacketSource.cs | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index 3c5d7795..13c4337e 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -43,11 +43,13 @@ private void SendInternal(IPlayer player, ref SpanBuffer writer, DeliveryMethod if (player.IsENetConnection) { // ENet send + _logger.Verbose($"Sending packet (SenderId={ServerId}) to player {player.ConnectionId} with UserId {player.UserId} via ENet"); _dedicatedInstance.ENetServer.Send(player.ENetPeerId!.Value, writer.Data, deliveryMethod); return; } // LiteNet send + _logger.Verbose($"Sending packet (SenderId={ServerId}) to player {player.ConnectionId} with UserId {player.UserId} via LiteNet"); Send(player.Endpoint, writer.Data, deliveryMethod); } @@ -103,6 +105,13 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packe $"Sending MultiPacket " + $"(ExcludedId={excludedPlayer.ConnectionId})" ); + if (_logger.IsEnabled(Serilog.Events.LogEventLevel.Verbose)) + for (int i = 0; i < packets.Length; i++) + { + _logger.Verbose( + $"Packet {i} is of type '{packets[i].GetType().Name}' " + ); + } var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index 8154f71a..cddeb6ef 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -4,6 +4,7 @@ using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; +using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Registries; using BeatTogether.Extensions; using BeatTogether.LiteNetLib; @@ -111,6 +112,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D } break; } + if (packet == null) { // skip any unprocessed bytes @@ -149,7 +151,8 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D var packetHandler = _serviceProvider.GetService(packetHandlerType); if (packetHandler is null) { - _logger.Verbose($"No handler exists for packet of type '{packetType.Name}'."); + if (!packetType.Name.StartsWith("NodePoseSyncState")) + _logger.Verbose($"No handler exists for packet of type '{packetType.Name}'."); // skip any unprocessed bytes var processedBytes = HandleRead.Offset - prevPosition; From e49f540d595af79e663f5251404c1cb37b322549 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 12:44:30 +0100 Subject: [PATCH 044/120] Update Cryptoprovider to RandomNumberGenerator as RNGCryptoServiceProvider is deprecated --- .../Encryption/EncryptedPacketWriter.cs | 4 ++-- .../Providers/CookieProvider.cs | 4 ++-- .../Providers/RandomProvider.cs | 4 ++-- .../Extensions/HostBuilderExtensions.cs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs index 41ee1ffc..64797183 100644 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs +++ b/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs @@ -8,10 +8,10 @@ namespace BeatTogether.DedicatedServer.Kernel.Encryption { public sealed class EncryptedPacketWriter : IEncryptedPacketWriter { - private readonly RNGCryptoServiceProvider _rngCryptoServiceProvider; + private readonly RandomNumberGenerator _rngCryptoServiceProvider; public EncryptedPacketWriter( - RNGCryptoServiceProvider rngCryptoServiceProvider) + RandomNumberGenerator rngCryptoServiceProvider) { _rngCryptoServiceProvider = rngCryptoServiceProvider; } diff --git a/BeatTogether.DedicatedServer.Kernel/Providers/CookieProvider.cs b/BeatTogether.DedicatedServer.Kernel/Providers/CookieProvider.cs index 8eff1e2a..1980f5cb 100644 --- a/BeatTogether.DedicatedServer.Kernel/Providers/CookieProvider.cs +++ b/BeatTogether.DedicatedServer.Kernel/Providers/CookieProvider.cs @@ -7,9 +7,9 @@ public class CookieProvider : ICookieProvider { private const int CookieLength = 32; - private readonly RNGCryptoServiceProvider _rngCryptoServiceProvider; + private readonly RandomNumberGenerator _rngCryptoServiceProvider; - public CookieProvider(RNGCryptoServiceProvider rngCryptoServiceProvider) + public CookieProvider(RandomNumberGenerator rngCryptoServiceProvider) { _rngCryptoServiceProvider = rngCryptoServiceProvider; } diff --git a/BeatTogether.DedicatedServer.Kernel/Providers/RandomProvider.cs b/BeatTogether.DedicatedServer.Kernel/Providers/RandomProvider.cs index 23a51f1d..66f57974 100644 --- a/BeatTogether.DedicatedServer.Kernel/Providers/RandomProvider.cs +++ b/BeatTogether.DedicatedServer.Kernel/Providers/RandomProvider.cs @@ -7,9 +7,9 @@ public class RandomProvider : IRandomProvider { private const int RandomLength = 32; - private readonly RNGCryptoServiceProvider _rngCryptoServiceProvider; + private readonly RandomNumberGenerator _rngCryptoServiceProvider; - public RandomProvider(RNGCryptoServiceProvider rngCryptoServiceProvider) + public RandomProvider(RandomNumberGenerator rngCryptoServiceProvider) { _rngCryptoServiceProvider = rngCryptoServiceProvider; } diff --git a/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs b/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs index 0d6c31f1..42e40b80 100644 --- a/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs +++ b/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs @@ -27,7 +27,7 @@ public static IHostBuilder UseDedicatedServerNode(this IHostBuilder hostBuilder) services .AddCoreSecurity() .AddConfiguration("Node") - .AddTransient() + .AddSingleton(RandomNumberGenerator.Create()) .AddSingleton() .AddSingleton() .AddSingleton() From 8e40641d5496b7902ec6d334736c4d4d64eb7888 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 15:02:58 +0100 Subject: [PATCH 045/120] Update SongPackMask --- .../Models/BitMask256.cs | 142 ++++++++++++++++++ .../Models/SongPackMask.cs | 2 +- 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 BeatTogether.DedicatedServer.Messaging/Models/BitMask256.cs diff --git a/BeatTogether.DedicatedServer.Messaging/Models/BitMask256.cs b/BeatTogether.DedicatedServer.Messaging/Models/BitMask256.cs new file mode 100644 index 00000000..d539af60 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Models/BitMask256.cs @@ -0,0 +1,142 @@ +using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Models +{ + public class BitMask256 : INetSerializable + { + public ulong D0 { get; set; } + public ulong D1 { get; set; } + public ulong D2 { get; set; } + public ulong D3 { get; set; } + + public const int BitCount = 256; + + public static BitMask256 MaxValue => new(ulong.MaxValue, ulong.MaxValue, ulong.MaxValue, ulong.MaxValue); + public static BitMask256 MinValue => new(); + + public BitMask256(ulong d0 = 0U, ulong d1 = 0U, ulong d2 = 0U, ulong d3 = 0U) + { + D0 = d0; + D1 = d1; + D2 = d2; + D3 = d3; + } + + #region Bits + + public BitMask256 SetBits(int offset, ulong bits) + { + ulong d = D0; + int num = offset - 192; + ulong num2 = d | ShiftLeft(bits, num); + ulong d2 = D1; + int num3 = offset - 128; + ulong num4 = d2 | ShiftLeft(bits, num3); + ulong d3 = D2; + int num5 = offset - 64; + return new BitMask256(num2, num4, d3 | ShiftLeft(bits, num5), D3 | ShiftLeft(bits, offset)); + } + + public ulong GetBits(int offset, int count) + { + ulong num = (1UL << count) - 1UL; + int num2 = offset - 192; + ulong num3 = ShiftRight(D0, num2); + int num4 = offset - 128; + ulong num5 = num3 | ShiftRight(D1, num4); + int num6 = offset - 64; + return (num5 | ShiftRight(D2, num6) | ShiftRight(D3, offset)) & num; + } + + #endregion + + #region Network + + public void WriteTo(ref SpanBuffer bufferWriter) + { + bufferWriter.WriteUInt64(D0); + bufferWriter.WriteUInt64(D1); + bufferWriter.WriteUInt64(D2); + bufferWriter.WriteUInt64(D3); + } + + public void ReadFrom(ref SpanBuffer bufferReader) + { + D0 = bufferReader.ReadUInt64(); + D1 = bufferReader.ReadUInt64(); + D2 = bufferReader.ReadUInt64(); + D3 = bufferReader.ReadUInt64(); + } + + #endregion + + private static uint MurmurHash2(string key) + { + uint num = (uint)key.Length; + uint num2 = 33U ^ num; + int num3 = 0; + while (num >= 4U) + { + uint num4 = (uint)((uint)key[num3 + 3] << 24 | (uint)key[num3 + 2] << 16 | (uint)key[num3 + 1] << 8 | key[num3]); + num4 *= 1540483477U; + num4 ^= num4 >> 24; + num4 *= 1540483477U; + num2 *= 1540483477U; + num2 ^= num4; + num3 += 4; + num -= 4U; + } + switch (num) + { + case 1U: + num2 ^= (uint)key[num3]; + num2 *= 1540483477U; + break; + case 2U: + num2 ^= (uint)((uint)key[num3 + 1] << 8); + num2 ^= (uint)key[num3]; + num2 *= 1540483477U; + break; + case 3U: + num2 ^= (uint)((uint)key[num3 + 2] << 16); + num2 ^= (uint)((uint)key[num3 + 1] << 8); + num2 ^= (uint)key[num3]; + num2 *= 1540483477U; + break; + } + num2 ^= num2 >> 13; + num2 *= 1540483477U; + return num2 ^ num2 >> 15; + } + + + public static ulong ShiftLeft(ulong value, in int shift) + { + if (shift < 0) + { + int num = -shift; + return ShiftRight(value, num); + } + if (shift < 64) + { + return value << shift; + } + return 0UL; + } + + public static ulong ShiftRight(ulong value, in int shift) + { + if (shift < 0) + { + int num = -shift; + return ShiftLeft(value, num); + } + if (shift < 64) + { + return value >> shift; + } + return 0UL; + } + } +} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Messaging/Models/SongPackMask.cs b/BeatTogether.DedicatedServer.Messaging/Models/SongPackMask.cs index 10434cd8..779310bd 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/SongPackMask.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/SongPackMask.cs @@ -1,6 +1,6 @@ namespace BeatTogether.DedicatedServer.Messaging.Models { - public sealed class SongPackMask : BitMask128 + public sealed class SongPackMask : BitMask256 { } } From 8841ed9bcc590bc996d7851d33a02416b3f53089 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 16:29:35 +0100 Subject: [PATCH 046/120] Remove unused using reference --- BeatTogether.DedicatedServer.Kernel/PacketSource.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index cddeb6ef..deb871e3 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -4,7 +4,6 @@ using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; -using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Registries; using BeatTogether.Extensions; using BeatTogether.LiteNetLib; From d4b12beab245a01d477bf30d11600ebaa516998f Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 16:30:29 +0100 Subject: [PATCH 047/120] BREAKING: Routing Header add third byte PacketOptions --- .../Enums/PacketOption.cs | 9 +++++++++ .../Extensions/SpanBufferExtensions.cs | 19 +++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 BeatTogether.DedicatedServer.Messaging/Enums/PacketOption.cs diff --git a/BeatTogether.DedicatedServer.Messaging/Enums/PacketOption.cs b/BeatTogether.DedicatedServer.Messaging/Enums/PacketOption.cs new file mode 100644 index 00000000..eb0840d4 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Enums/PacketOption.cs @@ -0,0 +1,9 @@ +namespace BeatTogether.DedicatedServer.Messaging.Enums +{ + public enum PacketOption + { + None = 0, + Encrypted = 1, + OnlyFirstDegreeConnections = 2 + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs index a8cb591f..e52121a9 100644 --- a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs +++ b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs @@ -1,4 +1,5 @@ -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Enums; +using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; using System; using System.Diagnostics.CodeAnalysis; @@ -9,10 +10,10 @@ namespace BeatTogether.Extensions { public static class SpanBufferExtensions { - public static (byte SenderId, byte ReceiverId) ReadRoutingHeader(this ref SpanBuffer reader) => - (reader.ReadUInt8(), reader.ReadUInt8()); + public static (byte SenderId, byte ReceiverId, PacketOption packetOptions) ReadRoutingHeader(this ref SpanBuffer reader) => + (reader.ReadUInt8(), reader.ReadUInt8(), (PacketOption)reader.ReadUInt8()); - public static bool TryReadRoutingHeader(this ref SpanBuffer reader, [MaybeNullWhen(false)] out (byte SenderId, byte ReceiverId) routingHeader) + public static bool TryReadRoutingHeader(this ref SpanBuffer reader, [MaybeNullWhen(false)] out (byte SenderId, byte ReceiverId, PacketOption packetOptions) routingHeader) { if (reader.RemainingSize < 2) { @@ -20,14 +21,20 @@ public static bool TryReadRoutingHeader(this ref SpanBuffer reader, [MaybeNullWh return false; } - routingHeader = (reader.ReadUInt8(), reader.ReadUInt8()); + routingHeader = (reader.ReadUInt8(), reader.ReadUInt8(), (PacketOption)reader.ReadUInt8()); return true; } - public static void WriteRoutingHeader(this ref SpanBuffer writer, byte senderId, byte receiverId) + public static void WriteRoutingHeader(this ref SpanBuffer writer, byte senderId, byte receiverId, PacketOption packetOptions = PacketOption.None) => + writer.WriteRoutingHeader(senderId, receiverId, (byte)packetOptions); + + + + public static void WriteRoutingHeader(this ref SpanBuffer writer, byte senderId, byte receiverId, byte packetOptions = 0) { writer.WriteUInt8(senderId); writer.WriteUInt8(receiverId); + writer.WriteUInt8(packetOptions); } public static ulong ReadVarULong(this ref SpanBuffer bufferReader) From 174d7d272e4453b408c333bda203ac6733f282f3 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 17:23:53 +0100 Subject: [PATCH 048/120] Change SyncTime to long from float --- .../Abstractions/IDedicatedInstance.cs | 2 +- .../Abstractions/IPlayer.cs | 2 +- .../DedicatedInstance.cs | 2 +- BeatTogether.DedicatedServer.Kernel/Player.cs | 4 ++-- .../Types/RollingAverage.cs | 17 +++++++---------- .../Packets/PlayerLatencyPacket.cs | 6 +++--- .../Packets/SyncTimePacket.cs | 6 +++--- 7 files changed, 18 insertions(+), 21 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs index a5947b70..4e3164f1 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs @@ -20,7 +20,7 @@ public interface IDedicatedInstance void InstanceConfigUpdated(); InstanceConfiguration _configuration { get; } bool IsRunning { get; } - float RunTime { get; } + long RunTime { get; } public int LiteNetPort { get; } public int ENetPort { get; } MultiplayerGameState State { get; } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index b3fb1f2a..72088927 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -30,7 +30,7 @@ public interface IPlayer bool IsENetConnection => ENetPeerId.HasValue; RollingAverage Latency { get; } - float SyncTime { get; } + long SyncTime { get; } int SortIndex { get; set; } AvatarData Avatar { get; set; } bool IsReady { get; set; } diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index d2942cdf..d459f5b6 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -38,7 +38,7 @@ public sealed class DedicatedInstance : LiteNetServer, IDedicatedInstance public int LiteNetPort => _configuration.LiteNetPort; public int ENetPort => _configuration.ENetPort; public bool IsRunning => IsStarted; - public float RunTime => (DateTime.UtcNow.Ticks - _startTime) / 10000000.0f; + public long RunTime => (DateTime.UtcNow.Ticks - _startTime) / 10000L; public float NoPlayersTime { get; private set; } = -1; //tracks the instance time once there are 0 players in the lobby public MultiplayerGameState State { get; private set; } = MultiplayerGameState.Lobby; diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index 8cf10d0a..a2cdfa51 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -26,7 +26,7 @@ public sealed class Player : IPlayer public uint? ENetPeerId { get; set; } public bool IsENetConnection => ENetPeerId.HasValue; public RollingAverage Latency { get; } = new(30); - public float SyncTime => + public long SyncTime => Math.Min(Instance.RunTime - Latency.CurrentAverage - _syncTimeOffset, Instance.RunTime); public int SortIndex { get; set; } @@ -61,7 +61,7 @@ public sealed class Player : IPlayer public bool FinishedLevel => State.Contains("finished_level"); //If the player has finished the level public bool InMenu => State.Contains("in_menu"); //Should be true while in lobby - private const float _syncTimeOffset = 0.06f; + private const long _syncTimeOffset = 6L; private readonly ConcurrentDictionary _entitlements = new(); public Player(EndPoint endPoint, IDedicatedInstance instance, diff --git a/BeatTogether.DedicatedServer.Kernel/Types/RollingAverage.cs b/BeatTogether.DedicatedServer.Kernel/Types/RollingAverage.cs index e0314251..0dfef632 100644 --- a/BeatTogether.DedicatedServer.Kernel/Types/RollingAverage.cs +++ b/BeatTogether.DedicatedServer.Kernel/Types/RollingAverage.cs @@ -5,14 +5,12 @@ namespace BeatTogether.DedicatedServer.Kernel.Types public class RollingAverage { private long _currentTotal; - private float _currentAverage; + private long _currentAverage; private readonly long[] _buffer; private int _index; private int _length; - private const long _granularity = 1000L; - - public float CurrentAverage => _currentAverage; + public long CurrentAverage => _currentAverage; public bool HasValue => _length > 0; public RollingAverage(int window) @@ -20,25 +18,24 @@ public RollingAverage(int window) _buffer = new long[window]; } - public void Update(float value) + public void Update(long value) { var currentTotal = _currentTotal; if (_length == _buffer.Length) { currentTotal -= _buffer[_index]; } - var i = (long)(value * 1000f); - _buffer[_index] = i; + _buffer[_index] = value; _index = (_index + 1) % _buffer.Length; _length = Math.Min(_length + 1, _buffer.Length); - currentTotal += i; + currentTotal += value; _currentTotal = currentTotal; - _currentAverage = (float)(currentTotal / (double)(_granularity * _length)); + _currentAverage = (currentTotal / (long)_length); } public void Reset() { - _currentAverage = 0f; + _currentAverage = 0L; _index = 0; _length = 0; _currentTotal = 0L; diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs index 1cb2ddf8..df8c3a8d 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs @@ -5,16 +5,16 @@ namespace BeatTogether.DedicatedServer.Messaging.Packets { public sealed class PlayerLatencyPacket : INetSerializable { - public float Latency { get; set; } + public long Latency { get; set; } public void ReadFrom(ref SpanBuffer reader) { - Latency = reader.ReadFloat32(); + Latency = (long)reader.ReadUInt64(); } public void WriteTo(ref SpanBuffer writer) { - writer.WriteFloat32(Latency); + writer.WriteUInt64((ulong)Latency); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs index 60331ffa..ffa2c98b 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs @@ -5,16 +5,16 @@ namespace BeatTogether.DedicatedServer.Messaging.Packets { public sealed class SyncTimePacket : INetSerializable { - public float SyncTime { get; set; } + public long SyncTime { get; set; } public void WriteTo(ref SpanBuffer writer) { - writer.WriteFloat32(SyncTime); + writer.WriteUInt64((ulong)SyncTime); } public void ReadFrom(ref SpanBuffer reader) { - SyncTime = reader.ReadFloat32(); + SyncTime = (long)reader.ReadUInt64(); } } } From 5f11dd222aae429fcbaaca450063519b3d5ce358 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 17:26:16 +0100 Subject: [PATCH 049/120] Update PacketEncryptionLayer to RandomNumberGenerator --- .../Encryption/PacketEncryptionLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs index d2ec3db8..ff61a5be 100644 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs @@ -33,7 +33,7 @@ public PacketEncryptionLayer( IEncryptedPacketReader encryptedPacketReader, IEncryptedPacketWriter encryptedPacketWriter, IDiffieHellmanService diffieHellmanService, - RNGCryptoServiceProvider rngCryptoServiceProvider) + RandomNumberGenerator rngCryptoServiceProvider) { _encryptedPacketReader = encryptedPacketReader; _encryptedPacketWriter = encryptedPacketWriter; From b58d5b04c8f86510d4171b6a94bf398da0af1545 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 17:27:14 +0100 Subject: [PATCH 050/120] Make use of PacketOption Enum within RoutingHeader --- BeatTogether.DedicatedServer.Kernel/PacketSource.cs | 5 ++++- .../Extensions/SpanBufferExtensions.cs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index deb871e3..9a2ef48c 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -2,6 +2,7 @@ using System.Net; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; using BeatTogether.DedicatedServer.Messaging.Registries; @@ -184,7 +185,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D #region Private Methods private void RoutePacket(IPlayer sender, - (byte SenderId, byte ReceiverId) routingHeader, + (byte SenderId, byte ReceiverId, PacketOption packetOption) routingHeader, ref SpanBuffer reader, DeliveryMethod deliveryMethod) { routingHeader.SenderId = sender.ConnectionId; @@ -196,6 +197,7 @@ private void RoutePacket(IPlayer sender, _logger.Verbose( $"Routing packet from {routingHeader.SenderId} -> all players " + + $"PacketOption {routingHeader.packetOption} " + $"(Secret='{sender.Secret}', DeliveryMethod={deliveryMethod})." ); foreach (var player in _playerRegistry.Players) @@ -217,6 +219,7 @@ private void RoutePacket(IPlayer sender, } _logger.Verbose( $"Routing packet from {routingHeader.SenderId} -> {routingHeader.ReceiverId} " + + $"PacketOption {routingHeader.packetOption} " + $"(Secret='{sender.Secret}', DeliveryMethod={deliveryMethod})." ); _packetDispatcher.Send(receiver.Endpoint, writer.Data, deliveryMethod); diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs index e52121a9..429cbe62 100644 --- a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs +++ b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs @@ -30,7 +30,7 @@ public static void WriteRoutingHeader(this ref SpanBuffer writer, byte senderId, - public static void WriteRoutingHeader(this ref SpanBuffer writer, byte senderId, byte receiverId, byte packetOptions = 0) + public static void WriteRoutingHeader(this ref SpanBuffer writer, byte senderId, byte receiverId, byte packetOptions) { writer.WriteUInt8(senderId); writer.WriteUInt8(receiverId); From 19c9fa70277a7dac2ba030ce805ae62b85042da7 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 20:05:01 +0100 Subject: [PATCH 051/120] Add new PacketType OptionalAvatarData --- .../Enums/MultiplayerSessionPacketType.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/BeatTogether.DedicatedServer.Messaging/Enums/MultiplayerSessionPacketType.cs b/BeatTogether.DedicatedServer.Messaging/Enums/MultiplayerSessionPacketType.cs index 72efa43d..0e7ce02f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Enums/MultiplayerSessionPacketType.cs +++ b/BeatTogether.DedicatedServer.Messaging/Enums/MultiplayerSessionPacketType.cs @@ -8,6 +8,7 @@ public enum MultiplayerSessionPacketType : byte ScoreSyncState = 3, NodePoseSyncStateDelta = 4, ScoreSyncStateDelta = 5, + OptionalAvatarData = 6, MultiplayerCore = 100 } } From 8335a24b53a909b9d58d5c4b949c43fd7ce1ff3d Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 20:06:24 +0100 Subject: [PATCH 052/120] Addittional logging --- .../PacketHandlers/PlayerLatencyPacketHandler.cs | 9 +++++++-- .../PacketHandlers/SyncTimePacketHandler.cs | 5 +++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs index 9b825191..cc384452 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs @@ -20,8 +20,8 @@ public PlayerLatencyPacketHandler( public override async Task Handle(IPlayer sender, PlayerLatencyPacket packet) { _logger.Debug( - $"Handling packet of type '{nameof(SyncTimePacket)}' " + - $"(SenderId={sender.ConnectionId}, SyncTime={packet.Latency})." + $"Handling packet of type '{nameof(PlayerLatencyPacket)}' " + + $"(SenderId={sender.ConnectionId}, Latency={packet.Latency})." ); await sender.PlayerAccessSemaphore.WaitAsync(); @@ -31,6 +31,11 @@ public override async Task Handle(IPlayer sender, PlayerLatencyPacket packet) { Latency = sender.Latency.CurrentAverage }, DeliveryMethod.ReliableOrdered); + + _logger.Verbose(( + $"Preparing packet of type '{nameof(PlayerLatencyPacket)}' " + + $"(SenderId={sender.ConnectionId}, Latency={sender.Latency.CurrentAverage})." + ); return; } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/SyncTimePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/SyncTimePacketHandler.cs index 6f7cf09e..025c956a 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/SyncTimePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/SyncTimePacketHandler.cs @@ -27,6 +27,11 @@ public override Task Handle(IPlayer sender, SyncTimePacket packet) { SyncTime = sender.SyncTime }, DeliveryMethod.ReliableOrdered); + + _logger.Verbose( + $"Preparing '{nameof(SyncTimePacket)}' " + + $"(SenderId={sender.ConnectionId}, SyncTime={sender.SyncTime})." + ); return Task.CompletedTask; } } From cadf61cd71575eeb11e477283563f5e7f44f5d73 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 20:07:02 +0100 Subject: [PATCH 053/120] Change log line for PacketOption --- BeatTogether.DedicatedServer.Kernel/PacketSource.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index 9a2ef48c..3d85f8b6 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -197,7 +197,7 @@ private void RoutePacket(IPlayer sender, _logger.Verbose( $"Routing packet from {routingHeader.SenderId} -> all players " + - $"PacketOption {routingHeader.packetOption} " + + $"PacketOption='{routingHeader.packetOption}' " + $"(Secret='{sender.Secret}', DeliveryMethod={deliveryMethod})." ); foreach (var player in _playerRegistry.Players) @@ -219,7 +219,7 @@ private void RoutePacket(IPlayer sender, } _logger.Verbose( $"Routing packet from {routingHeader.SenderId} -> {routingHeader.ReceiverId} " + - $"PacketOption {routingHeader.packetOption} " + + $"PacketOption='{routingHeader.packetOption}' " + $"(Secret='{sender.Secret}', DeliveryMethod={deliveryMethod})." ); _packetDispatcher.Send(receiver.Endpoint, writer.Data, deliveryMethod); From 2064fc8b23851813e9645e6b5b89bdd945307e5a Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 20:07:34 +0100 Subject: [PATCH 054/120] Change num to hash in function to be clearer --- BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs index 7e6ebc54..118b1713 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs @@ -12,14 +12,14 @@ public class BitMask128 : INetSerializable public bool Contains(string value, int hashCount = 3, int hashBits = 8) { - uint num = MurmurHash2(value); + uint hash = MurmurHash2(value); for (int i = 0; i < hashCount; i++) { - if (GetBits((int)((ulong)num % (ulong)((long)BitCount)), 1) == 0UL) + if (GetBits((int)((ulong)hash % (ulong)((long)BitCount)), 1) == 0UL) { return false; } - num >>= hashBits; + hash >>= hashBits; } return true; } From 6763bfa3ad32c4beb4ffe6b645f288abc8f802e4 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Dec 2023 20:08:39 +0100 Subject: [PATCH 055/120] Change packets to long from float --- .../Abstractions/BaseRpcPacket.cs | 13 +++++++------ .../Packets/PingPacket.cs | 9 +++++---- .../Packets/PlayerLatencyPacket.cs | 7 ++++--- .../Packets/PongPacket.cs | 9 +++++---- .../Packets/SyncTimePacket.cs | 7 ++++--- 5 files changed, 25 insertions(+), 20 deletions(-) diff --git a/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcPacket.cs b/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcPacket.cs index 11f848ef..8d32328c 100644 --- a/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcPacket.cs @@ -1,29 +1,30 @@ -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Abstractions { public abstract class BaseRpcPacket : INetSerializable { - public float SyncTime { get; set; } + public long SyncTime { get; set; } public virtual void ReadFrom(ref SpanBuffer reader) { - SyncTime = reader.ReadFloat32(); + SyncTime = (long)reader.ReadVarULong(); } public virtual void WriteTo(ref SpanBuffer writer) { - writer.WriteFloat32(SyncTime); + writer.WriteVarULong((ulong)SyncTime); } public virtual void ReadFrom(ref MemoryBuffer reader) { - SyncTime = reader.ReadFloat32(); + SyncTime = (long)reader.ReadVarULong(); } public virtual void WriteTo(ref MemoryBuffer writer) { - writer.WriteFloat32(SyncTime); + writer.WriteVarULong((ulong)SyncTime); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs index c2e6df18..8642c0d6 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs @@ -1,20 +1,21 @@ -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { public sealed class PingPacket : INetSerializable { - public float PingTime { get; set; } + public long PingTime { get; set; } public void WriteTo(ref SpanBuffer writer) { - writer.WriteFloat32(PingTime); + writer.WriteVarULong((ulong)PingTime); } public void ReadFrom(ref SpanBuffer reader) { - PingTime = reader.ReadFloat32(); + PingTime = (long)reader.ReadVarULong(); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs index df8c3a8d..5f64c8e2 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs @@ -1,4 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets @@ -9,12 +10,12 @@ public sealed class PlayerLatencyPacket : INetSerializable public void ReadFrom(ref SpanBuffer reader) { - Latency = (long)reader.ReadUInt64(); + Latency = (long)reader.ReadVarULong(); } public void WriteTo(ref SpanBuffer writer) { - writer.WriteUInt64((ulong)Latency); + writer.WriteVarULong((ulong)Latency); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs index c244980e..e18c4f43 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs @@ -1,20 +1,21 @@ -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { public sealed class PongPacket : INetSerializable { - public float PingTime { get; set; } + public long PingTime { get; set; } public void WriteTo(ref SpanBuffer writer) { - writer.WriteFloat32(PingTime); + writer.WriteVarULong((ulong)PingTime); } public void ReadFrom(ref SpanBuffer reader) { - PingTime = reader.ReadFloat32(); + PingTime = (long)reader.ReadVarULong(); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs index ffa2c98b..bdcba96d 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs @@ -1,4 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets @@ -9,12 +10,12 @@ public sealed class SyncTimePacket : INetSerializable public void WriteTo(ref SpanBuffer writer) { - writer.WriteUInt64((ulong)SyncTime); + writer.WriteVarULong((ulong)SyncTime); } public void ReadFrom(ref SpanBuffer reader) { - SyncTime = (long)reader.ReadUInt64(); + SyncTime = (long)reader.ReadVarULong(); } } } From ce98cf94225a89df028d570c0019ff8818733826 Mon Sep 17 00:00:00 2001 From: Michael R Date: Mon, 18 Dec 2023 08:31:49 +0100 Subject: [PATCH 056/120] Fix remove extra ( --- .../PacketHandlers/PlayerLatencyPacketHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs index cc384452..01151031 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs @@ -32,7 +32,7 @@ public override async Task Handle(IPlayer sender, PlayerLatencyPacket packet) Latency = sender.Latency.CurrentAverage }, DeliveryMethod.ReliableOrdered); - _logger.Verbose(( + _logger.Verbose( $"Preparing packet of type '{nameof(PlayerLatencyPacket)}' " + $"(SenderId={sender.ConnectionId}, Latency={sender.Latency.CurrentAverage})." ); From 1234c91bb9ed3ad515f56bcada71360ce5742f92 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Mon, 18 Dec 2023 14:13:37 +0100 Subject: [PATCH 057/120] Fix capitalization --- BeatTogether.DedicatedServer.Kernel/PacketSource.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index 3d85f8b6..eb92a44c 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -185,19 +185,19 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D #region Private Methods private void RoutePacket(IPlayer sender, - (byte SenderId, byte ReceiverId, PacketOption packetOption) routingHeader, + (byte SenderId, byte ReceiverId, PacketOption PacketOption) routingHeader, ref SpanBuffer reader, DeliveryMethod deliveryMethod) { routingHeader.SenderId = sender.ConnectionId; var writer = new SpanBuffer(stackalloc byte[412]); if (routingHeader.ReceiverId == AllConnectionIds) { - writer.WriteRoutingHeader(routingHeader.SenderId, routingHeader.ReceiverId); + writer.WriteRoutingHeader(routingHeader.SenderId, routingHeader.ReceiverId, routingHeader.PacketOption); writer.WriteBytes(reader.RemainingData); _logger.Verbose( $"Routing packet from {routingHeader.SenderId} -> all players " + - $"PacketOption='{routingHeader.packetOption}' " + + $"PacketOption='{routingHeader.PacketOption}' " + $"(Secret='{sender.Secret}', DeliveryMethod={deliveryMethod})." ); foreach (var player in _playerRegistry.Players) @@ -206,7 +206,7 @@ private void RoutePacket(IPlayer sender, } else { - writer.WriteRoutingHeader(routingHeader.SenderId, LocalConnectionId); + writer.WriteRoutingHeader(routingHeader.SenderId, LocalConnectionId, routingHeader.PacketOption); writer.WriteBytes(reader.RemainingData); if (!_playerRegistry.TryGetPlayer(routingHeader.ReceiverId, out var receiver)) @@ -219,7 +219,7 @@ private void RoutePacket(IPlayer sender, } _logger.Verbose( $"Routing packet from {routingHeader.SenderId} -> {routingHeader.ReceiverId} " + - $"PacketOption='{routingHeader.packetOption}' " + + $"PacketOption='{routingHeader.PacketOption}' " + $"(Secret='{sender.Secret}', DeliveryMethod={deliveryMethod})." ); _packetDispatcher.Send(receiver.Endpoint, writer.Data, deliveryMethod); From 7d8ac0580f0b833ba428c3263f6a44ca54dfb8f4 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Mon, 18 Dec 2023 14:17:45 +0100 Subject: [PATCH 058/120] Add necessary extension methods --- .../Extensions/BinaryReadWriteExtension.cs | 23 ++++++++ .../Extensions/SpanBufferReaderExtensions.cs | 52 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 BeatTogether.DedicatedServer.Messaging/Extensions/BinaryReadWriteExtension.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferReaderExtensions.cs diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/BinaryReadWriteExtension.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/BinaryReadWriteExtension.cs new file mode 100644 index 00000000..449b7af8 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Extensions/BinaryReadWriteExtension.cs @@ -0,0 +1,23 @@ +using System.IO; +using BeatTogether.DedicatedServer.Messaging.Models; + +namespace BeatTogether.DedicatedServer.Messaging.Extensions +{ + public static class BinaryReadWriteExtension + { + // Token: 0x06000069 RID: 105 RVA: 0x00002ED8 File Offset: 0x000010D8 + public static void Write(this BinaryWriter binaryWriter, Color color) + { + binaryWriter.Write(color.r); + binaryWriter.Write(color.g); + binaryWriter.Write(color.b); + binaryWriter.Write(color.a); + } + + // Token: 0x0600006A RID: 106 RVA: 0x00002F0A File Offset: 0x0000110A + public static Color ReadColor(this BinaryReader binaryReader) + { + return new Color(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferReaderExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferReaderExtensions.cs new file mode 100644 index 00000000..fa204c01 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferReaderExtensions.cs @@ -0,0 +1,52 @@ +using BeatTogether.DedicatedServer.Messaging.Models; +using Krypton.Buffers; +using System.Diagnostics.CodeAnalysis; + +namespace BeatTogether.Extensions +{ + public static class SpanBufferReaderExtensions + { + public static (byte SenderId, byte ReceiverId, byte PacketOption) ReadRoutingHeader(this ref SpanBufferReader reader) => + (reader.ReadUInt8(), reader.ReadUInt8(), reader.ReadUInt8()); + + public static bool TryReadRoutingHeader(this ref SpanBufferReader reader, [MaybeNullWhen(false)] out (byte SenderId, byte ReceiverId, byte PacketOption) routingHeader) + { + if (reader.RemainingSize < 2) + { + routingHeader = default; + return false; + } + + routingHeader = (reader.ReadUInt8(), reader.ReadUInt8(), reader.ReadUInt8()); + return true; + } + + public static void ReadBytesArray(this ref SpanBufferReader reader, ref byte[]? array) + { + int length = (int)reader.ReadVarUInt(); + array = reader.ReadBytes(length).ToArray(); + } + + public static void ReadColor(this ref SpanBufferReader reader, ref Color color) + { + color.r = reader.ReadFloat32(); + color.g = reader.ReadFloat32(); + color.b = reader.ReadFloat32(); + color.a = reader.ReadFloat32(); + } + + public static void ReadColorNoAlpha(this ref SpanBufferReader reader, ref ColorNoAlpha color) + { + color.r = reader.ReadFloat32(); + color.g = reader.ReadFloat32(); + color.b = reader.ReadFloat32(); + } + + public static void ReadBeatmapIdentifier(this ref SpanBufferReader reader, ref BeatmapIdentifier beatmapIdentifier) + { + beatmapIdentifier.LevelId = reader.ReadString(); + beatmapIdentifier.Characteristic = reader.ReadString(); + beatmapIdentifier.Difficulty = (BeatmapDifficulty)reader.ReadVarUInt(); + } + } +} From 65aa3fba352961897a89c3a8cc9ce358c6a850f1 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Mon, 18 Dec 2023 14:20:44 +0100 Subject: [PATCH 059/120] BitMask128 add constructor and SetBits function --- .../Models/BitMask128.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs index 118b1713..bef731c6 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs @@ -10,6 +10,14 @@ public class BitMask128 : INetSerializable public ulong Top { get; set; } public ulong Bottom { get; set; } + public BitMask128(ulong top, ulong bottom) + { + Top = top; + Bottom = bottom; + } + + public BitMask128() { } + public bool Contains(string value, int hashCount = 3, int hashBits = 8) { uint hash = MurmurHash2(value); @@ -31,7 +39,14 @@ public ulong GetBits(int offset, int count) return (ShiftRight(Top, num2) | ShiftRight(Bottom, offset)) & num; } - public void ReadFrom(ref SpanBuffer reader) + public BitMask128 SetBits(int offset, ulong bits) + { + ulong d = Top; + int num = offset - 64; + return new BitMask128(d | ShiftLeft(bits, num), Bottom | ShiftLeft(bits, offset)); + } + + public void ReadFrom(ref SpanBuffer reader) { Top = reader.ReadUInt64(); Bottom = reader.ReadUInt64(); From 022375753497bc5f5db09c7be938a1a475474077 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Mon, 18 Dec 2023 14:21:25 +0100 Subject: [PATCH 060/120] Add Color class --- .../Models/Color.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 BeatTogether.DedicatedServer.Messaging/Models/Color.cs diff --git a/BeatTogether.DedicatedServer.Messaging/Models/Color.cs b/BeatTogether.DedicatedServer.Messaging/Models/Color.cs new file mode 100644 index 00000000..fa5e4d52 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Models/Color.cs @@ -0,0 +1,39 @@ +using BeatTogether.LiteNetLib.Abstractions; +using Krypton.Buffers; + +namespace BeatTogether.DedicatedServer.Messaging.Models +{ + public sealed class Color : INetSerializable + { + public float r { get; set; } + public float g { get; set; } + public float b { get; set; } + public float a { get; set; } + + public Color(float r, float g, float b, float a) + { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + + public Color() { } + + public void ReadFrom(ref SpanBufferReader reader) + { + r = reader.ReadFloat32(); + g = reader.ReadFloat32(); + b = reader.ReadFloat32(); + a = reader.ReadFloat32(); + } + + public void WriteTo(ref SpanBufferWriter writer) + { + writer.WriteFloat32(r); + writer.WriteFloat32(g); + writer.WriteFloat32(b); + writer.WriteFloat32(a); + } + } +} From 7617c2738ca020381d9f4b6e37d963f02bc04aad Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Mon, 18 Dec 2023 18:32:15 +0100 Subject: [PATCH 061/120] Add Color class with float rgba values --- BeatTogether.DedicatedServer.Messaging/Models/Color.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BeatTogether.DedicatedServer.Messaging/Models/Color.cs b/BeatTogether.DedicatedServer.Messaging/Models/Color.cs index fa5e4d52..e0337d71 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/Color.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/Color.cs @@ -1,5 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; -using Krypton.Buffers; +using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { @@ -20,7 +20,7 @@ public Color(float r, float g, float b, float a) public Color() { } - public void ReadFrom(ref SpanBufferReader reader) + public void ReadFrom(ref SpanBuffer reader) { r = reader.ReadFloat32(); g = reader.ReadFloat32(); @@ -28,7 +28,7 @@ public void ReadFrom(ref SpanBufferReader reader) a = reader.ReadFloat32(); } - public void WriteTo(ref SpanBufferWriter writer) + public void WriteTo(ref SpanBuffer writer) { writer.WriteFloat32(r); writer.WriteFloat32(g); From 394cdbce02c7d0d5fa2916926a3bd4279ca91066 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Mon, 18 Dec 2023 18:33:32 +0100 Subject: [PATCH 062/120] Add new Avatar classes --- ...atarDataMultiplayerAvatarsDataConverter.cs | 55 +++++++++ .../Models/AvatarData.cs | 113 +++++++++++------- .../Models/MultiplayerAvatarsData.cs | 99 +++++++++++++++ .../Structs/AvatarSystemIdentifier.cs | 65 ++++++++++ .../Structs/MultiplayerAvatarData.cs | 22 ++++ 5 files changed, 309 insertions(+), 45 deletions(-) create mode 100644 BeatTogether.DedicatedServer.Messaging/Converter/AvatarDataMultiplayerAvatarsDataConverter.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Structs/AvatarSystemIdentifier.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Structs/MultiplayerAvatarData.cs diff --git a/BeatTogether.DedicatedServer.Messaging/Converter/AvatarDataMultiplayerAvatarsDataConverter.cs b/BeatTogether.DedicatedServer.Messaging/Converter/AvatarDataMultiplayerAvatarsDataConverter.cs new file mode 100644 index 00000000..9a52d13a --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Converter/AvatarDataMultiplayerAvatarsDataConverter.cs @@ -0,0 +1,55 @@ +using BeatTogether.DedicatedServer.Messaging.Extensions; +using BeatTogether.DedicatedServer.Messaging.Models; +using BeatTogether.DedicatedServer.Messaging.Structs; +using System.IO; + +namespace BeatTogether.DedicatedServer.Messaging.Converter +{ + public static class AvatarDataMultiplayerAvatarsDataConverter + { + public static AvatarSystemIdentifier BaseGameAvatarSystemTypeIdentifier = new AvatarSystemIdentifier("BeatAvatarSystem"); + public static MultiplayerAvatarData CreateMultiplayerAvatarsData(this AvatarData avatarData) + { + MultiplayerAvatarData multiplayerAvatarData; + using (MemoryStream memoryStream = new MemoryStream()) + { + using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream)) + { + binaryWriter.Write(avatarData.HeadTopId); + binaryWriter.Write(avatarData.HeadTopPrimaryColor); + binaryWriter.Write(avatarData.HeadTopSecondaryColor); + binaryWriter.Write(avatarData.GlassesId); + binaryWriter.Write(avatarData.GlassesColor); + binaryWriter.Write(avatarData.FacialHairId); + binaryWriter.Write(avatarData.FacialHairColor); + binaryWriter.Write(avatarData.HandsId); + binaryWriter.Write(avatarData.HandsColor); + binaryWriter.Write(avatarData.ClothesId); + binaryWriter.Write(avatarData.ClothesPrimaryColor); + binaryWriter.Write(avatarData.ClothesSecondaryColor); + binaryWriter.Write(avatarData.ClothesDetailColor); + binaryWriter.Write(avatarData.SkinColorId); + binaryWriter.Write(avatarData.EyesId); + binaryWriter.Write(avatarData.MouthId); + byte[] array = memoryStream.ToArray(); + multiplayerAvatarData = new MultiplayerAvatarData(BaseGameAvatarSystemTypeIdentifier.AvatarTypeIdentifierHash, array); + } + } + return multiplayerAvatarData; + } + + public static AvatarData CreateAvatarData(this MultiplayerAvatarData multiplayerAvatarsData) + { + AvatarData avatarData; + using (MemoryStream memoryStream = new MemoryStream(multiplayerAvatarsData.Data!)) + { + memoryStream.Position = 0L; + using (BinaryReader binaryReader = new BinaryReader(memoryStream)) + { + avatarData = new AvatarData(binaryReader.ReadString(), binaryReader.ReadColor(), binaryReader.ReadColor(), binaryReader.ReadString(), binaryReader.ReadColor(), binaryReader.ReadString(), binaryReader.ReadColor(), binaryReader.ReadString(), binaryReader.ReadColor(), binaryReader.ReadString(), binaryReader.ReadColor(), binaryReader.ReadColor(), binaryReader.ReadColor(), binaryReader.ReadString(), binaryReader.ReadString(), binaryReader.ReadString()); + } + } + return avatarData; + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs b/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs index 51afb59e..637e73a3 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs @@ -1,70 +1,93 @@ using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; using BeatTogether.LiteNetLib.Util; -using Krypton.Buffers; -using System.Drawing; +using System; namespace BeatTogether.DedicatedServer.Messaging.Models { public sealed class AvatarData : INetSerializable { public string HeadTopId { get; set; } = "BedHead"; - public Color HeadTopPrimaryColor { get; set; } - public Color HeadTopSecondaryColor { get; set; } + public Color HeadTopPrimaryColor { get; set; } = new Color(); + public Color HeadTopSecondaryColor { get; set; } = new Color(); public string GlassesId { get; set; } = "Default"; - public Color GlassesColor { get; set; } + public Color GlassesColor { get; set; } = new Color(); public string FacialHairId { get; set; } = "None"; - public Color FacialHairColor { get; set; } + public Color FacialHairColor { get; set; } = new Color(); public string HandsId { get; set; } = "BareHands"; - public Color HandsColor { get; set; } + public Color HandsColor { get; set; } = new Color(); public string ClothesId { get; set; } = "Hoodie"; - public Color ClothesPrimaryColor { get; set; } - public Color ClothesSecondaryColor { get; set; } - public Color ClothesDetailColor { get; set; } + public Color ClothesPrimaryColor { get; set; } = new Color(); + public Color ClothesSecondaryColor { get; set; } = new Color(); + public Color ClothesDetailColor { get; set; } = new Color(); public string SkinColorId { get; set; } = "Default"; public string EyesId { get; set; } = "Eyes1"; public string MouthId { get; set; } = "Mouth8"; + public AvatarData() { } + + public AvatarData(string headTopId, Color headTopPrimaryColor, Color headTopSecondaryColor, string glassesId, Color glassesColor, string facialHairId, Color facialHairColor, string handsId, Color handsColor, string clothesId, Color clothesPrimaryColor, Color clothesSecondaryColor, Color clothesDetailColor, string skinColorId, string eyesId, string mouthId) + { + HeadTopId = headTopId; + HeadTopPrimaryColor = headTopPrimaryColor; + HeadTopSecondaryColor = headTopSecondaryColor; + GlassesId = glassesId; + GlassesColor = glassesColor; + FacialHairId = facialHairId; + FacialHairColor = facialHairColor; + HandsId = handsId; + HandsColor = handsColor; + ClothesId = clothesId; + ClothesPrimaryColor = clothesPrimaryColor; + ClothesSecondaryColor = clothesSecondaryColor; + ClothesDetailColor = clothesDetailColor; + SkinColorId = skinColorId; + EyesId = eyesId; + MouthId = mouthId; + } + + //TODO: Move class as it's no longer a INetSerializable + [Obsolete("This method is obsolete and will be removed soon. Use MultiplayerAvatarsData.ReadFrom instead.")] public void ReadFrom(ref SpanBuffer reader) { - HeadTopId = reader.ReadString(); - HeadTopPrimaryColor = reader.ReadColor(); - HandsColor = reader.ReadColor(); - ClothesId = reader.ReadString(); - ClothesPrimaryColor = reader.ReadColor(); - ClothesSecondaryColor = reader.ReadColor(); - ClothesDetailColor = reader.ReadColor(); - reader.SkipBytes(8); - EyesId = reader.ReadString(); - MouthId = reader.ReadString(); - GlassesColor = reader.ReadColor(); - FacialHairColor = reader.ReadColor(); - HeadTopSecondaryColor = reader.ReadColor(); - GlassesId = reader.ReadString(); - FacialHairId = reader.ReadString(); - HandsId = reader.ReadString(); - SkinColorId = GlassesId; // Don't ask + //HeadTopId = reader.ReadString(); + //HeadTopPrimaryColor = reader.ReadColor(); + //HandsColor = reader.ReadColor(); + //ClothesId = reader.ReadString(); + //ClothesPrimaryColor = reader.ReadColor(); + //ClothesSecondaryColor = reader.ReadColor(); + //ClothesDetailColor = reader.ReadColor(); + //reader.SkipBytes(8); + //EyesId = reader.ReadString(); + //MouthId = reader.ReadString(); + //GlassesColor = reader.ReadColor(); + //FacialHairColor = reader.ReadColor(); + //HeadTopSecondaryColor = reader.ReadColor(); + //GlassesId = reader.ReadString(); + //FacialHairId = reader.ReadString(); + //HandsId = reader.ReadString(); + //SkinColorId = GlassesId; // Don't ask } + [Obsolete("This method is obsolete and will be removed soon. Use MultiplayerAvatarsData.WriteTo instead.")] public void WriteTo(ref SpanBuffer writer) { - writer.WriteString(HeadTopId); - writer.WriteColor(HeadTopPrimaryColor); - writer.WriteColor(HandsColor); - writer.WriteString(ClothesId); - writer.WriteColor(ClothesPrimaryColor); - writer.WriteColor(ClothesSecondaryColor); - writer.WriteColor(ClothesDetailColor); - writer.WriteColor(new Color()); - writer.WriteColor(new Color()); - writer.WriteString(EyesId); - writer.WriteString(MouthId); - writer.WriteColor(GlassesColor); - writer.WriteColor(FacialHairColor); - writer.WriteColor(HeadTopSecondaryColor); - writer.WriteString(GlassesId); - writer.WriteString(FacialHairId); - writer.WriteString(HandsId); + //writer.WriteString(HeadTopId); + //writer.WriteColor(HeadTopPrimaryColor); + //writer.WriteColor(HandsColor); + //writer.WriteString(ClothesId); + //writer.WriteColor(ClothesPrimaryColor); + //writer.WriteColor(ClothesSecondaryColor); + //writer.WriteColor(ClothesDetailColor); + //writer.WriteColor(new Color()); + //writer.WriteColor(new Color()); + //writer.WriteString(EyesId); + //writer.WriteString(MouthId); + //writer.WriteColor(GlassesColor); + //writer.WriteColor(FacialHairColor); + //writer.WriteColor(HeadTopSecondaryColor); + //writer.WriteString(GlassesId); + //writer.WriteString(FacialHairId); + //writer.WriteString(HandsId); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs new file mode 100644 index 00000000..82bad6d6 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs @@ -0,0 +1,99 @@ +using BeatTogether.DedicatedServer.Messaging.Converter; +using BeatTogether.DedicatedServer.Messaging.Structs; +using BeatTogether.Extensions; +using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Util; +using System.Collections.Generic; +using System.Linq; + +namespace BeatTogether.DedicatedServer.Messaging.Models +{ + public sealed class MultiplayerAvatarsData : INetSerializable + { + public List? AvatarsData { get; set; } + public BitMask128 SupportedAvatarTypeIdHashesBloomFilter { get; set; } = AddBloomFilterEntryHash(new BitMask128(), AvatarDataMultiplayerAvatarsDataConverter.BaseGameAvatarSystemTypeIdentifier.AvatarTypeIdentifierHash, 3, 8); + + public MultiplayerAvatarsData() + { + AvatarData defaultAvatar = new AvatarData(); + AvatarsData = new List + { + defaultAvatar.CreateMultiplayerAvatarsData() + }; + } + + public MultiplayerAvatarsData(List multiplayerAvatarsData, IEnumerable supportedAvatarTypeIdHashes) + { + AvatarsData = multiplayerAvatarsData; + SupportedAvatarTypeIdHashesBloomFilter = ToBloomFilter(supportedAvatarTypeIdHashes, 3, 8); + } + + // Token: 0x060000A2 RID: 162 RVA: 0x00003D91 File Offset: 0x00001F91 + public MultiplayerAvatarsData(List multiplayerAvatarsData, BitMask128 supportedAvatarTypeIdHashesBloomFilter) + { + AvatarsData = multiplayerAvatarsData; + SupportedAvatarTypeIdHashesBloomFilter = supportedAvatarTypeIdHashesBloomFilter; + } + + public void WriteTo(ref SpanBuffer writer) + { + WriteToAvatarsData(ref writer); + SupportedAvatarTypeIdHashesBloomFilter.WriteTo(ref writer); + } + public void WriteToAvatarsData(ref SpanBuffer writer) + { + if (AvatarsData == null) + { + writer.WriteInt32(0); + return; + } + writer.WriteInt32(AvatarsData.Count); + foreach (MultiplayerAvatarData multiplayerAvatarData in AvatarsData) + { + writer.WriteVarUInt(multiplayerAvatarData.AvatarTypeIdentifierHash); + ByteArray byteArray = new ByteArray(); // TODO: Check if ByteArray is the correct equivalent to PutBytes() + byteArray.WriteTo(ref writer); + } + } + + public void ReadFrom(ref SpanBuffer reader) + { + AvatarsData = ReadFromAvatarsData(ref reader); + SupportedAvatarTypeIdHashesBloomFilter.ReadFrom(ref reader); + } + public static MultiplayerAvatarsData Deserialize(ref SpanBuffer reader) + { + List list = MultiplayerAvatarsData.ReadFromAvatarsData(ref reader); + BitMask128 bitMask = new BitMask128(); + bitMask.ReadFrom(ref reader); + return new MultiplayerAvatarsData(list, bitMask); + } + public static List ReadFromAvatarsData(ref SpanBuffer reader) + { + int @int = reader.ReadInt32(); + List list = new List(@int); + for (int i = 0; i < @int; i++) + { + uint @uint = reader.ReadUInt32(); + ByteArray byteArray = new ByteArray(); // TODO: Check if ByteArray is the correct equivalent to GetBytes() + byteArray.ReadFrom(ref reader); + list.Add(new MultiplayerAvatarData(@uint, byteArray.Data)); + } + return list; + } + public static BitMask128 ToBloomFilter(IEnumerable hashes, int hashCount = 3, int hashBits = 8) + { + return hashes.Aggregate(new BitMask128(), (BitMask128 bloomFilter, uint hash) => AddBloomFilterEntryHash(bloomFilter, hash, hashCount, hashBits)); + } + + public static BitMask128 AddBloomFilterEntryHash(BitMask128 bitMask, uint hash, int hashCount = 3, int hashBits = 8) + { + for (int i = 0; i < hashCount; i++) + { + bitMask = bitMask.SetBits((int)((ulong)hash % (ulong)((long)bitMask.BitCount)), 1UL); + hash >>= hashBits; + } + return bitMask; + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Structs/AvatarSystemIdentifier.cs b/BeatTogether.DedicatedServer.Messaging/Structs/AvatarSystemIdentifier.cs new file mode 100644 index 00000000..f8c48cad --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Structs/AvatarSystemIdentifier.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BeatTogether.DedicatedServer.Messaging.Structs +{ + public struct AvatarSystemIdentifier + { + public string AvatarSystemTypeIdentifier { get; set; } + public uint AvatarTypeIdentifierHash { get; set; } + + public AvatarSystemIdentifier(string avatarSystemTypeIdentifier) + { + AvatarSystemTypeIdentifier = avatarSystemTypeIdentifier; + AvatarTypeIdentifierHash = AvatarSystemIdentifier.HashAvatarSystemTypeMultiplier(AvatarSystemTypeIdentifier); + } + + public static uint HashAvatarSystemTypeMultiplier(string avatarSystemTypeIdentifier) + { + return MurmurHash2(avatarSystemTypeIdentifier); + } + + public static uint MurmurHash2(string key) + { + uint num = (uint)key.Length; + uint num2 = 33U ^ num; + int num3 = 0; + while (num >= 4U) + { + uint num4 = (uint)(((uint)key[num3 + 3] << 24) | ((uint)key[num3 + 2] << 16) | ((uint)key[num3 + 1] << 8) | key[num3]); + num4 *= 1540483477U; + num4 ^= num4 >> 24; + num4 *= 1540483477U; + num2 *= 1540483477U; + num2 ^= num4; + num3 += 4; + num -= 4U; + } + switch (num) + { + case 1U: + num2 ^= (uint)key[num3]; + num2 *= 1540483477U; + break; + case 2U: + num2 ^= (uint)((uint)key[num3 + 1] << 8); + num2 ^= (uint)key[num3]; + num2 *= 1540483477U; + break; + case 3U: + num2 ^= (uint)((uint)key[num3 + 2] << 16); + num2 ^= (uint)((uint)key[num3 + 1] << 8); + num2 ^= (uint)key[num3]; + num2 *= 1540483477U; + break; + } + num2 ^= num2 >> 13; + num2 *= 1540483477U; + return num2 ^ (num2 >> 15); + } + } + +} diff --git a/BeatTogether.DedicatedServer.Messaging/Structs/MultiplayerAvatarData.cs b/BeatTogether.DedicatedServer.Messaging/Structs/MultiplayerAvatarData.cs new file mode 100644 index 00000000..49fc3a2c --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Structs/MultiplayerAvatarData.cs @@ -0,0 +1,22 @@ +using BeatTogether.DedicatedServer.Messaging.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BeatTogether.DedicatedServer.Messaging.Structs +{ + public readonly struct MultiplayerAvatarData + { + public byte[]? Data { get; } + public uint AvatarTypeIdentifierHash { get; } + + public MultiplayerAvatarData(uint avatarTypeIdentifierHash, byte[]? data) + { + AvatarTypeIdentifierHash = avatarTypeIdentifierHash; + Data = data; + } + + } +} From b8e02286f898bd47d97fe862cf8e71e3bf6cbd0b Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Mon, 18 Dec 2023 18:33:50 +0100 Subject: [PATCH 063/120] Update existing packets to use new avatar classes --- BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs | 2 +- .../Packets/PlayerIdentityPacket.cs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index 72088927..477f0ff5 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -32,7 +32,7 @@ public interface IPlayer RollingAverage Latency { get; } long SyncTime { get; } int SortIndex { get; set; } - AvatarData Avatar { get; set; } + MultiplayerAvatarsData Avatar { get; set; } bool IsReady { get; set; } BeatmapIdentifier? BeatmapIdentifier { get; set; } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs index 575df89a..eaa22709 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs @@ -1,13 +1,12 @@ using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Util; - namespace BeatTogether.DedicatedServer.Messaging.Packets { public sealed class PlayerIdentityPacket : INetSerializable { public PlayerStateHash PlayerState { get; set; } = new(); - public AvatarData PlayerAvatar { get; set; } = new(); + public MultiplayerAvatarsData PlayerAvatar { get; set; } = new(); public ByteArray Random { get; set; } = new(); public ByteArray PublicEncryptionKey { get; set; } = new(); From b124e239a03c78b0fc0af50667c08c9ca339fc61 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Tue, 19 Dec 2023 20:41:10 +0100 Subject: [PATCH 064/120] Add Extension methods for ByteArrays (not the ByteArray Packet) --- .../Extensions/SpanBufferExtensions.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs index 429cbe62..480538ae 100644 --- a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs +++ b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs @@ -110,6 +110,12 @@ public static ReadOnlySpan ReadVarBytes(this ref SpanBuffer bufferReader) return bufferReader.ReadBytes((int)count); } + public static ReadOnlySpan ReadByteArray(this ref SpanBuffer bufferReader) + { + ushort num = bufferReader.ReadUInt16(); + return bufferReader.ReadBytes(num); + } + public static string ReadString(this ref SpanBuffer bufferReader, int maxLength = 65535) { int num = bufferReader.ReadInt32(); @@ -169,6 +175,16 @@ public static void WriteVarBytes(this ref SpanBuffer bufferWriter, ReadOnlySpan< bufferWriter.WriteBytes(bytes); } + public static void WriteByteArray(this ref SpanBuffer bufferWriter, byte[]? arr = null) + { + ushort num = (arr == null) ? (ushort)0 : ((ushort)arr.Length); + bufferWriter.WriteUInt16(num); + if (arr != null) + { + bufferWriter.WriteBytes(arr); + } + } + public static void WriteString(this ref SpanBuffer bufferWriter, string value) { bufferWriter.WriteInt32(Encoding.UTF8.GetByteCount(value)); From 8a2accbd7315c4146a9e3346bf6fdd33760c2679 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Tue, 19 Dec 2023 20:41:58 +0100 Subject: [PATCH 065/120] Change PlayerAvatarPacket to use MultiplayerAvatarsData --- .../Packets/PlayerAvatarPacket.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerAvatarPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerAvatarPacket.cs index b4fe697a..5218b1ac 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerAvatarPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerAvatarPacket.cs @@ -6,7 +6,7 @@ namespace BeatTogether.DedicatedServer.Messaging.Packets { public sealed class PlayerAvatarPacket : INetSerializable { - public AvatarData PlayerAvatar { get; set; } = new(); + public MultiplayerAvatarsData PlayerAvatar { get; set; } = new(); public void ReadFrom(ref SpanBuffer reader) { From 43f87f313c7d787118ffdf248856e3811c90eb6c Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Tue, 19 Dec 2023 20:43:40 +0100 Subject: [PATCH 066/120] Fix use proper ByteArray for avatars --- .../Models/MultiplayerAvatarsData.cs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs index 82bad6d6..f0d57aa3 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs @@ -3,6 +3,7 @@ using BeatTogether.Extensions; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Util; +using System; using System.Collections.Generic; using System.Linq; @@ -51,8 +52,7 @@ public void WriteToAvatarsData(ref SpanBuffer writer) foreach (MultiplayerAvatarData multiplayerAvatarData in AvatarsData) { writer.WriteVarUInt(multiplayerAvatarData.AvatarTypeIdentifierHash); - ByteArray byteArray = new ByteArray(); // TODO: Check if ByteArray is the correct equivalent to PutBytes() - byteArray.WriteTo(ref writer); + writer.WriteByteArray(multiplayerAvatarData.Data); } } @@ -61,13 +61,6 @@ public void ReadFrom(ref SpanBuffer reader) AvatarsData = ReadFromAvatarsData(ref reader); SupportedAvatarTypeIdHashesBloomFilter.ReadFrom(ref reader); } - public static MultiplayerAvatarsData Deserialize(ref SpanBuffer reader) - { - List list = MultiplayerAvatarsData.ReadFromAvatarsData(ref reader); - BitMask128 bitMask = new BitMask128(); - bitMask.ReadFrom(ref reader); - return new MultiplayerAvatarsData(list, bitMask); - } public static List ReadFromAvatarsData(ref SpanBuffer reader) { int @int = reader.ReadInt32(); @@ -75,9 +68,8 @@ public static List ReadFromAvatarsData(ref SpanBuffer rea for (int i = 0; i < @int; i++) { uint @uint = reader.ReadUInt32(); - ByteArray byteArray = new ByteArray(); // TODO: Check if ByteArray is the correct equivalent to GetBytes() - byteArray.ReadFrom(ref reader); - list.Add(new MultiplayerAvatarData(@uint, byteArray.Data)); + ReadOnlySpan byteArray = reader.ReadByteArray(); + list.Add(new MultiplayerAvatarData(@uint, byteArray.ToArray())); } return list; } From ce276147f40aad80cdb0180bc78735402e5e80ff Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Tue, 19 Dec 2023 22:05:27 +0100 Subject: [PATCH 067/120] Update SongStartTimePacket also long now from float --- .../Managers/Abstractions/IGameplayManager.cs | 2 +- .../Managers/GameplayManager.cs | 12 ++++++++---- .../MenuRpc/SetStartGameTimePacket.cs | 7 ++++--- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/IGameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/IGameplayManager.cs index 3c2893ff..9b0bb734 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/IGameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/IGameplayManager.cs @@ -12,7 +12,7 @@ public interface IGameplayManager GameplayManagerState State { get; } BeatmapIdentifier? CurrentBeatmap { get; } GameplayModifiers CurrentModifiers { get; } - public float _songStartTime { get; } + public long _songStartTime { get; } void HandlePlayerLeaveGameplay(IPlayer player); void HandleGameSceneLoaded(IPlayer player, SetGameplaySceneReadyPacket packet); diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs index b4353a8a..3561048f 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs @@ -5,6 +5,7 @@ using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; using BeatTogether.LiteNetLib.Enums; +using Serilog; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -28,11 +29,11 @@ public sealed class GameplayManager : IGameplayManager, IDisposable public BeatmapIdentifier? CurrentBeatmap { get; private set; } = null; public GameplayModifiers CurrentModifiers { get; private set; } = new(); - private const float SongStartDelay = 0.5f; + private const long SongStartDelay = 100; private const float SceneLoadTimeLimit = 15.0f; private const float SongLoadTimeLimit = 15.0f; - public float _songStartTime { get; private set; } + public long _songStartTime { get; private set; } List PlayersAtStart = new(); private CancellationTokenSource? _requestReturnToMenuCts; @@ -56,6 +57,8 @@ public sealed class GameplayManager : IGameplayManager, IDisposable private CancellationTokenSource? songReadyCts = null; private CancellationTokenSource? linkedSongReadyCts = null; + private readonly ILogger _logger = Log.ForContext(); + public GameplayManager( IDedicatedInstance instance, IPlayerRegistry playerRegistry, @@ -150,7 +153,7 @@ public async void StartSong(CancellationToken cancellationToken) songReadyCts.CancelAfter((int)((SongLoadTimeLimit + (PlayersAtStart.Count*0.3f)) * 1000)); await Task.WhenAll(_songReadyTcs.Values.Select(p => p.Task)); - float StartDelay = 0; + long StartDelay = 0; foreach (var UserId in PlayersAtStart) { if (_playerRegistry.TryGetPlayer(UserId, out var p)) @@ -162,7 +165,8 @@ public async void StartSong(CancellationToken cancellationToken) } // Start song and wait for finish - _songStartTime = _instance.RunTime + SongStartDelay + (StartDelay * 2f); + _songStartTime = (_instance.RunTime + SongStartDelay + (StartDelay * 2))*2; + _logger.Verbose($"Song start time: {_songStartTime}"); State = GameplayManagerState.Gameplay; diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs index 753b9f6c..f4f52995 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs @@ -1,23 +1,24 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { public sealed class SetStartGameTimePacket : BaseRpcWithValuesPacket { - public float StartTime { get; set; } + public long StartTime { get; set; } public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) - StartTime = reader.ReadFloat32(); + StartTime = (long)reader.ReadVarULong(); } public override void WriteTo(ref SpanBuffer writer) { base.WriteTo(ref writer); - writer.WriteFloat32(StartTime); + writer.WriteVarULong((ulong)StartTime); } } } From c294ca9cadae7a1ebe375d31fe4b49065a3059c0 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Tue, 19 Dec 2023 22:06:35 +0100 Subject: [PATCH 068/120] Player update Avatar property to MultiplayerAvatarsData --- BeatTogether.DedicatedServer.Kernel/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index a2cdfa51..05999ad3 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -35,7 +35,7 @@ public sealed class Player : IPlayer public string ClientVersion { get; set; } = "Pre-1.29"; public Platform Platform { get; set; } = Platform.Test; //Unknown public string PlatformUserId { get; set; } = ""; - public AvatarData Avatar { get; set; } = new(); + public MultiplayerAvatarsData Avatar { get; set; } = new(); public bool IsReady { get; set; } public bool InLobby { get; set; } From 8990d46910c912b4ad1a56e207339bc03a55a17e Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Tue, 19 Dec 2023 22:36:53 +0100 Subject: [PATCH 069/120] Update internal values to long from float --- .../Configuration/InstanceConfiguration.cs | 4 ++-- .../Abstractions/IInstanceFactory.cs | 6 +++--- .../InstanceFactory.cs | 14 +++++++------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs index 1f47fce1..8dd9ed63 100644 --- a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs +++ b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs @@ -35,8 +35,8 @@ public sealed class InstanceConfiguration public sealed class CountdownConfig { - public float CountdownTimePlayersReady { get; set; } = 30.0f; - public float BeatMapStartCountdownTime { get; set; } = 5.0f; + public long CountdownTimePlayersReady { get; set; } = 30; + public long BeatMapStartCountdownTime { get; set; } = 5; public float ResultsScreenTime { get; set; } = 20.0f; } } diff --git a/BeatTogether.DedicatedServer.Node/Abstractions/IInstanceFactory.cs b/BeatTogether.DedicatedServer.Node/Abstractions/IInstanceFactory.cs index c6345130..65845bcd 100644 --- a/BeatTogether.DedicatedServer.Node/Abstractions/IInstanceFactory.cs +++ b/BeatTogether.DedicatedServer.Node/Abstractions/IInstanceFactory.cs @@ -12,9 +12,9 @@ public interface IInstanceFactory bool permanentManager = false,//If a user links there account to discord and uses a bot to make a lobby, then can enter there userId float instanceTimeout = 0f, string ServerName = "", - float resultScreenTime = 20.0f, - float BeatmapStartTime = 5.0f, - float PlayersReadyCountdownTime = 0f, + long resultScreenTime = 20, + long BeatmapStartTime = 5, + long PlayersReadyCountdownTime = 0, bool AllowPerPlayerModifiers = false, bool AllowPerPlayerDifficulties = false, bool AllowChroma = true, diff --git a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs index 45ed2245..321121b2 100644 --- a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs +++ b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs @@ -31,9 +31,9 @@ public InstanceFactory( bool permanentManager, float instanceTimeout, string ServerName, - float resultScreenTime, - float BeatmapStartTime, - float PlayersReadyCountdownTime, + long resultScreenTime, + long BeatmapStartTime, + long PlayersReadyCountdownTime, bool AllowPerPlayerModifiers, bool AllowPerPlayerDifficulties, bool AllowChroma, @@ -62,8 +62,8 @@ bool AllowNE instanceConfig.GameplayServerControlSettings = (GameplayServerControlSettings)config.GameplayServerControlSettings; instanceConfig.DestroyInstanceTimeout = instanceTimeout; instanceConfig.ServerName = ServerName; - instanceConfig.CountdownConfig.BeatMapStartCountdownTime = Math.Max(BeatmapStartTime,0f); - instanceConfig.CountdownConfig.ResultsScreenTime = Math.Max(resultScreenTime,0f); + instanceConfig.CountdownConfig.BeatMapStartCountdownTime = Math.Max(BeatmapStartTime,0); + instanceConfig.CountdownConfig.ResultsScreenTime = Math.Max(resultScreenTime,0); instanceConfig.AllowChroma = AllowChroma; instanceConfig.AllowMappingExtensions = AllowME; instanceConfig.AllowNoodleExtensions = AllowNE; @@ -71,9 +71,9 @@ bool AllowNE instanceConfig.AllowPerPlayerModifiers = AllowPerPlayerModifiers; if (permanentManager) instanceConfig.SetConstantManagerFromUserId = managerId; - instanceConfig.CountdownConfig.CountdownTimePlayersReady = Math.Max(PlayersReadyCountdownTime,0f); + instanceConfig.CountdownConfig.CountdownTimePlayersReady = Math.Max(PlayersReadyCountdownTime,0); if (instanceConfig.CountdownConfig.CountdownTimePlayersReady == 0f) - instanceConfig.CountdownConfig.CountdownTimePlayersReady = instanceConfig.GameplayServerMode == GameplayServerMode.Managed ? 15.0f : 30.0f; + instanceConfig.CountdownConfig.CountdownTimePlayersReady = instanceConfig.GameplayServerMode == GameplayServerMode.Managed ? 15 : 30; var instance = scope.ServiceProvider.GetRequiredService(); if (!_instanceRegistry.AddInstance(instance)) return null; From a6dd693e6c5a97f48104cce2a3fe9a98d38e46b7 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Tue, 19 Dec 2023 22:37:59 +0100 Subject: [PATCH 070/120] Update SongStart, StartLevel and Countdown Packet to long from float --- .../GameplayRpc/SetSongStartTimePacket.cs | 7 ++++--- .../MenuRpc/SetCountdownEndTimePacket.cs | 7 ++++--- .../Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs | 7 ++++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs index ae7fae63..3c285348 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs @@ -1,23 +1,24 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { public sealed class SetSongStartTimePacket : BaseRpcWithValuesPacket { - public float StartTime { get; set; } + public long StartTime { get; set; } public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) - StartTime = reader.ReadFloat32(); + StartTime = (long)reader.ReadVarULong(); } public override void WriteTo(ref SpanBuffer writer) { base.WriteTo(ref writer); - writer.WriteFloat32(StartTime); + writer.WriteVarULong((ulong)StartTime); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs index 25612d0d..10ded87c 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs @@ -1,23 +1,24 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { public sealed class SetCountdownEndTimePacket : BaseRpcWithValuesPacket { - public float CountdownTime { get; set; } + public long CountdownTime { get; set; } public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) - CountdownTime = reader.ReadFloat32(); + CountdownTime = (long)reader.ReadVarULong(); } public override void WriteTo(ref SpanBuffer writer) { base.WriteTo(ref writer); - writer.WriteFloat32(CountdownTime); + writer.WriteVarULong((ulong)CountdownTime); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs index fb9a9a32..ed896532 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs @@ -1,5 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; +using BeatTogether.Extensions; using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc @@ -8,7 +9,7 @@ public sealed class StartLevelPacket : BaseRpcWithValuesPacket { public BeatmapIdentifier Beatmap { get; set; } = new(); public GameplayModifiers Modifiers { get; set; } = new(); - public float StartTime { get; set; } + public long StartTime { get; set; } public override void ReadFrom(ref SpanBuffer reader) { @@ -18,7 +19,7 @@ public override void ReadFrom(ref SpanBuffer reader) if (HasValue1) Modifiers.ReadFrom(ref reader); if (HasValue2) - StartTime = reader.ReadFloat32(); + StartTime = (long)reader.ReadVarULong(); } public override void WriteTo(ref SpanBuffer writer) @@ -26,7 +27,7 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); Beatmap.WriteTo(ref writer); Modifiers.WriteTo(ref writer); - writer.WriteFloat32(StartTime); + writer.WriteVarULong((ulong)StartTime); } } } From 444d1e6609dea7025d35f6f269d56319083bcbd8 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Tue, 19 Dec 2023 22:41:54 +0100 Subject: [PATCH 071/120] Update internal matchmaking request cast to long --- .../NodeService.cs | 27 +++---------------- 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/BeatTogether.DedicatedServer.Node/NodeService.cs b/BeatTogether.DedicatedServer.Node/NodeService.cs index b869a547..3bd56917 100644 --- a/BeatTogether.DedicatedServer.Node/NodeService.cs +++ b/BeatTogether.DedicatedServer.Node/NodeService.cs @@ -54,9 +54,9 @@ public async Task CreateMatchmakingServer(Creat request.PermanentManager, request.Timeout, request.ServerName, - request.resultScreenTime, - request.BeatmapStartTime, - request.PlayersReadyCountdownTime , + (long)request.resultScreenTime, + (long)request.BeatmapStartTime, + (long)request.PlayersReadyCountdownTime , request.AllowPerPlayerModifiers, request.AllowPerPlayerDifficulties, request.AllowChroma, @@ -98,27 +98,6 @@ public static Interface.Models.LevelCompletionResults LevelCompletionCast(LevelC { return new(GameplayCast(y.GameplayModifiers), y.ModifiedScore, y.MultipliedScore, (Interface.Models.Rank)y.Rank, y.FullCombo, y.LeftSaberMovementDistance, y.RightSaberMovementDistance, y.LeftHandMovementDistance, y.RightHandMovementDistance, (Interface.Models.LevelEndStateType)y.LevelEndStateType, (Interface.Models.LevelEndAction)y.LevelEndAction, y.Energy, y.GoodCutsCount, y.BadCutsCount, y.MissedCount, y.NotGoodCount, y.OkCount, y.MaxCutScore, y.TotalCutScore, y.GoodCutsCountForNotesWithFullScoreScoringType, y.AverageCenterDistanceCutScoreForNotesWithFullScoreScoringType, y.AverageCutScoreForNotesWithFullScoreScoringType, y.MaxCombo, y.EndSongTime); } - public static Interface.Models.AvatarData AvatarCast(AvatarData v) - { - return new( - v.HeadTopId, - v.HeadTopPrimaryColor, - v.HeadTopSecondaryColor, - v.GlassesId, - v.GlassesColor, - v.FacialHairId, - v.FacialHairColor, - v.HandsId, - v.HandsColor, - v.ClothesId, - v.ClothesPrimaryColor, - v.ClothesSecondaryColor, - v.ClothesDetailColor, - v.SkinColorId, - v.EyesId, - v.MouthId); - } - private void HandleConfigChangeEvent(IDedicatedInstance inst) { From 6a2c70c91658b1574abbd046d4508804d94582c2 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Tue, 19 Dec 2023 22:46:42 +0100 Subject: [PATCH 072/120] WIP: Refactor LobbyManager countdown Probably some internal logic being broken and causing the countdown to be skipped --- .../Managers/Abstractions/ILobbyManager.cs | 2 +- .../Managers/LobbyManager.cs | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs index 87882bd5..2db9c9fa 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs @@ -15,7 +15,7 @@ public interface ILobbyManager BeatmapIdentifier? SelectedBeatmap { get; } GameplayModifiers SelectedModifiers { get; } CountdownState CountDownState { get; } - float CountdownEndTime { get; } + long CountdownEndTime { get; } GameplayModifiers EmptyModifiers {get; } public bool SpectatingPlayersUpdated { get; set; } public bool ForceStartSelectedBeatmap { get; set; } diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 827b4e83..2a3e0034 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -38,7 +38,7 @@ public sealed class LobbyManager : ILobbyManager, IDisposable public BeatmapIdentifier? SelectedBeatmap { get; private set; } = null; public GameplayModifiers SelectedModifiers { get; private set; } = new(); public CountdownState CountDownState { get; private set; } = CountdownState.NotCountingDown; - public float CountdownEndTime { get; private set; } = 0; + public long CountdownEndTime { get; private set; } = 0; private BeatmapIdentifier? _lastBeatmap = null; private bool _lastSpectatorState; @@ -352,9 +352,10 @@ public BeatmapDifficulty[] GetSelectedBeatmapDifficulties() // Sets countdown and beatmap how the client would expect it to - // If you want to cancel the countdown use CancelCountdown(), Not SetCountdown as CancelCountdown() ALSO informs the clients it has been canceled, whereas SetCountdown will now - private void SetCountdown(CountdownState countdownState, float countdown = 0) + // If you want to cancel the countdown use CancelCountdown(), Not SetCountdown as CancelCountdown() ALSO informs the clients it has been canceled, whereas SetCountdown will not + private void SetCountdown(CountdownState countdownState, long countdown = 0) { + _logger.Error($"CountdownEndTime currently is '{CountdownEndTime}' countdown is set to '{countdown}' state will be set to '{countdownState}'"); CountDownState = countdownState; switch (CountDownState) { @@ -365,7 +366,7 @@ private void SetCountdown(CountdownState countdownState, float countdown = 0) break; case CountdownState.CountingDown: if (countdown == 0) - countdown = 30f; + countdown = 30*2; CountdownEndTime = _instance.RunTime + countdown; _packetDispatcher.SendToNearbyPlayers(new SetCountdownEndTimePacket { @@ -374,7 +375,7 @@ private void SetCountdown(CountdownState countdownState, float countdown = 0) break; case CountdownState.StartBeatmapCountdown: if (countdown == 0) - countdown = 5f; + countdown = 5*2; CountdownEndTime = _instance.RunTime + countdown; StartBeatmapPacket(); break; @@ -382,6 +383,7 @@ private void SetCountdown(CountdownState countdownState, float countdown = 0) StartBeatmapPacket(); break; } + _logger.Error($"CountdownEndTime final set to '{CountdownEndTime}' CountdownState '{CountDownState}' countdown is '{countdown}' RunTime is '{_instance.RunTime}'"); } //Checks the lobby settings and sends the player the correct beatmap From ab08e8350642aa76220e1cb468b0a1125ceff68b Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Wed, 20 Dec 2023 18:51:03 +0100 Subject: [PATCH 073/120] Fix Quickplay map selection was disabled --- BeatTogether.DedicatedServer.Kernel/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index 05999ad3..592ed759 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -43,7 +43,7 @@ public sealed class Player : IPlayer public GameplayModifiers Modifiers { get; set; } = new(); public PlayerStateHash State { get; set; } = new(); public bool IsServerOwner => UserId == Instance._configuration.ServerOwnerId; - public bool CanRecommendBeatmaps => Instance._configuration.GameplayServerControlSettings is not GameplayServerControlSettings.None; + public bool CanRecommendBeatmaps => true;// This check is wrong as GameplayServerControlSettings is None in Quickplay to disable Modifier selection //Instance._configuration.GameplayServerControlSettings is not GameplayServerControlSettings.None; public bool CanRecommendModifiers => Instance._configuration.GameplayServerControlSettings is GameplayServerControlSettings.AllowModifierSelection or GameplayServerControlSettings.All; public bool CanKickVote => UserId == Instance._configuration.ServerOwnerId; From 1a032a1eda34724a0f7e817e156c15c1e82c702a Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Wed, 20 Dec 2023 20:12:38 +0100 Subject: [PATCH 074/120] Fixed Rpc packets, these do not do a conversion to ulong but rather send the data as long --- .../Abstractions/BaseRpcWithValuesPacket.cs | 1 + .../MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs | 4 ++-- .../MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs | 4 ++-- .../MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs | 4 ++-- .../Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs | 4 ++-- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcWithValuesPacket.cs b/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcWithValuesPacket.cs index 3ec3364c..4aa4194a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcWithValuesPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcWithValuesPacket.cs @@ -2,6 +2,7 @@ namespace BeatTogether.DedicatedServer.Messaging.Abstractions { + // WARNING do not cast to ulong for any packets that inherit this class public abstract class BaseRpcWithValuesPacket : BaseRpcPacket { public byte HasValues { get; set; } = (1 | 2 | 4 | 8); diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs index 3c285348..a298eceb 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs @@ -12,13 +12,13 @@ public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) - StartTime = (long)reader.ReadVarULong(); + StartTime = reader.ReadVarLong(); } public override void WriteTo(ref SpanBuffer writer) { base.WriteTo(ref writer); - writer.WriteVarULong((ulong)StartTime); + writer.WriteVarLong(StartTime); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs index 10ded87c..af235b09 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs @@ -12,13 +12,13 @@ public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) - CountdownTime = (long)reader.ReadVarULong(); + CountdownTime = reader.ReadVarLong(); } public override void WriteTo(ref SpanBuffer writer) { base.WriteTo(ref writer); - writer.WriteVarULong((ulong)CountdownTime); + writer.WriteVarLong(CountdownTime); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs index f4f52995..65038454 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs @@ -12,13 +12,13 @@ public override void ReadFrom(ref SpanBuffer reader) { base.ReadFrom(ref reader); if (HasValue0) - StartTime = (long)reader.ReadVarULong(); + StartTime = reader.ReadVarLong(); } public override void WriteTo(ref SpanBuffer writer) { base.WriteTo(ref writer); - writer.WriteVarULong((ulong)StartTime); + writer.WriteVarLong(StartTime); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs index ed896532..864f91c3 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs @@ -19,7 +19,7 @@ public override void ReadFrom(ref SpanBuffer reader) if (HasValue1) Modifiers.ReadFrom(ref reader); if (HasValue2) - StartTime = (long)reader.ReadVarULong(); + StartTime = reader.ReadVarLong(); } public override void WriteTo(ref SpanBuffer writer) @@ -27,7 +27,7 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); Beatmap.WriteTo(ref writer); Modifiers.WriteTo(ref writer); - writer.WriteVarULong((ulong)StartTime); + writer.WriteVarLong(StartTime); } } } From 1392f1911fe2ee2c9be0556d1e68343862ad587c Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Wed, 20 Dec 2023 20:14:47 +0100 Subject: [PATCH 075/120] Convert values to milliseconds, tweak logging --- .../Configuration/InstanceConfiguration.cs | 6 +++--- .../Managers/GameplayManager.cs | 6 +++--- .../Managers/LobbyManager.cs | 14 ++++++++++---- .../MenuRpc/GetCountdownEndTimePacketHandler.cs | 2 +- .../InstanceFactory.cs | 6 +++--- BeatTogether.DedicatedServer.Node/NodeService.cs | 4 ++-- 6 files changed, 22 insertions(+), 16 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs index 8dd9ed63..384652f0 100644 --- a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs +++ b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs @@ -28,15 +28,15 @@ public sealed class InstanceConfiguration public bool DisableNotes { get; set; } public bool ForceEnableNotes { get; set; } = false; public bool ForceStartMode { get; set; } = false; - public float SendPlayersWithoutEntitlementToSpectateTimeout { get; set; } = 30f; + public long SendPlayersWithoutEntitlementToSpectateTimeout { get; set; } = 30000L; public int MaxLengthCommand { get; set; } = 200; public bool ApplyNoFailModifier { get; set; } = true; } public sealed class CountdownConfig { - public long CountdownTimePlayersReady { get; set; } = 30; - public long BeatMapStartCountdownTime { get; set; } = 5; + public long CountdownTimePlayersReady { get; set; } = 30000L; + public long BeatMapStartCountdownTime { get; set; } = 5000L; public float ResultsScreenTime { get; set; } = 20.0f; } } diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs index 3561048f..7d490ac9 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs @@ -29,7 +29,7 @@ public sealed class GameplayManager : IGameplayManager, IDisposable public BeatmapIdentifier? CurrentBeatmap { get; private set; } = null; public GameplayModifiers CurrentModifiers { get; private set; } = new(); - private const long SongStartDelay = 100; + private const long SongStartDelay = 500L; private const float SceneLoadTimeLimit = 15.0f; private const float SongLoadTimeLimit = 15.0f; @@ -165,8 +165,8 @@ public async void StartSong(CancellationToken cancellationToken) } // Start song and wait for finish - _songStartTime = (_instance.RunTime + SongStartDelay + (StartDelay * 2))*2; - _logger.Verbose($"Song start time: {_songStartTime}"); + _songStartTime = (_instance.RunTime + SongStartDelay + (StartDelay * 2)); + _logger.Verbose($"SongStartTime: {_songStartTime} RunTime: {_instance.RunTime}"); State = GameplayManagerState.Gameplay; diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 2a3e0034..e3184677 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -248,6 +248,7 @@ public void Update() private void CountingDown(bool isReady, bool NotStartable) { + _logger.Debug($"CountdownEndTime '{CountdownEndTime}' RunTime '{_instance.RunTime}' BeatMapStartCountdownTime '{_configuration.CountdownConfig.BeatMapStartCountdownTime}' CountdownTimePlayersReady '{_configuration.CountdownConfig.CountdownTimePlayersReady}'"); // If not already counting down if (CountDownState == CountdownState.NotCountingDown) { @@ -261,8 +262,10 @@ private void CountingDown(bool isReady, bool NotStartable) // If counting down if (CountDownState != CountdownState.NotCountingDown) { + _logger.Debug($"CountdownEndTime '{CountdownEndTime}' RunTime '{_instance.RunTime}'"); if(CountdownEndTime <= _instance.RunTime) { + _logger.Debug($"Countdown finished, sending map"); // If countdown just finished, send map then pause lobby untill all players have map downloaded if (CountDownState != CountdownState.WaitingForEntitlement) { @@ -281,6 +284,7 @@ private void CountingDown(bool isReady, bool NotStartable) }, DeliveryMethod.ReliableOrdered); } } + _logger.Debug($"All players have entitlement, starting map"); //starts beatmap _gameplayManager.SetBeatmap(SelectedBeatmap!, SelectedModifiers); Task.Run(() => _gameplayManager.StartSong(CancellationToken.None)); @@ -290,6 +294,7 @@ private void CountingDown(bool isReady, bool NotStartable) } if (CountdownEndTime + _configuration.SendPlayersWithoutEntitlementToSpectateTimeout <= _instance.RunTime) //If takes too long to start then players are sent to spectate by telling them the beatmap already started { + _logger.Debug($"Took too long to start, sending players to spectate"); IPlayer[] MissingEntitlement = _playerRegistry.Players.Where(p => p.GetEntitlement(SelectedBeatmap!.LevelId) is not EntitlementStatus.Ok).ToArray(); foreach (IPlayer p in MissingEntitlement) { @@ -355,7 +360,8 @@ public BeatmapDifficulty[] GetSelectedBeatmapDifficulties() // If you want to cancel the countdown use CancelCountdown(), Not SetCountdown as CancelCountdown() ALSO informs the clients it has been canceled, whereas SetCountdown will not private void SetCountdown(CountdownState countdownState, long countdown = 0) { - _logger.Error($"CountdownEndTime currently is '{CountdownEndTime}' countdown is set to '{countdown}' state will be set to '{countdownState}'"); + _logger.Error($"CountdownEndTime currently is '{CountdownEndTime}' countdown is set to '{countdown}' state will be set to '{countdownState}' BeatmapStartTime is '{_configuration.CountdownConfig.BeatMapStartCountdownTime}'"); + _logger.Error($"Check should start Beatmap {(CountdownEndTime - _instance.RunTime) < _configuration.CountdownConfig.BeatMapStartCountdownTime} EndTime '{CountdownEndTime - _instance.RunTime}' RunTime '{_instance.RunTime}'"); CountDownState = countdownState; switch (CountDownState) { @@ -366,7 +372,7 @@ private void SetCountdown(CountdownState countdownState, long countdown = 0) break; case CountdownState.CountingDown: if (countdown == 0) - countdown = 30*2; + countdown = 30000L; CountdownEndTime = _instance.RunTime + countdown; _packetDispatcher.SendToNearbyPlayers(new SetCountdownEndTimePacket { @@ -375,7 +381,7 @@ private void SetCountdown(CountdownState countdownState, long countdown = 0) break; case CountdownState.StartBeatmapCountdown: if (countdown == 0) - countdown = 5*2; + countdown = 5000L; CountdownEndTime = _instance.RunTime + countdown; StartBeatmapPacket(); break; @@ -383,7 +389,7 @@ private void SetCountdown(CountdownState countdownState, long countdown = 0) StartBeatmapPacket(); break; } - _logger.Error($"CountdownEndTime final set to '{CountdownEndTime}' CountdownState '{CountDownState}' countdown is '{countdown}' RunTime is '{_instance.RunTime}'"); + _logger.Error($"CountdownEndTime final set to '{CountdownEndTime}' CountdownState '{CountDownState}' countdown is '{countdown}' RunTime is '{_instance.RunTime}' BeatmapStartTime is '{_configuration.CountdownConfig.BeatMapStartCountdownTime}'"); } //Checks the lobby settings and sends the player the correct beatmap diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs index 7fda03f6..018efff0 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs @@ -25,7 +25,7 @@ public override Task Handle(IPlayer sender, GetCountdownEndTimePacket packet) { _logger.Debug( $"Handling packet of type '{nameof(GetCountdownEndTimePacket)}' " + - $"(SenderId={sender.ConnectionId})." + $"(SenderId={sender.ConnectionId} CountdownTime={_lobbyManager.CountdownEndTime})." ); if(_lobbyManager.CountDownState == Enums.CountdownState.CountingDown) _packetDispatcher.SendToPlayer(sender, new SetCountdownEndTimePacket diff --git a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs index 321121b2..54755343 100644 --- a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs +++ b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs @@ -71,9 +71,9 @@ bool AllowNE instanceConfig.AllowPerPlayerModifiers = AllowPerPlayerModifiers; if (permanentManager) instanceConfig.SetConstantManagerFromUserId = managerId; - instanceConfig.CountdownConfig.CountdownTimePlayersReady = Math.Max(PlayersReadyCountdownTime,0); - if (instanceConfig.CountdownConfig.CountdownTimePlayersReady == 0f) - instanceConfig.CountdownConfig.CountdownTimePlayersReady = instanceConfig.GameplayServerMode == GameplayServerMode.Managed ? 15 : 30; + instanceConfig.CountdownConfig.CountdownTimePlayersReady = Math.Max(PlayersReadyCountdownTime,0L); + if (instanceConfig.CountdownConfig.CountdownTimePlayersReady == 0L) + instanceConfig.CountdownConfig.CountdownTimePlayersReady = instanceConfig.GameplayServerMode == GameplayServerMode.Managed ? 15000L : 30000L; var instance = scope.ServiceProvider.GetRequiredService(); if (!_instanceRegistry.AddInstance(instance)) return null; diff --git a/BeatTogether.DedicatedServer.Node/NodeService.cs b/BeatTogether.DedicatedServer.Node/NodeService.cs index 3bd56917..064f7f7a 100644 --- a/BeatTogether.DedicatedServer.Node/NodeService.cs +++ b/BeatTogether.DedicatedServer.Node/NodeService.cs @@ -55,8 +55,8 @@ public async Task CreateMatchmakingServer(Creat request.Timeout, request.ServerName, (long)request.resultScreenTime, - (long)request.BeatmapStartTime, - (long)request.PlayersReadyCountdownTime , + ((long)request.BeatmapStartTime) * 1000, + ((long)request.PlayersReadyCountdownTime) * 1000, request.AllowPerPlayerModifiers, request.AllowPerPlayerDifficulties, request.AllowChroma, From 9b588a5b9f2e00a8a16b1bc4cd5badfd6351159b Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Thu, 21 Dec 2023 21:27:26 +0100 Subject: [PATCH 076/120] MpPlayerData Platform conversion, MpNodePose update to long, extra logging --- .../DedicatedInstance.cs | 29 ++++++++-------- .../GamePlatformToMpCorePlatform.cs | 33 +++++++++++++++++++ .../GetExtraPlayerDataPacketHandler.cs | 3 +- .../MpNodePoseSyncStatePacket.cs | 15 +++++---- .../MpCorePackets/MpPlayerData.cs | 17 +++++++--- 5 files changed, 72 insertions(+), 25 deletions(-) create mode 100644 BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index d459f5b6..1b1b4096 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -9,6 +9,7 @@ using BeatTogether.DedicatedServer.Kernel.Encryption; using BeatTogether.DedicatedServer.Kernel.ENet; using BeatTogether.DedicatedServer.Kernel.Enums; +using BeatTogether.DedicatedServer.Kernel.Extensions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets; @@ -378,7 +379,7 @@ public void SetState(MultiplayerGameState state) _handshakeSessionRegistry.TryGetByPlayerSessionId(connectionRequestData.PlayerSessionId); _handshakeSessionRegistry.RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out var ClientVer, out var Platform, out var PlayerPlatformUserId); player.ClientVersion = ClientVer; - player.Platform = (Platform)Platform; + player.Platform = (Enums.Platform)Platform; player.PlatformUserId = PlayerPlatformUserId; if (handshakeSession != null && handshakeSession.EncryptionParameters != null) { @@ -419,8 +420,8 @@ private async void SendPlayerDataInBackgroundAsync(IPlayer player) }, new MpNodePoseSyncStatePacket { - fullStateUpdateFrequency = 0.1f, - deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f + fullStateUpdateFrequency = 100L, + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() }, }; player.PlayerAccessSemaphore.Release(); @@ -560,7 +561,7 @@ public async Task ShouldDenyConnection(EndPoint endPoint, byte[] additiona _handshakeSessionRegistry.TryGetByPlayerSessionId(connectionRequestData.PlayerSessionId); _handshakeSessionRegistry.RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out var ClientVer, out var Platform, out var PlayerPlatformUserId); player.ClientVersion = ClientVer; - player.Platform = (Platform)Platform; + player.Platform = (Enums.Platform)Platform; player.PlatformUserId = PlayerPlatformUserId; if (handshakeSession != null && handshakeSession.EncryptionParameters != null) { @@ -588,12 +589,14 @@ public async Task ShouldDenyConnection(EndPoint endPoint, byte[] additiona }, new MpNodePoseSyncStatePacket { - fullStateUpdateFrequency = 0.1f, - deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f + fullStateUpdateFrequency = 100L, + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() }, }; player.PlayerAccessSemaphore.Release(); + _logger.Debug($"MpNodePoseSyncStatePacket check deltaUpdateFrequency {_playerRegistry.GetMillisBetweenSyncStatePackets()}"); + PacketDispatcher.SendExcludingPlayer(player, SendToOtherPlayers, DeliveryMethod.ReliableOrdered); @@ -650,8 +653,8 @@ public override async void OnConnect(EndPoint endPoint) }, new MpNodePoseSyncStatePacket { - fullStateUpdateFrequency = 0.1f, - deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f + fullStateUpdateFrequency = 100L, + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() }, }; player.PlayerAccessSemaphore.Release(); @@ -710,7 +713,7 @@ public override async void OnConnect(EndPoint endPoint) }, DeliveryMethod.ReliableOrdered); } - if (player.Platform == Platform.Test) //If the player is a bot, send permissions. Normal players request this in a packet when they join + if (player.Platform == Kernel.Enums.Platform.Test) //If the player is a bot, send permissions. Normal players request this in a packet when they join { bool HasManager = (_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var ServerOwner) && !player.IsServerOwner); PlayerPermissionConfiguration[] playerPermissionConfigurations = new PlayerPermissionConfiguration[HasManager ? 2 : 1]; @@ -759,7 +762,7 @@ public override async void OnConnect(EndPoint endPoint) ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).Random = new ByteArray { Data = p.Random }; ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PublicEncryptionKey = new ByteArray { Data = p.PublicEncryptionKey }; ((MpPlayerData)SendToPlayerFromPlayers[1]).PlatformID = p.PlatformUserId; - ((MpPlayerData)SendToPlayerFromPlayers[1]).Platform = (byte)p.Platform; + ((MpPlayerData)SendToPlayerFromPlayers[1]).Platform = p.Platform.Convert(); ((MpPlayerData)SendToPlayerFromPlayers[1]).ClientVersion = p.ClientVersion; p.PlayerAccessSemaphore.Release(); @@ -779,7 +782,7 @@ await Task.WhenAny( PacketDispatcher.SendFromPlayerToPlayerAndAwait(player, p, new MpPlayerData { PlatformID = player.PlatformUserId!, - Platform = (byte)player.Platform, + Platform = player.Platform.Convert(), ClientVersion = player.ClientVersion! }, DeliveryMethod.ReliableOrdered), Task.Delay(50)); @@ -879,8 +882,8 @@ public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reas PacketDispatcher.SendToNearbyPlayers(new MpNodePoseSyncStatePacket { - fullStateUpdateFrequency = 0.1f, - deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() * 0.001f + fullStateUpdateFrequency = 100L, + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() }, DeliveryMethod.ReliableOrdered); if (_playerRegistry.GetPlayerCount() == 0) diff --git a/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs b/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs new file mode 100644 index 00000000..6d897509 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; + +namespace BeatTogether.DedicatedServer.Kernel.Extensions +{ + public static class GamePlatformToMpCorePlatform + { + public static Platform Convert(this Kernel.Enums.Platform gamePlatform) + { + switch (gamePlatform) + { + case Kernel.Enums.Platform.Test: + return Platform.Unknown; + case Kernel.Enums.Platform.OculusRift: + return Platform.OculusPC; + case Kernel.Enums.Platform.OculusQuest: + return Platform.OculusQuest; + case Kernel.Enums.Platform.Steam: + return Platform.Steam; + case Kernel.Enums.Platform.PS4: + case Kernel.Enums.Platform.PS4Dev: + case Kernel.Enums.Platform.PS4Cert: + return Platform.PS4; + default: + return 0; + } + } + } +} diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs index d4decb03..6e3faaad 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs @@ -1,4 +1,5 @@ using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.Extensions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; using BeatTogether.LiteNetLib.Enums; using System.Threading.Tasks; @@ -26,7 +27,7 @@ public override Task Handle(IPlayer sender, MpPlayerData packet) _PacketDispatcher.SendFromPlayerToPlayer(Player, sender, new MpPlayerData() { PlatformID = Player.PlatformUserId, - Platform = (byte)Player.Platform, + Platform = Player.Platform.Convert(), ClientVersion = Player.ClientVersion }, DeliveryMethod.ReliableOrdered); } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpNodePoseSyncStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpNodePoseSyncStatePacket.cs index 8e775c69..b32127b5 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpNodePoseSyncStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpNodePoseSyncStatePacket.cs @@ -1,22 +1,23 @@ -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets { public sealed class MpNodePoseSyncStatePacket : INetSerializable { - public float deltaUpdateFrequency; - public float fullStateUpdateFrequency; + public long deltaUpdateFrequency; + public long fullStateUpdateFrequency; public void WriteTo(ref SpanBuffer bufferWriter) { - bufferWriter.WriteFloat32(deltaUpdateFrequency); - bufferWriter.WriteFloat32(fullStateUpdateFrequency); + bufferWriter.WriteVarLong(deltaUpdateFrequency); + bufferWriter.WriteVarLong(fullStateUpdateFrequency); } public void ReadFrom(ref SpanBuffer bufferReader) { - deltaUpdateFrequency = bufferReader.ReadFloat32(); - fullStateUpdateFrequency = bufferReader.ReadFloat32(); + deltaUpdateFrequency = bufferReader.ReadVarLong(); + fullStateUpdateFrequency = bufferReader.ReadVarLong(); } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPlayerData.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPlayerData.cs index bb935e66..eee64196 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPlayerData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPlayerData.cs @@ -4,22 +4,31 @@ namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets { + public enum Platform + { + Unknown = 0, + Steam = 1, + OculusPC = 2, + OculusQuest = 3, + PS4 = 4 + } + public sealed class MpPlayerData : INetSerializable { public string PlatformID = string.Empty; - public byte Platform; + public Platform Platform; public string ClientVersion = string.Empty; public void WriteTo(ref SpanBuffer bufferWriter) { bufferWriter.WriteString(PlatformID); - bufferWriter.WriteUInt8(Platform); - bufferWriter.WriteString(ClientVersion); + bufferWriter.WriteInt32((int)Platform); + bufferWriter.WriteString(ClientVersion.Replace("_","-")); } public void ReadFrom(ref SpanBuffer bufferReader) { PlatformID = bufferReader.ReadString(); - Platform = bufferReader.ReadUInt8(); + Platform = (Platform)bufferReader.ReadInt32(); ClientVersion = bufferReader.ReadString(); } } From 5374038e2b093769e427b50270361633d201c57a Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Thu, 21 Dec 2023 21:29:28 +0100 Subject: [PATCH 077/120] Update NodePose- and ScoreSyncStatePacket float to long --- .../Packets/MultiplayerSession/NodePoseSyncStatePacket.cs | 6 +++--- .../Packets/MultiplayerSession/ScoreSyncStatePacket.cs | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs index bd2e4729..228d47d6 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs @@ -8,20 +8,20 @@ namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession public sealed class NodePoseSyncStatePacket : INetSerializable { public byte SyncStateId { get; set; } - public float Time { get; set; } + public long Time { get; set; } public NodePoseSyncState State { get; set; } = new(); public void ReadFrom(ref SpanBuffer reader) { SyncStateId = reader.ReadUInt8(); - Time = reader.ReadFloat32(); + Time = (long)reader.ReadVarULong(); State.ReadFrom(ref reader); } public void WriteTo(ref SpanBuffer writer) { writer.WriteUInt8(SyncStateId); - writer.WriteFloat32(Time); + writer.WriteVarULong((ulong)Time); State.WriteTo(ref writer); } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs index cec87d3d..60bac637 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs @@ -1,4 +1,5 @@ using BeatTogether.DedicatedServer.Messaging.Models; +using BeatTogether.Extensions; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Util; @@ -7,20 +8,20 @@ namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession public sealed class ScoreSyncStatePacket : INetSerializable { public byte SyncStateId { get; set; } - public float Time { get; set; } + public long Time { get; set; } public StandardScoreSyncState State { get; set; } = new(); public void ReadFrom(ref SpanBuffer reader) { SyncStateId = reader.ReadUInt8(); - Time = reader.ReadFloat32(); + Time = (long)reader.ReadVarULong(); State.ReadFrom(ref reader); } public void WriteTo(ref SpanBuffer writer) { writer.WriteUInt8(SyncStateId); - writer.WriteFloat32(Time); + writer.WriteVarULong((ulong)Time); State.WriteTo(ref writer); } } From c6d8c418f7c426e2a78d99c8ad8ab5b883843214 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Thu, 21 Dec 2023 21:32:16 +0100 Subject: [PATCH 078/120] Avatar Identifier send as UInt32 instead of VarUInt --- .../Models/MultiplayerAvatarsData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs index f0d57aa3..7086e558 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs @@ -51,7 +51,7 @@ public void WriteToAvatarsData(ref SpanBuffer writer) writer.WriteInt32(AvatarsData.Count); foreach (MultiplayerAvatarData multiplayerAvatarData in AvatarsData) { - writer.WriteVarUInt(multiplayerAvatarData.AvatarTypeIdentifierHash); + writer.WriteUInt32(multiplayerAvatarData.AvatarTypeIdentifierHash); writer.WriteByteArray(multiplayerAvatarData.Data); } } From 37c1cc6b85cb7c9e6ad6a14b8a60e2bd77f4bec5 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Thu, 21 Dec 2023 22:40:15 +0100 Subject: [PATCH 079/120] Fix packets directly routed were not sent via ENet --- .../PacketDispatcher.cs | 27 ++++++++++++++++++- .../PacketSource.cs | 14 +++++----- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index 13c4337e..d94b7687 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -52,7 +52,7 @@ private void SendInternal(IPlayer player, ref SpanBuffer writer, DeliveryMethod _logger.Verbose($"Sending packet (SenderId={ServerId}) to player {player.ConnectionId} with UserId {player.UserId} via LiteNet"); Send(player.Endpoint, writer.Data, deliveryMethod); } - + #region Sends public void SendToNearbyPlayers(INetSerializable packet, DeliveryMethod deliveryMethod) { @@ -99,6 +99,7 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, if (player.ConnectionId != excludedPlayer.ConnectionId) SendInternal(player, ref writer, deliveryMethod); } + public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) { _logger.Debug( @@ -122,6 +123,19 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packe SendInternal(player, ref writer, deliveryMethod); } + public void RouteExcludingPlayer(IPlayer excludedPlayer, ref SpanBuffer writer, DeliveryMethod deliveryMethod) + { + _logger.Debug( + $"Sending routed packet " + + $"(ExcludedId={excludedPlayer.ConnectionId})" + ); + + foreach (IPlayer player in _playerRegistry.Players) + if (player.ConnectionId != excludedPlayer.ConnectionId) + SendInternal(player, ref writer, deliveryMethod); + } + + public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) { _logger.Debug( @@ -163,6 +177,7 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer WriteOne(ref writer, packet); SendInternal(toPlayer, ref writer, deliveryMethod); } + public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) { _logger.Debug( @@ -176,6 +191,16 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer SendInternal(toPlayer, ref writer, deliveryMethod); } + public void RouteFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, ref SpanBuffer writer, DeliveryMethod deliveryMethod) + { + _logger.Debug( + $"Sending routed packet " + + $"(SenderId={fromPlayer.ConnectionId}, ReceiverId={LocalConnectionId})." + ); + + SendInternal(toPlayer, ref writer, deliveryMethod); + } + public void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod deliveryMethod) { _logger.Debug( diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index eb92a44c..6c972f48 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -115,6 +115,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D if (packet == null) { + _logger.Debug($"Failed to create packet."); // skip any unprocessed bytes var processedBytes = HandleRead.Offset - prevPosition; try { HandleRead.SkipBytes((int)length - processedBytes); } @@ -132,6 +133,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D { if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncState) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets()) { + _logger.Verbose($"Skipping sync state packet from {sender.ConnectionId} (Secret='{sender.Secret}')."); return; } method = DeliveryMethod.Unreliable; @@ -139,8 +141,9 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D } if (packet is NodePoseSyncStateDeltaPacket) { - if((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncStateDelta) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets()) + if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncStateDelta) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets()) { + _logger.Verbose($"Skipping sync state packet from {sender.ConnectionId} (Secret='{sender.Secret}')."); return; } sender.TicksAtLastSyncStateDelta = DateTime.UtcNow.Ticks; @@ -151,7 +154,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D var packetHandler = _serviceProvider.GetService(packetHandlerType); if (packetHandler is null) { - if (!packetType.Name.StartsWith("NodePoseSyncState")) + //if (!packetType.Name.StartsWith("NodePoseSyncState")) _logger.Verbose($"No handler exists for packet of type '{packetType.Name}'."); // skip any unprocessed bytes @@ -168,6 +171,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D catch { // skip any unprocessed bytes + _logger.Debug($"Failed to read packet of type '{packetType.Name}'."); var processedBytes = HandleRead.Offset - prevPosition; try { HandleRead.SkipBytes((int)length - processedBytes); } catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); goto RoutePacket; } @@ -200,9 +204,7 @@ private void RoutePacket(IPlayer sender, $"PacketOption='{routingHeader.PacketOption}' " + $"(Secret='{sender.Secret}', DeliveryMethod={deliveryMethod})." ); - foreach (var player in _playerRegistry.Players) - if (player != sender) - _packetDispatcher.Send(player.Endpoint, writer.Data, deliveryMethod); + _packetDispatcher.RouteExcludingPlayer(sender, ref writer, deliveryMethod); } else { @@ -222,7 +224,7 @@ private void RoutePacket(IPlayer sender, $"PacketOption='{routingHeader.PacketOption}' " + $"(Secret='{sender.Secret}', DeliveryMethod={deliveryMethod})." ); - _packetDispatcher.Send(receiver.Endpoint, writer.Data, deliveryMethod); + _packetDispatcher.RouteFromPlayerToPlayer(sender, receiver, ref writer, deliveryMethod); } } From 0124fed0bf80587ff1ec450a08ea78ad26ae5ded Mon Sep 17 00:00:00 2001 From: cubic <79692655+cubicgraphics@users.noreply.github.com> Date: Tue, 27 Feb 2024 00:32:30 +0000 Subject: [PATCH 080/120] Update LobbyManager.cs Changed order of processes when not entitled players list are sent to players with beatmaps --- BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index e3184677..8ee8e93d 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -189,6 +189,7 @@ public void Update() { if (player.UpdateEntitlement || SpectatingPlayersUpdated) { + player.UpdateEntitlement = false; if (player.BeatmapIdentifier != null) { _packetDispatcher.SendToPlayer(player, new SetPlayersMissingEntitlementsToLevelPacket @@ -199,7 +200,6 @@ public void Update() }, DeliveryMethod.ReliableOrdered); _logger.Debug("Sent missing entitlement packet"); } - player.UpdateEntitlement = false; } } SpectatingPlayersUpdated = false; From 0fbcfee4ab22aeb112e29bf35bd398ba47836f89 Mon Sep 17 00:00:00 2001 From: Aaron Date: Sat, 30 Mar 2024 20:15:02 +0000 Subject: [PATCH 081/120] First pass of removing compat for older versions --- .../CreateMatchmakingServerResponse.cs | 3 +- .../BaseHandshakeMessageHandler.cs | 15 - .../Abstractions/BasePacketHandler.cs | 5 +- .../Abstractions/IDedicatedInstance.cs | 8 +- .../Abstractions/IHandshakeMessageHandler.cs | 17 - .../Abstractions/IHandshakeService.cs | 15 - .../Abstractions/IHandshakeSessionRegistry.cs | 16 - .../Abstractions/IPacketDispatcher.cs | 4 +- .../Abstractions/IPacketHandler.cs | 5 +- .../Abstractions/IPlayer.cs | 8 +- .../Abstractions/IPlayerRegistry.cs | 3 + .../Abstractions/IUnconnectedDispatcher.cs | 11 - .../Configuration/InstanceConfiguration.cs | 4 +- .../DedicatedInstance.cs | 409 +++++------------- .../ENet/ENetServer.cs | 52 ++- .../GamePlatformToMpCorePlatform.cs | 23 +- .../Extensions/HostBuilderExtensions.cs | 45 +- .../Extensions/ServiceCollectionExtensions.cs | 4 +- .../Handshake/HandshakePendingMultipart.cs | 83 ---- .../Handshake/HandshakePendingRequest.cs | 67 --- .../Handshake/HandshakeService.cs | 249 ----------- .../Handshake/HandshakeSession.cs | 42 -- .../Handshake/HandshakeSessionRegistry.cs | 67 --- .../Handshake/UnconnectedDispatcher.cs | 141 ------ .../Handshake/UnconnectedSource.cs | 194 --------- .../Managers/LobbyManager.cs | 7 +- .../PacketDispatcher.cs | 260 +---------- .../GameplayRpc/LevelFinishedPacketHandler.cs | 4 +- .../RequestReturnToMenuPacketHandler.cs | 5 +- .../SetGameplaySceneReadyPacketHandler.cs | 8 +- .../SetGameplaySongReadyPacketHandler.cs | 8 +- .../MPChat/MpcCapabilitiesPacketHandler.cs | 5 +- .../MPChat/MpcTextChatPacketHandler.cs | 6 +- .../ClearRecommendedBeatmapPacketHandler.cs | 4 +- .../ClearRecommendedModifiersPacketHandler.cs | 5 +- .../GetCountdownEndTimePacketHandler.cs | 4 +- .../MenuRpc/GetIsInLobbyPacketHandler.cs | 5 +- .../MenuRpc/GetIsReadyPacketHandler.cs | 5 +- .../GetMultiplayerGameStatePacketHandler.cs | 5 +- ...ersPermissionConfigurationPacketHandler.cs | 5 +- .../GetRecommendedBeatmapPacketHandler.cs | 5 +- .../GetRecommendedModifiersPacketHandler.cs | 5 +- .../MenuRpc/GetSelectedBeatmapHandler.cs | 8 +- .../GetSelectedGameplayModifiersHandler.cs | 8 +- .../MenuRpc/GetStartedLevelPacketHandler.cs | 4 +- .../MenuRpc/RequestKickPlayerPacketHandler.cs | 8 +- .../SetIsEntitledToLevelPacketHandler.cs | 6 +- .../MenuRpc/SetIsInLobbyPacketHandler.cs | 17 +- .../MenuRpc/SetIsReadyPacketHandler.cs | 9 +- .../SetRecommendedBeatmapPacketHandler.cs | 12 +- .../SetRecommendedModifiersPacketHandler.cs | 9 +- .../DediPacketSetNewManagerHandler.cs | 4 +- .../GetExtraPlayerDataPacketHandler.cs | 4 +- .../MultiplayerCore/MPBeatmapPacketHandler.cs | 4 +- .../PacketHandlers/PingPacketHandler.cs | 5 +- .../PlayerAvatarPacketHandler.cs | 7 +- .../PlayerIdentityPacketHandler.cs | 5 +- .../PlayerLatencyPacketHandler.cs | 11 +- .../PlayerSortOrderPacketHandler.cs | 12 +- .../PlayerStatePacketHandler.cs | 6 +- .../PacketHandlers/SyncTimePacketHandler.cs | 9 +- .../Unconnected/AcknowledgeMessageHandler.cs | 25 -- .../AuthenticateGameLiftUserRequestHandler.cs | 21 - .../Unconnected/ClientHelloRequestHandler.cs | 21 - .../ClientHelloWithCookieRequestHandler.cs | 21 - .../ClientKeyExchangeRequestHandler.cs | 21 - .../PacketSource.cs | 24 +- BeatTogether.DedicatedServer.Kernel/Player.cs | 17 +- .../PlayerRegistry.cs | 34 ++ .../Enums/EntitlementStatus.cs | 9 +- .../Enums/GameLiftMessageType.cs | 10 - .../AuthenticateGameLiftUserRequest.cs | 31 -- .../AuthenticateGameLiftUserResponse.cs | 32 -- .../Handshake/ChangeCipherSpecRequest.cs | 19 - .../Messages/Handshake/ClientHelloRequest.cs | 21 - .../Handshake/ClientHelloWithCookieRequest.cs | 27 -- .../Handshake/ClientKeyExchangeRequest.cs | 23 - .../Messages/Handshake/HelloVerifyRequest.cs | 22 - .../Handshake/ServerCertificateRequest.cs | 29 -- .../Messages/Handshake/ServerHelloRequest.cs | 29 -- .../Models/ConnectionRequestData.cs | 61 +-- .../Unconnected/GameLiftMessageRegistry.cs | 20 - .../Unconnected/HandshakeMessageRegistry.cs | 25 -- .../Configuration/NodeConfiguration.cs | 2 +- .../InstanceFactory.cs | 13 +- .../MasterServerEventHandler.cs | 21 +- .../NodeService.cs | 9 +- .../PortAllocator.cs | 37 +- 88 files changed, 356 insertions(+), 2252 deletions(-) delete mode 100644 BeatTogether.DedicatedServer.Kernel/Abstractions/BaseHandshakeMessageHandler.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeMessageHandler.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeService.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeSessionRegistry.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Abstractions/IUnconnectedDispatcher.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Handshake/HandshakePendingMultipart.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Handshake/HandshakePendingRequest.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeService.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeSession.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeSessionRegistry.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedSource.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/AcknowledgeMessageHandler.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/AuthenticateGameLiftUserRequestHandler.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/ClientHelloRequestHandler.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/ClientHelloWithCookieRequestHandler.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/ClientKeyExchangeRequestHandler.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Enums/GameLiftMessageType.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserRequest.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserResponse.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ChangeCipherSpecRequest.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ClientHelloRequest.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ClientHelloWithCookieRequest.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ClientKeyExchangeRequest.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Messages/Handshake/HelloVerifyRequest.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ServerCertificateRequest.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ServerHelloRequest.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Registries/Unconnected/GameLiftMessageRegistry.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Registries/Unconnected/HandshakeMessageRegistry.cs diff --git a/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs b/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs index b80ad625..3a122e1f 100644 --- a/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs +++ b/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs @@ -11,8 +11,7 @@ public record CreateMatchmakingServerResponse( CreateMatchmakingServerError Error, string? RemoteEndPoint = null, byte[]? Random = null, - byte[]? PublicKey = null, - string? RemoteEndPointENet = null) + byte[]? PublicKey = null) { public bool Success => Error == default; } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/BaseHandshakeMessageHandler.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/BaseHandshakeMessageHandler.cs deleted file mode 100644 index 04d67198..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/BaseHandshakeMessageHandler.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Threading.Tasks; -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Handshake; - -namespace BeatTogether.DedicatedServer.Kernel.Abstractions -{ - public abstract class BaseHandshakeMessageHandler : IHandshakeMessageHandler - where TMessage : class, IMessage - { - public abstract Task Handle(HandshakeSession session, TMessage message); - - public Task Handle(HandshakeSession session, IMessage message) => - Handle(session, (TMessage) message); - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/BasePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/BasePacketHandler.cs index 0b9dd5ba..c290a7e1 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/BasePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/BasePacketHandler.cs @@ -1,14 +1,13 @@ using BeatTogether.LiteNetLib.Abstractions; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { public abstract class BasePacketHandler : IPacketHandler where TPacket : class, INetSerializable { - public abstract Task Handle(IPlayer sender, TPacket packet); + public abstract void Handle(IPlayer sender, TPacket packet); - public Task Handle(IPlayer sender, INetSerializable packet) => + public void Handle(IPlayer sender, INetSerializable packet) => Handle(sender, (TPacket)packet); } } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs index 4e3164f1..c1dbcbae 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs @@ -16,18 +16,18 @@ public interface IDedicatedInstance event Action PlayerDisconnectBeforeJoining; event Action GameIsInLobby; event Action UpdateInstanceEvent; - SemaphoreSlim ConnectDisconnectSemaphore { get; } + void InstanceConfigUpdated(); InstanceConfiguration _configuration { get; } bool IsRunning { get; } long RunTime { get; } - public int LiteNetPort { get; } - public int ENetPort { get; } + //public int LiteNetPort { get; } + public int Port { get; } MultiplayerGameState State { get; } float NoPlayersTime { get; } - IHandshakeSessionRegistry GetHandshakeSessionRegistry(); + //IHandshakeSessionRegistry GetHandshakeSessionRegistry(); IPlayerRegistry GetPlayerRegistry(); IServiceProvider GetServiceProvider(); diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeMessageHandler.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeMessageHandler.cs deleted file mode 100644 index 3ac42934..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeMessageHandler.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Threading.Tasks; -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Handshake; - -namespace BeatTogether.DedicatedServer.Kernel.Abstractions -{ - public interface IHandshakeMessageHandler - { - Task Handle(HandshakeSession session, IMessage message); - } - - public interface IHandshakeMessageHandler : IHandshakeMessageHandler - where TMessage : class, IMessage - { - Task Handle(HandshakeSession session, TMessage message); - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeService.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeService.cs deleted file mode 100644 index 7b1fe24f..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeService.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Threading.Tasks; -using BeatTogether.DedicatedServer.Kernel.Handshake; -using BeatTogether.DedicatedServer.Messaging.Messages.GameLift; -using BeatTogether.DedicatedServer.Messaging.Messages.Handshake; - -namespace BeatTogether.DedicatedServer.Kernel.Abstractions -{ - public interface IHandshakeService - { - Task ClientHello(HandshakeSession session, ClientHelloRequest request); - Task ClientHelloWithCookie(HandshakeSession session, ClientHelloWithCookieRequest request); - Task ClientKeyExchange(HandshakeSession session, ClientKeyExchangeRequest request); - Task AuthenticateGameLiftUser(HandshakeSession session, AuthenticateGameLiftUserRequest request); - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeSessionRegistry.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeSessionRegistry.cs deleted file mode 100644 index 03c7790e..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IHandshakeSessionRegistry.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using System.Net; -using BeatTogether.DedicatedServer.Kernel.Handshake; - -namespace BeatTogether.DedicatedServer.Kernel.Abstractions -{ - public interface IHandshakeSessionRegistry - { - HandshakeSession GetOrAdd(EndPoint endPoint); - HandshakeSession? TryGetByPlayerSessionId(string playerSessionId); - void AddPendingPlayerSessionId(string playerSessionId); - void AddExtraPlayerSessionData(string playerSessionId, string ClientVersion, byte Platform, string PlayerPlatformUserId); - void RemoveExtraPlayerSessionData(string playerSessionId, out string ClientVersion, out byte Platform, out string PlayerPlatformUserId); - bool TryRemovePendingPlayerSessionId(string playerSessionId); - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs index 349a338e..81ae9192 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs @@ -1,6 +1,5 @@ using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Enums; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { @@ -17,7 +16,7 @@ public interface IPacketDispatcher void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod); void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); - + /* Task SendToNearbyPlayersAndAwait(INetSerializable packet, DeliveryMethod deliveryMethod); Task SendToNearbyPlayersAndAwait(INetSerializable[] packets, DeliveryMethod deliveryMethod); Task SendExcludingPlayerAndAwait(IPlayer excludedPlayer, INetSerializable packet, DeliveryMethod deliveryMethod); @@ -28,5 +27,6 @@ public interface IPacketDispatcher Task SendFromPlayerToPlayerAndAwait(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); Task SendToPlayerAndAwait(IPlayer player, INetSerializable packet, DeliveryMethod deliveryMethod); Task SendToPlayerAndAwait(IPlayer player, INetSerializable[] packets, DeliveryMethod deliveryMethod); + */ } } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketHandler.cs index df5bdf0c..fd1cbacf 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketHandler.cs @@ -1,16 +1,15 @@ using BeatTogether.LiteNetLib.Abstractions; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { public interface IPacketHandler { - Task Handle(IPlayer sender, INetSerializable packet); + void Handle(IPlayer sender, INetSerializable packet); } public interface IPacketHandler : IPacketHandler where TPacket : class, INetSerializable { - Task Handle(IPlayer sender, TPacket packet); + void Handle(IPlayer sender, TPacket packet); } } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index 477f0ff5..dcc4c0d7 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -3,22 +3,18 @@ using BeatTogether.DedicatedServer.Kernel.Types; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; -using System.Threading; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { public interface IPlayer { - SemaphoreSlim PlayerAccessSemaphore { get; set; } EndPoint Endpoint { get; } IDedicatedInstance Instance { get; } byte ConnectionId { get; } byte RemoteConnectionId { get; } - string Secret { get; } string UserId { get; } string UserName { get; } - string? PlayerSessionId { get; } + string PlayerSessionId { get; } byte[]? Random { get; set; } byte[]? PublicEncryptionKey { get; set; } @@ -27,7 +23,7 @@ public interface IPlayer string PlatformUserId { get; set; } uint? ENetPeerId { get; set; } - bool IsENetConnection => ENetPeerId.HasValue; + bool IsENetConnection { get;} RollingAverage Latency { get; } long SyncTime { get; } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs index 0d162f90..0b7a93b6 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs @@ -13,5 +13,8 @@ public interface IPlayerRegistry bool TryGetPlayer(byte connectionId, [MaybeNullWhen(false)] out IPlayer player); bool TryGetPlayer(string userId, [MaybeNullWhen(false)] out IPlayer player); int GetMillisBetweenSyncStatePackets(); + + public void AddExtraPlayerSessionData(string playerSessionId, string ClientVersion, byte PlatformId, string PlayerPlatformUserId); + public bool RemoveExtraPlayerSessionData(string playerSessionId, out string ClientVersion, out byte Platform, out string PlayerPlatformUserId); } } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IUnconnectedDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IUnconnectedDispatcher.cs deleted file mode 100644 index e72f8020..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IUnconnectedDispatcher.cs +++ /dev/null @@ -1,11 +0,0 @@ -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Handshake; - -namespace BeatTogether.DedicatedServer.Kernel.Abstractions -{ - public interface IUnconnectedDispatcher - { - void Send(HandshakeSession session, IMessage message, bool retry = false); - bool Acknowledge(HandshakeSession session, uint responseId, bool handled = true); - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs index 384652f0..a8e9a827 100644 --- a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs +++ b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs @@ -4,8 +4,8 @@ namespace BeatTogether.DedicatedServer.Kernel.Configuration { public sealed class InstanceConfiguration { - public int LiteNetPort { get; set; } - public int ENetPort { get; set; } + //public int LiteNetPort { get; set; } + public int Port { get; set; } public string Secret { get; set; } = string.Empty; public string ServerOwnerId { get; set; } = string.Empty; public string ServerId { get; set; } = "ziuMSceapEuNN7wRGQXrZg"; diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 1b1b4096..b493cb98 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -16,18 +16,23 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; -using BeatTogether.LiteNetLib; using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Configuration; using BeatTogether.LiteNetLib.Enums; +//using BeatTogether.LiteNetLib.Sources; using BeatTogether.LiteNetLib.Util; -using BeatTogether.LiteNetLib.Sources; -using Microsoft.Extensions.DependencyInjection; + +//using BeatTogether.LiteNetLib; +//using BeatTogether.LiteNetLib.Abstractions; +//using BeatTogether.LiteNetLib.Configuration; +//using BeatTogether.LiteNetLib.Enums; +//using BeatTogether.LiteNetLib.Util; +//using BeatTogether.LiteNetLib.Sources; +//using Microsoft.Extensions.DependencyInjection; using Serilog; namespace BeatTogether.DedicatedServer.Kernel { - public sealed class DedicatedInstance : LiteNetServer, IDedicatedInstance + public sealed class DedicatedInstance : ENetServer, /*LiteNetServer,*/ IDedicatedInstance { // Milliseconds instance will wait for a player to connect. public const int WaitForPlayerTimeLimit = 10000; @@ -36,9 +41,9 @@ public sealed class DedicatedInstance : LiteNetServer, IDedicatedInstance public const int SyncTimeDelay = 5000; public InstanceConfiguration _configuration { get; private set; } - public int LiteNetPort => _configuration.LiteNetPort; - public int ENetPort => _configuration.ENetPort; - public bool IsRunning => IsStarted; + //public int LiteNetPort => _configuration.LiteNetPort; + public int Port => _configuration.Port; + public bool IsRunning => IsAlive; public long RunTime => (DateTime.UtcNow.Ticks - _startTime) / 10000L; public float NoPlayersTime { get; private set; } = -1; //tracks the instance time once there are 0 players in the lobby public MultiplayerGameState State { get; private set; } = MultiplayerGameState.Lobby; @@ -50,64 +55,52 @@ public sealed class DedicatedInstance : LiteNetServer, IDedicatedInstance public event Action GameIsInLobby = null!; public event Action UpdateInstanceEvent = null!; - private readonly IHandshakeSessionRegistry _handshakeSessionRegistry; + //private readonly IHandshakeSessionRegistry _handshakeSessionRegistry; private readonly IPlayerRegistry _playerRegistry; private readonly IServiceProvider _serviceProvider; private readonly PacketEncryptionLayer _packetEncryptionLayer; - public SemaphoreSlim ConnectDisconnectSemaphore { get; } = new(1); //Stops lobby loop from running during player connection/disconnection, and stops disconnects and connects happening simultaneously + private readonly IPacketDispatcher PacketDispatcher; + private readonly PacketSource ConnectedMessageSource; + + //public SemaphoreSlim ConnectDisconnectSemaphore { get; } = new(1); //Stops lobby loop from running during player connection/disconnection, and stops disconnects and connects happening simultaneously private byte _connectionIdCount = 0; - private readonly object _ConnectionIDLock = new(); private int _lastSortIndex = -1; - private readonly object _SortIndexLock = new(); private readonly Queue _releasedConnectionIds = new(); - private readonly object _releasedConnectionIds_Lock = new(); private readonly Queue _releasedSortIndices = new(); - private readonly object _releasedSortIndices_Lock = new(); private readonly ILogger _logger = Log.ForContext(); private long _startTime; private CancellationTokenSource? _waitForPlayerCts = null; private CancellationTokenSource? _stopServerCts; - public IPacketDispatcher PacketDispatcher { get; private set; } - public ConnectedMessageSource ConnectedMessageSource { get; private set; } - public readonly ENetServer ENetServer; + + //public readonly ENetServer ENetServer; public DedicatedInstance( InstanceConfiguration configuration, - IHandshakeSessionRegistry handshakeSessionRegistry, + //IHandshakeSessionRegistry handshakeSessionRegistry, IPlayerRegistry playerRegistry, - LiteNetConfiguration liteNetConfiguration, - LiteNetPacketRegistry registry, + //LiteNetConfiguration liteNetConfiguration, + //LiteNetPacketRegistry registry, + IPacketDispatcher packetDispatcher, + PacketSource connectedMessageSource, IServiceProvider serviceProvider, - IPacketLayer packetLayer, + //IPacketLayer packetLayer, PacketEncryptionLayer packetEncryptionLayer) - : base ( - new IPEndPoint(IPAddress.Any, configuration.LiteNetPort), - liteNetConfiguration, - registry, - serviceProvider, - (configuration.MaxPlayerCount/20+1), - packetLayer) + : base (configuration.Port) { _configuration = configuration; - - _handshakeSessionRegistry = handshakeSessionRegistry; _playerRegistry = playerRegistry; _serviceProvider = serviceProvider; _packetEncryptionLayer = packetEncryptionLayer; - - ENetServer = new(this, configuration.ENetPort); + PacketDispatcher = packetDispatcher; + ConnectedMessageSource = connectedMessageSource; } #region Public Methods - - public IHandshakeSessionRegistry GetHandshakeSessionRegistry() - { - return _handshakeSessionRegistry; - } + public IPlayerRegistry GetPlayerRegistry() { @@ -123,14 +116,14 @@ public async Task Start(CancellationToken cancellationToken = default) if (IsRunning) return; - PacketDispatcher = _serviceProvider.GetRequiredService(); - ConnectedMessageSource = _serviceProvider.GetRequiredService(); + //PacketDispatcher = _serviceProvider.GetRequiredService(); + //ConnectedMessageSource = _serviceProvider.GetRequiredService(); _startTime = DateTime.UtcNow.Ticks; _logger.Information( "Starting dedicated server " + - "(Endpoint={Endpoint}," + + $"Endpoint={EndPoint}," + $"ServerName='{_configuration.ServerName}', " + $"Secret='{_configuration.Secret}', " + $"ManagerId='{_configuration.ServerOwnerId}', " + @@ -139,8 +132,7 @@ public async Task Start(CancellationToken cancellationToken = default) $"InvitePolicy={_configuration.InvitePolicy}, " + $"GameplayServerMode={_configuration.GameplayServerMode}, " + $"SongSelectionMode={_configuration.SongSelectionMode}, " + - $"GameplayServerControlSettings={_configuration.GameplayServerControlSettings})", - Endpoint + $"GameplayServerControlSettings={_configuration.GameplayServerControlSettings})" ); _stopServerCts = new CancellationTokenSource(); @@ -166,8 +158,7 @@ public async Task Start(CancellationToken cancellationToken = default) }, cancellationToken); } - base.Start(); - await ENetServer.Start(); + await base.Start(); _ = Task.Run(() => SendSyncTime(_stopServerCts.Token), cancellationToken); } @@ -196,67 +187,51 @@ public async Task Stop(CancellationToken cancellationToken = default) DisconnectedReason = DisconnectedReason.ServerTerminated }, DeliveryMethod.ReliableOrdered); - ENetServer.KickAllPeers(); + KickAllPeers(); _stopServerCts!.Cancel(); _waitForPlayerCts!.Cancel(); StopEvent?.Invoke(this); - base.Stop(); - await ENetServer.Stop(); + await base.Stop(); } public int GetNextSortIndex() { - lock (_releasedSortIndices_Lock) - { - if (_releasedSortIndices.TryDequeue(out var sortIndex)) - return sortIndex; - } - lock (_SortIndexLock) + if (_releasedSortIndices.TryDequeue(out var sortIndex)) + return sortIndex; + + _lastSortIndex++; + if (_lastSortIndex > _configuration.MaxPlayerCount) { - _lastSortIndex++; - if (_lastSortIndex > _configuration.MaxPlayerCount) - { - return 0; - } - return _lastSortIndex; + return 0; } + return _lastSortIndex; } public void ReleaseSortIndex(int sortIndex) { - lock (_releasedSortIndices_Lock) - { - _releasedSortIndices.Enqueue(sortIndex); - } + _releasedSortIndices.Enqueue(sortIndex); } public byte GetNextConnectionId() //ID 0 is server, ID 127 means send to all players { - lock (_releasedConnectionIds_Lock) - { - if (_releasedConnectionIds.TryDequeue(out var connectionId)) - return connectionId; - } - lock (_ConnectionIDLock) - { + if (_releasedConnectionIds.TryDequeue(out var connectionId)) + return connectionId; + + _connectionIdCount++; + if (_connectionIdCount == 127) _connectionIdCount++; - if (_connectionIdCount == 127) - _connectionIdCount++; - if (_connectionIdCount > (byte.MaxValue - 5)) //Currently not implimented to use ID's over 126 client side - return 255; //Give them an unusedID so they dont conflict with anyone - return _connectionIdCount; - } + if (_connectionIdCount > (byte.MaxValue - 5)) //Currently not implimented to use ID's over 126 client side + return 255; //Give them an unusedID so they dont conflict with anyone + return _connectionIdCount; } public void ReleaseConnectionId(byte connectionId) { - lock (_releasedConnectionIds_Lock) - { - _releasedConnectionIds.Enqueue(connectionId); - } + + _releasedConnectionIds.Enqueue(connectionId); } public void SetState(MultiplayerGameState state) @@ -273,7 +248,7 @@ public void SetState(MultiplayerGameState state) #region EnetCompat - public IPlayer? TryAcceptConnection(IPEndPoint endPoint, ref SpanBuffer Data) + public override IPlayer? TryAcceptConnection(IPEndPoint endPoint, ref SpanBuffer Data) { bool PlayerNoJoin = false; @@ -295,7 +270,7 @@ public void SetState(MultiplayerGameState state) _logger.Debug( "Handling connection request though Enet" + $"(RemoteEndPoint='{endPoint}', " + - $"Secret='{connectionRequestData.Secret}', " + + $"PlayerSessionId='{connectionRequestData.PlayerSessionId}', " + $"UserId='{connectionRequestData.UserId}', " + $"UserName='{connectionRequestData.UserName}', " ); @@ -313,17 +288,14 @@ public void SetState(MultiplayerGameState state) PlayerNoJoin = true; goto EndOfTryAccept; } - ConnectDisconnectSemaphore.Wait(); //Will fix joining issues, and although it will block any Enet recieving, hopefully its not that bad if (_playerRegistry.GetPlayerCount() >= _configuration.MaxPlayerCount) { - ConnectDisconnectSemaphore.Release(); _logger.Warning("Master server sent a player to a full server"); PlayerNoJoin = true; goto EndOfTryAccept; } if (connectionRequestData.UserName == "IGGAMES" || connectionRequestData.UserName == "IGGGAMES") { - ConnectDisconnectSemaphore.Release(); _logger.Information("an IGG player just tried joining after passing master auth"); PlayerNoJoin = true; goto EndOfTryAccept; @@ -335,7 +307,6 @@ public void SetState(MultiplayerGameState state) endPoint, this, connectionId, - _configuration.Secret, connectionRequestData.UserId, connectionRequestData.UserName, connectionRequestData.PlayerSessionId @@ -347,7 +318,6 @@ public void SetState(MultiplayerGameState state) { ReleaseSortIndex(player.SortIndex); ReleaseConnectionId(player.ConnectionId); - ConnectDisconnectSemaphore.Release(); PlayerNoJoin = true; goto EndOfTryAccept; } @@ -363,7 +333,7 @@ public void SetState(MultiplayerGameState state) "Player joined dedicated server " + $"(RemoteEndPoint='{player.Endpoint}', " + $"ConnectionId={player.ConnectionId}, " + - $"Secret='{player.Secret}', " + + $"PlayerSessionId='{player.PlayerSessionId}', " + $"UserId='{player.UserId}', " + $"UserName='{player.UserName}', " + $"SortIndex={player.SortIndex})." @@ -373,242 +343,73 @@ public void SetState(MultiplayerGameState state) _waitForPlayerCts.Cancel(); // Retrieve encryption params and platform data from handshake process by player session token, if provided - if (!string.IsNullOrEmpty(connectionRequestData.PlayerSessionId)) + //if (!string.IsNullOrEmpty(connectionRequestData.PlayerSessionId)) + //{ + //var handshakeSession = + // _handshakeSessionRegistry.TryGetByPlayerSessionId(connectionRequestData.PlayerSessionId); + //GetPlayerRegistry().RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out var ClientVer, out var Platform, out var PlayerPlatformUserId); + //player.ClientVersion = ClientVer; + //player.Platform = (Enums.Platform)Platform; + //player.PlatformUserId = PlayerPlatformUserId; + //if (handshakeSession != null && handshakeSession.EncryptionParameters != null) + //{ + // _packetEncryptionLayer.AddEncryptedEndPoint((IPEndPoint)endPoint, + // handshakeSession.EncryptionParameters, true); + //} + //} + if (GetPlayerRegistry().RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out var ClientVer, out var Platform, out var PlayerPlatformUserId)) { - var handshakeSession = - _handshakeSessionRegistry.TryGetByPlayerSessionId(connectionRequestData.PlayerSessionId); - _handshakeSessionRegistry.RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out var ClientVer, out var Platform, out var PlayerPlatformUserId); player.ClientVersion = ClientVer; player.Platform = (Enums.Platform)Platform; player.PlatformUserId = PlayerPlatformUserId; - if (handshakeSession != null && handshakeSession.EncryptionParameters != null) - { - _packetEncryptionLayer.AddEncryptedEndPoint((IPEndPoint)endPoint, - handshakeSession.EncryptionParameters, true); - } } - ConnectDisconnectSemaphore.Release(); - Task.Run(() => SendPlayerDataInBackgroundAsync(player)); - return player; - EndOfTryAccept: - if (PlayerNoJoin) - { - string[] Players = _playerRegistry.Players.Select(p => p.UserId).ToArray(); - PlayerDisconnectBeforeJoining?.Invoke(_configuration.Secret, endPoint, Players); - return null; - } - return null; - } - private async void SendPlayerDataInBackgroundAsync(IPlayer player) - { - await player.PlayerAccessSemaphore.WaitAsync(); - var SendToOtherPlayers = new INetSerializable[] - { - new PlayerConnectedPacket + PacketDispatcher.SendExcludingPlayer(player, new INetSerializable[]{ + new PlayerConnectedPacket { RemoteConnectionId = player.ConnectionId, UserId = player.UserId, UserName = player.UserName, IsConnectionOwner = false }, - new PlayerSortOrderPacket + new PlayerSortOrderPacket { UserId = player.UserId, SortIndex = player.SortIndex }, - new MpNodePoseSyncStatePacket + new MpNodePoseSyncStatePacket { fullStateUpdateFrequency = 100L, deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() }, - }; - player.PlayerAccessSemaphore.Release(); - - PacketDispatcher.SendExcludingPlayer(player, SendToOtherPlayers, DeliveryMethod.ReliableOrdered); - } - - #endregion - - - #region LiteNetServer + }, DeliveryMethod.ReliableOrdered); + return player; - public override async Task ShouldAcceptConnection(EndPoint endPoint, byte[] additionalData) - { - - if (await ShouldDenyConnection(endPoint, additionalData)) + EndOfTryAccept: + if (PlayerNoJoin) { + GetPlayerRegistry().RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out _, out _, out _); string[] Players = _playerRegistry.Players.Select(p => p.UserId).ToArray(); PlayerDisconnectBeforeJoining?.Invoke(_configuration.Secret, endPoint, Players); - return false; + return null; } - - return true; + return null; } - private bool GetConnectionData(byte[] additionalData, out ConnectionRequestData connectionRequestData) + public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, DeliveryMethod method) { - connectionRequestData = new(); - SpanBuffer spanBuffer = new(additionalData); - try - { - connectionRequestData.ReadFrom(ref spanBuffer); - } - catch(Exception ex) - { - _logger.Warning(ex + - "Failed to deserialize connection request data" - ); - return false; - } - return true; + ConnectedMessageSource.OnReceive(remoteEndPoint, ref reader, method); } + #endregion - public async Task ShouldDenyConnection(EndPoint endPoint, byte[] additionalData) - { - //var connectionRequestData = new ConnectionRequestData(); - if(!GetConnectionData(additionalData, out var connectionRequestData)) - { - _logger.Warning( - "Failed to deserialize connection request data " + - $"(RemoteEndPoint='{endPoint}')." - ); - return true; - } - _logger.Debug( - "Handling connection request " + - $"(RemoteEndPoint='{endPoint}', " + - $"Secret='{connectionRequestData.Secret}', " + - $"UserId='{connectionRequestData.UserId}', " + - $"UserName='{connectionRequestData.UserName}', " - ); - - if (string.IsNullOrEmpty(connectionRequestData.UserId) || - string.IsNullOrEmpty(connectionRequestData.UserName)) - { - _logger.Warning( - "Received a connection request with invalid data " + - $"(RemoteEndPoint='{endPoint}', " + - $"UserId='{connectionRequestData.UserId}', " + - $"UserName='{connectionRequestData.UserName}', " + - $"IsConnectionOwner={connectionRequestData.IsConnectionOwner})." - ); - return true; - } - await ConnectDisconnectSemaphore.WaitAsync(); - if (_playerRegistry.GetPlayerCount() >= _configuration.MaxPlayerCount) - { - ConnectDisconnectSemaphore.Release(); - _logger.Warning("Master server sent a player to a full server"); - return true; - } - if (connectionRequestData.UserName == "IGGAMES" || connectionRequestData.UserName == "IGGGAMES") - { - ConnectDisconnectSemaphore.Release(); - _logger.Information("an IGG player just tried joining after passing master auth"); - return true; - } - int sortIndex = GetNextSortIndex(); - byte connectionId = GetNextConnectionId(); - - var player = new Player( - endPoint, - this, - connectionId, - _configuration.Secret, - connectionRequestData.UserId, - connectionRequestData.UserName, - connectionRequestData.PlayerSessionId - ) - { - SortIndex = sortIndex - }; - if (!_playerRegistry.AddPlayer(player)) - { - ReleaseSortIndex(player.SortIndex); - ReleaseConnectionId(player.ConnectionId); - ConnectDisconnectSemaphore.Release(); - return true; - } - - if (_configuration.ServerName == string.Empty) - { - _logger.Information("About to update servers name" + _configuration.ServerName); - _configuration.ServerName = player.UserName + "'s server"; - InstanceConfigUpdated(); - _logger.Information("Updated servers name to: " + _configuration.ServerName); - } - _logger.Information( - "Player joined dedicated server " + - $"(RemoteEndPoint='{player.Endpoint}', " + - $"ConnectionId={player.ConnectionId}, " + - $"Secret='{player.Secret}', " + - $"UserId='{player.UserId}', " + - $"UserName='{player.UserName}', " + - $"SortIndex={player.SortIndex})." - ); - - if (_waitForPlayerCts != null) - _waitForPlayerCts.Cancel(); - - // Retrieve encryption params and platform data from handshake process by player session token, if provided - if (!string.IsNullOrEmpty(connectionRequestData.PlayerSessionId)) - { - var handshakeSession = - _handshakeSessionRegistry.TryGetByPlayerSessionId(connectionRequestData.PlayerSessionId); - _handshakeSessionRegistry.RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out var ClientVer, out var Platform, out var PlayerPlatformUserId); - player.ClientVersion = ClientVer; - player.Platform = (Enums.Platform)Platform; - player.PlatformUserId = PlayerPlatformUserId; - if (handshakeSession != null && handshakeSession.EncryptionParameters != null) - { - _packetEncryptionLayer.AddEncryptedEndPoint((IPEndPoint)endPoint, - handshakeSession.EncryptionParameters, true); - } - } - - ConnectDisconnectSemaphore.Release(); - //Send to all other players that they have connected, so that they can recieve the routed avatar packet - await player.PlayerAccessSemaphore.WaitAsync(); - var SendToOtherPlayers = new INetSerializable[] - { - new PlayerConnectedPacket - { - RemoteConnectionId = player.ConnectionId, - UserId = player.UserId, - UserName = player.UserName, - IsConnectionOwner = false - }, - new PlayerSortOrderPacket - { - UserId = player.UserId, - SortIndex = player.SortIndex - }, - new MpNodePoseSyncStatePacket - { - fullStateUpdateFrequency = 100L, - deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() - }, - }; - player.PlayerAccessSemaphore.Release(); - - _logger.Debug($"MpNodePoseSyncStatePacket check deltaUpdateFrequency {_playerRegistry.GetMillisBetweenSyncStatePackets()}"); - - PacketDispatcher.SendExcludingPlayer(player, SendToOtherPlayers, DeliveryMethod.ReliableOrdered); - - - return false; - } public override void OnLatencyUpdate(EndPoint endPoint, int latency) => _logger.Verbose($"Latency updated (RemoteEndPoint='{endPoint}', Latency={0.001f * latency})."); - - - public override async void OnConnect(EndPoint endPoint) + public override void OnConnect(EndPoint endPoint) { _logger.Information($"Endpoint connected (RemoteEndPoint='{endPoint}')"); @@ -618,7 +419,8 @@ public override async void OnConnect(EndPoint endPoint) "Failed to retrieve player " + $"(RemoteEndPoint='{endPoint}')." ); - Disconnect(endPoint); + //Disconnect(endPoint); + //TODO impliment for enet, enet peers cannot be located at this point as a peer ID is required to kick them return; } PlayerConnectedEvent?.Invoke(player); @@ -628,7 +430,6 @@ public override async void OnConnect(EndPoint endPoint) //Now send all players already in the game to the new player IPlayer[] PlayersAtJoin = _playerRegistry.Players; - await player.PlayerAccessSemaphore.WaitAsync(); var Player_ConnectPacket = new INetSerializable[] { new SyncTimePacket @@ -657,16 +458,14 @@ public override async void OnConnect(EndPoint endPoint) deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() }, }; - player.PlayerAccessSemaphore.Release(); - await PacketDispatcher.SendToPlayerAndAwait(player, Player_ConnectPacket, DeliveryMethod.ReliableOrdered); + PacketDispatcher.SendToPlayer(player, Player_ConnectPacket, DeliveryMethod.ReliableOrdered); List MakeBigPacketToSendToPlayer = new(); foreach (IPlayer p in PlayersAtJoin) { if(p.ConnectionId != player.ConnectionId) { - await p.PlayerAccessSemaphore.WaitAsync(); MakeBigPacketToSendToPlayer.Add(new PlayerConnectedPacket { RemoteConnectionId = p.ConnectionId, @@ -679,12 +478,11 @@ public override async void OnConnect(EndPoint endPoint) UserId = p.UserId, SortIndex = p.SortIndex }); - p.PlayerAccessSemaphore.Release(); } } foreach (var SubPacket in MakeBigPacketToSendToPlayer.Chunk(20)) { - await PacketDispatcher.SendToPlayerAndAwait(player, SubPacket.ToArray(), DeliveryMethod.ReliableOrdered); + PacketDispatcher.SendToPlayer(player, SubPacket.ToArray(), DeliveryMethod.ReliableOrdered); } //End of sending other players to player @@ -713,7 +511,7 @@ public override async void OnConnect(EndPoint endPoint) }, DeliveryMethod.ReliableOrdered); } - if (player.Platform == Kernel.Enums.Platform.Test) //If the player is a bot, send permissions. Normal players request this in a packet when they join + if (player.Platform == Enums.Platform.Test) //If the player is a bot, send permissions. Normal players request this in a packet when they join { bool HasManager = (_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var ServerOwner) && !player.IsServerOwner); PlayerPermissionConfiguration[] playerPermissionConfigurations = new PlayerPermissionConfiguration[HasManager ? 2 : 1]; @@ -755,7 +553,6 @@ public override async void OnConnect(EndPoint endPoint) if (p.ConnectionId != player.ConnectionId) { // Send player to player data to new player - await p.PlayerAccessSemaphore.WaitAsync(); ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PlayerState = p.State; ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PlayerAvatar = p.Avatar; @@ -765,10 +562,9 @@ public override async void OnConnect(EndPoint endPoint) ((MpPlayerData)SendToPlayerFromPlayers[1]).Platform = p.Platform.Convert(); ((MpPlayerData)SendToPlayerFromPlayers[1]).ClientVersion = p.ClientVersion; - p.PlayerAccessSemaphore.Release(); // Send all player avatars and states to just joined player - await Task.WhenAny(PacketDispatcher.SendFromPlayerToPlayerAndAwait(p, player, SendToPlayerFromPlayers, DeliveryMethod.ReliableOrdered), Task.Delay(50)); + PacketDispatcher.SendFromPlayerToPlayer(p, player, SendToPlayerFromPlayers, DeliveryMethod.ReliableOrdered); //Sends them one by one to avoid server lag } } @@ -778,30 +574,26 @@ public override async void OnConnect(EndPoint endPoint) { if (p.ConnectionId != player.ConnectionId) { - await Task.WhenAny( - PacketDispatcher.SendFromPlayerToPlayerAndAwait(player, p, new MpPlayerData + PacketDispatcher.SendFromPlayerToPlayer(player, p, new MpPlayerData { PlatformID = player.PlatformUserId!, Platform = player.Platform.Convert(), ClientVersion = player.ClientVersion! - }, DeliveryMethod.ReliableOrdered), - Task.Delay(50)); + }, DeliveryMethod.ReliableOrdered); } } - await player.PlayerAccessSemaphore.WaitAsync(); var packet = new MpcTextChatPacket { Text = player.UserName + " Joined, Platform: " + player.Platform.ToString() + " Version: " + player.ClientVersion }; - player.PlayerAccessSemaphore.Release(); foreach (var p in PlayersAtJoin) { if (p.CanTextChat) { - await Task.WhenAny(PacketDispatcher.SendToPlayerAndAwait(p, packet, DeliveryMethod.ReliableOrdered), Task.Delay(50)); + PacketDispatcher.SendToPlayer(p, packet, DeliveryMethod.ReliableOrdered); } } } - public void DisconnectPlayer(string UserId) //Used my master servers kick player event + public void DisconnectPlayer(string UserId) //Used by master servers kick player event { if(_playerRegistry.TryGetPlayer(UserId, out var player)) @@ -811,7 +603,7 @@ public void DisconnectPlayer(string UserId) //Used my master servers kick player }, DeliveryMethod.ReliableOrdered); } - public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reason) + public override void OnDisconnect(EndPoint endPoint, DisconnectReason reason) { _logger.Information( "Endpoint disconnected " + @@ -825,7 +617,6 @@ public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reas ); return; } - await ConnectDisconnectSemaphore.WaitAsync(); if (_playerRegistry.TryGetPlayer(endPoint, out var player)) { //Sends to all players that they have disconnected @@ -844,7 +635,6 @@ public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reas PlayerDisconnectedEvent?.Invoke(player); } - ConnectDisconnectSemaphore.Release(); if (_playerRegistry.GetPlayerCount() != 0 && string.IsNullOrEmpty(_configuration.ServerOwnerId) && _configuration.GameplayServerMode == GameplayServerMode.Managed) { @@ -907,7 +697,6 @@ public override async void OnDisconnect(EndPoint endPoint, DisconnectReason reas } } } - #endregion #region Private Methods diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs index 9956726b..1c7c2a6d 100644 --- a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs @@ -8,8 +8,10 @@ using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Ignorance.Util; using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Enums; using BeatTogether.LiteNetLib.Extensions; +using BeatTogether.LiteNetLib.Sources; using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; using Serilog; @@ -21,9 +23,7 @@ namespace BeatTogether.DedicatedServer.Kernel.ENet /// public class ENetServer : IDisposable { - public readonly DedicatedInstance DedicatedInstance; - public readonly int Port; - + private readonly int Port; private readonly IgnoranceServer _ignorance; private readonly ILogger _logger; private CancellationTokenSource _runtimeCts; @@ -35,9 +35,8 @@ public class ENetServer : IDisposable public IPEndPoint EndPoint => new(IPAddress.Any, Port); public bool IsAlive => _ignorance.IsAlive; - public ENetServer(DedicatedInstance dedicatedInstance, int port) + public ENetServer(int port) { - DedicatedInstance = dedicatedInstance; Port = port; _ignorance = new IgnoranceServer(); @@ -159,7 +158,7 @@ private void HandleIncomingEvents() } // Process actual payload var deliveryMethod = e.Channel == 0 ? DeliveryMethod.ReliableOrdered : DeliveryMethod.Unreliable; - DedicatedInstance.ConnectedMessageSource.OnReceive(connection.EndPoint, ref bufferReader, deliveryMethod); + OnReceive(connection.EndPoint, ref bufferReader, deliveryMethod); } } @@ -194,14 +193,15 @@ private bool TryAcceptConnection(ENetConnection connection, ref SpanBuffer reade } // Continue with regular accept flow (remainder is regular GameLift connection request) - var player = DedicatedInstance.TryAcceptConnection(connection.EndPoint, ref reader); + var player = TryAcceptConnection(connection.EndPoint, ref reader); + if (player != null) { // Accept success player.ENetPeerId = connection.NativePeerId; connection.State = ENetConnectionState.Accepted; - DedicatedInstance.OnConnect(connection.EndPoint); + OnConnect(connection.EndPoint); return true; } } @@ -224,7 +224,7 @@ public void KickPeer(uint peerId, bool sendKick = true) connection.NativePeerId, connection.EndPoint); connection.State = ENetConnectionState.Disconnected; - DedicatedInstance.OnDisconnect(connection.EndPoint, DisconnectReason.DisconnectPeerCalled); + OnDisconnect(connection.EndPoint, DisconnectReason.DisconnectPeerCalled); if (!IsAlive || !sendKick) // Can't or won't send kick @@ -312,5 +312,39 @@ private void ReturnReceiveBuffer() } #endregion + + + + #region Overrideables + public virtual IPlayer? TryAcceptConnection(IPEndPoint endPoint, ref SpanBuffer reader) + { + return null; + } + + public virtual void OnConnect(EndPoint endPoint) + { + } + + public virtual void OnDisconnect(EndPoint endPoint, DisconnectReason reason) + { + } + + public virtual void OnLatencyUpdate(EndPoint endPoint, int latency) + { + } + + public virtual void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, DeliveryMethod method) + { + } + +/* public virtual void SendAsync(EndPoint endPoint, INetSerializable packet) + { + Span buffer = stackalloc byte[412]; + SpanBuffer bufferWriter = new SpanBuffer(buffer); + packet.WriteTo(ref bufferWriter); + SendAsync(endPoint, new Memory(bufferWriter.Data.ToArray())); + }*/ + + #endregion } } \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs b/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs index 6d897509..7836f1da 100644 --- a/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs +++ b/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs @@ -1,29 +1,24 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; namespace BeatTogether.DedicatedServer.Kernel.Extensions { public static class GamePlatformToMpCorePlatform { - public static Platform Convert(this Kernel.Enums.Platform gamePlatform) + public static Platform Convert(this Enums.Platform gamePlatform) { switch (gamePlatform) { - case Kernel.Enums.Platform.Test: + case Enums.Platform.Test: return Platform.Unknown; - case Kernel.Enums.Platform.OculusRift: + case Enums.Platform.OculusRift: return Platform.OculusPC; - case Kernel.Enums.Platform.OculusQuest: + case Enums.Platform.OculusQuest: return Platform.OculusQuest; - case Kernel.Enums.Platform.Steam: + case Enums.Platform.Steam: return Platform.Steam; - case Kernel.Enums.Platform.PS4: - case Kernel.Enums.Platform.PS4Dev: - case Kernel.Enums.Platform.PS4Cert: + case Enums.Platform.PS4: + case Enums.Platform.PS4Dev: + case Enums.Platform.PS4Cert: return Platform.PS4; default: return 0; diff --git a/BeatTogether.DedicatedServer.Kernel/Extensions/HostBuilderExtensions.cs b/BeatTogether.DedicatedServer.Kernel/Extensions/HostBuilderExtensions.cs index b5c5680d..bd28ed0c 100644 --- a/BeatTogether.DedicatedServer.Kernel/Extensions/HostBuilderExtensions.cs +++ b/BeatTogether.DedicatedServer.Kernel/Extensions/HostBuilderExtensions.cs @@ -1,20 +1,21 @@ -using BeatTogether.Core.Messaging.Abstractions; +//using BeatTogether.Core.Messaging.Abstractions; using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers; +//using BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; -using BeatTogether.DedicatedServer.Kernel.Handshake; +using BeatTogether.DedicatedServer.Kernel.ENet; +//using BeatTogether.DedicatedServer.Kernel.Handshake; using BeatTogether.DedicatedServer.Kernel.Managers; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MPChat; -using BeatTogether.DedicatedServer.Messaging.Registries; -using BeatTogether.DedicatedServer.Messaging.Registries.Unconnected; +//using BeatTogether.DedicatedServer.Messaging.Registries; +//using BeatTogether.DedicatedServer.Messaging.Registries.Unconnected; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib; +/*using BeatTogether.LiteNetLib; using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Configuration; using BeatTogether.LiteNetLib.Dispatchers; using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Sources; +using BeatTogether.LiteNetLib.Sources;*/ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -28,31 +29,31 @@ public static IHostBuilder UseDedicatedInstances(this IHostBuilder hostBuilder) .UseSerilog() .ConfigureServices((hostBuilderContext, services) => services - .AddLiteNetMessaging() - .AddConfiguration("LiteNetLib") + //.AddLiteNetMessaging() + //.AddConfiguration("LiteNetLib") .AddScoped() .AddDedicatedServerMessaging() .AddScoped() .AddExisting() - .AddExisting() - .AddScoped() + .AddExisting() + //.AddScoped() .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() - .AddExisting() - .AddExisting() + //.AddScoped() + .AddScoped() + //.AddScoped() + //.AddExisting() + //.AddExisting() .AddScoped() .AddExisting() - .AddExisting() - .AddScoped() + //.AddExisting() + //.AddScoped() .AddScoped() .AddScoped() - .AddCoreMessaging() + //.AddCoreMessaging() .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddAllHandshakeMessageHandlersFromAssembly(typeof(UnconnectedSource).Assembly) + //.AddSingleton() + //.AddSingleton() + //.AddAllHandshakeMessageHandlersFromAssembly(typeof(UnconnectedSource).Assembly) .AddAllPacketHandlersFromAssembly(typeof(PacketSource).Assembly) .AddAllCommandHandlersFromAssembly(typeof(MpcTextChatPacketHandler).Assembly) ); diff --git a/BeatTogether.DedicatedServer.Kernel/Extensions/ServiceCollectionExtensions.cs b/BeatTogether.DedicatedServer.Kernel/Extensions/ServiceCollectionExtensions.cs index 20ab0b9f..2e8f38be 100644 --- a/BeatTogether.DedicatedServer.Kernel/Extensions/ServiceCollectionExtensions.cs +++ b/BeatTogether.DedicatedServer.Kernel/Extensions/ServiceCollectionExtensions.cs @@ -41,7 +41,7 @@ public static IServiceCollection AddAllCommandHandlersFromAssembly(this IService return services; } - public static IServiceCollection AddAllHandshakeMessageHandlersFromAssembly(this IServiceCollection services, Assembly assembly) +/* public static IServiceCollection AddAllHandshakeMessageHandlersFromAssembly(this IServiceCollection services, Assembly assembly) { var genericInterface = typeof(IHandshakeMessageHandler<>); var eventHandlerTypes = assembly @@ -53,6 +53,6 @@ public static IServiceCollection AddAllHandshakeMessageHandlersFromAssembly(this genericInterface.MakeGenericType(eventHandlerType.BaseType!.GetGenericArguments()), eventHandlerType); return services; - } + }*/ } } diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakePendingMultipart.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakePendingMultipart.cs deleted file mode 100644 index e2ad249b..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakePendingMultipart.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using BeatTogether.Core.Messaging.Messages; -using Krypton.Buffers; - -namespace BeatTogether.DedicatedServer.Kernel.Handshake -{ - public class HandshakePendingMultipart - { - public UnconnectedSource UnconnectedSource { get; private set; } - public HandshakeSession Session { get; private set; } - public uint MultipartMessageId { get; private set; } - public uint TotalLength { get; private set; } - public DateTime LastReceive { get; private set; } - - private readonly ConcurrentDictionary _messages; - private uint _receivedLength; - - public bool IsComplete { get; private set; } - - public HandshakePendingMultipart(UnconnectedSource unconnectedSource, HandshakeSession session, - uint multipartMessageId, uint totalLength) - { - UnconnectedSource = unconnectedSource; - Session = session; - MultipartMessageId = multipartMessageId; - TotalLength = totalLength; - LastReceive = DateTime.Now; - - _messages = new(); - _receivedLength = 0; - } - - public void AddMessage(MultipartMessage message) - { - if (message.MultipartMessageId != MultipartMessageId) - // Invalid id - return; - - if (_receivedLength >= TotalLength) - // Already received all messages - return; - - if (!_messages.TryAdd(message.Offset, message)) - // Already received this message - return; - - // Receive success - LastReceive = DateTime.Now; - - if (Interlocked.Add(ref _receivedLength, message.Length) < TotalLength) - // Not yet complete, wait for all messages to come in - return; - - FinalizeMessage(); - } - - private void FinalizeMessage() - { - if (IsComplete) - return; - - IsComplete = true; - - var bufferWriter = new SpanBufferWriter(stackalloc byte[(int)TotalLength]); - - foreach (var kvp in _messages.OrderBy(kvp => kvp.Key)) - bufferWriter.WriteBytes(kvp.Value.Data); - - var bufferReader = new SpanBufferReader(bufferWriter.Data); - var fullMessage = UnconnectedSource.GetMessageReader().ReadFrom(ref bufferReader); - - Task.Run(() => UnconnectedSource.HandleMessage(Session, fullMessage)); - } - - public double MsSinceLastReceive => DateTime.Now.Subtract(LastReceive).TotalMilliseconds; - - public bool HasExpired => MsSinceLastReceive > 10000; - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakePendingRequest.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakePendingRequest.cs deleted file mode 100644 index d5b15e4f..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakePendingRequest.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Abstractions; - -namespace BeatTogether.DedicatedServer.Kernel.Handshake -{ - public class HandshakePendingRequest - { - public IUnconnectedDispatcher UnconnectedDispatcher { get; private set; } - public HandshakeSession Session { get; private set; } - public IReliableRequest Request { get; private set; } - public DateTime LastSend { get; private set; } - public int RetryCount { get; private set; } - - public uint RequestId => Request.RequestId; - - public HandshakePendingRequest(IUnconnectedDispatcher unconnectedDispatcher, HandshakeSession session, - IReliableRequest request) - { - UnconnectedDispatcher = unconnectedDispatcher; - Session = session; - Request = request; - LastSend = DateTime.Now; - RetryCount = 0; - } - - - public void Retry() - { - UnconnectedDispatcher.Send(Session, Request, true); - LastSend = DateTime.Now; - RetryCount++; - } - - public int? GetRetryInterval() - { - switch (RetryCount) - { - case 0: - return 200; - case 1: - return 300; - case 2: - return 450; - case 3: - return 600; - case 4: - return 1000; - default: - return null; - } - } - - public double MsSinceLastSend => DateTime.Now.Subtract(LastSend).TotalMilliseconds; - - public bool HasExpired => GetRetryInterval() == null; - - public bool ShouldRetry - { - get - { - var interval = GetRetryInterval(); - return interval.HasValue && MsSinceLastSend >= interval; - } - } - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeService.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeService.cs deleted file mode 100644 index 0f1891c0..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeService.cs +++ /dev/null @@ -1,249 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Threading.Tasks; -using BeatTogether.Core.Security.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Messaging.Messages.GameLift; -using BeatTogether.DedicatedServer.Messaging.Messages.Handshake; -using Krypton.Buffers; -using Serilog; - -namespace BeatTogether.DedicatedServer.Kernel.Handshake -{ - public class HandshakeService : IHandshakeService - { - private readonly IUnconnectedDispatcher _messageDispatcher; - private readonly ICookieProvider _cookieProvider; - private readonly IRandomProvider _randomProvider; - private readonly X509Certificate2 _certificate; - private readonly ICertificateSigningService _certificateSigningService; - private readonly IDiffieHellmanService _diffieHellmanService; - private readonly IHandshakeSessionRegistry _handshakeSessionRegistry; - - private readonly ILogger _logger; - - private static readonly byte[] MasterSecretSeed = Encoding.UTF8.GetBytes("master secret"); - private static readonly byte[] KeyExpansionSeed = Encoding.UTF8.GetBytes("key expansion"); - private const uint EpochMask = 0xff000000; - - public HandshakeService( - IUnconnectedDispatcher messageDispatcher, - ICookieProvider cookieProvider, - IRandomProvider randomProvider, - X509Certificate2 certificate, - ICertificateSigningService certificateSigningService, - IDiffieHellmanService diffieHellmanService, - IHandshakeSessionRegistry handshakeSessionRegistry) - { - _messageDispatcher = messageDispatcher; - _cookieProvider = cookieProvider; - _randomProvider = randomProvider; - _certificate = certificate; - _certificateSigningService = certificateSigningService; - _diffieHellmanService = diffieHellmanService; - _handshakeSessionRegistry = handshakeSessionRegistry; - - _logger = Log.ForContext(); - } - - #region Public Methods - - public Task ClientHello(HandshakeSession session, ClientHelloRequest request) - { - _logger.Verbose( - $"Handling {nameof(ClientHelloRequest)} " + - $"(Random='{BitConverter.ToString(request.Random)}')." - ); - - session.Epoch = request.RequestId & EpochMask; - session.EncryptionParameters = null; - session.Cookie = _cookieProvider.GetCookie(); - session.ClientRandom = request.Random; - - return Task.FromResult(new HelloVerifyRequest - { - Cookie = session.Cookie - }); - } - - public async Task ClientHelloWithCookie(HandshakeSession session, - ClientHelloWithCookieRequest request) - { - _logger.Verbose( - $"Handling {nameof(ClientHelloWithCookieRequest)} " + - $"(CertificateResponseId={request.CertificateResponseId}, " + - $"Random='{BitConverter.ToString(request.Random)}', " + - $"Cookie='{BitConverter.ToString(request.Cookie)}')." - ); - - if (!request.Cookie.SequenceEqual(session.Cookie)) - { - _logger.Warning( - $"Session sent {nameof(ClientHelloWithCookieRequest)} with a mismatching cookie " + - $"(EndPoint='{session.EndPoint}', " + - $"Cookie='{BitConverter.ToString(request.Cookie)}', " + - $"Expected='{BitConverter.ToString(session.Cookie ?? new byte[0])}')." - ); - return null; - } - - if (!request.Random.SequenceEqual(session.ClientRandom)) - { - _logger.Warning( - $"Session sent {nameof(ClientHelloWithCookieRequest)} with a mismatching client random " + - $"(EndPoint='{session.EndPoint}', " + - $"Random='{BitConverter.ToString(request.Random)}', " + - $"Expected='{BitConverter.ToString(session.ClientRandom ?? new byte[0])}')." - ); - return null; - } - - // Generate a server random - session.ServerRandom = _randomProvider.GetRandom(); - - // Generate a key pair - var keyPair = _diffieHellmanService.GetECKeyPair(); - session.ServerPrivateKeyParameters = keyPair.PrivateKeyParameters; - - // Generate a signature - var signature = MakeSignature(session.ClientRandom, session.ServerRandom, keyPair.PublicKey); - - _messageDispatcher.Send(session, new ServerCertificateRequest() - { - ResponseId = request.CertificateResponseId, - Certificates = new List() {_certificate.RawData} - }); - - return new ServerHelloRequest - { - Random = session.ServerRandom, - PublicKey = keyPair.PublicKey, - Signature = signature - }; - } - - public Task ClientKeyExchange(HandshakeSession session, - ClientKeyExchangeRequest request) - { - _logger.Verbose( - $"Handling {nameof(ClientKeyExchange)} " + - $"(ClientPublicKey='{BitConverter.ToString(request.ClientPublicKey)}')." - ); - - session.ClientPublicKey = request.ClientPublicKey; - session.ClientPublicKeyParameters = _diffieHellmanService.DeserializeECPublicKey(request.ClientPublicKey); - session.PreMasterSecret = _diffieHellmanService.GetPreMasterSecret( - session.ClientPublicKeyParameters, - session.ServerPrivateKeyParameters! - ); - - - var sendKey = new byte[32]; - var receiveKey = new byte[32]; - var sendMacSourceArray = new byte[64]; - var receiveMacSourceArray = new byte[64]; - var masterSecretSeed = MakeSeed(MasterSecretSeed, session.ServerRandom!, session.ClientRandom!); - var keyExpansionSeed = MakeSeed(KeyExpansionSeed, session.ServerRandom!, session.ClientRandom!); - var sourceArray = PRF( - PRF(session.PreMasterSecret, masterSecretSeed, 48), - keyExpansionSeed, - 192 - ); - Array.Copy(sourceArray, 0, sendKey, 0, 32); - Array.Copy(sourceArray, 32, receiveKey, 0, 32); - Array.Copy(sourceArray, 64, sendMacSourceArray, 0, 64); - Array.Copy(sourceArray, 128, receiveMacSourceArray, 0, 64); - session.EncryptionParameters = new BeatTogether.Core.Messaging.Models.EncryptionParameters( - receiveKey, - sendKey, - new HMACSHA256(receiveMacSourceArray), - new HMACSHA256(sendMacSourceArray) - ); - - return Task.FromResult(new ChangeCipherSpecRequest()); - } - - public Task AuthenticateGameLiftUser(HandshakeSession session, - AuthenticateGameLiftUserRequest request) - { - if (!_handshakeSessionRegistry.TryRemovePendingPlayerSessionId(request.PlayerSessionId)) - { - // Not a pending player session ID, auth failure - _logger.Warning("Bad session token, GameLift auth failed " + - "(EndPoint={EndPoint}, PlayerSessionId={PlayerSessionId})", - session.EndPoint.ToString(), request.PlayerSessionId); - - return Task.FromResult(new AuthenticateGameLiftUserResponse() - { - Result = AuthenticateUserResult.Failed - }); - } - - // Auth success - session.PlayerSessionId = request.PlayerSessionId; - session.UserId = request.UserId; - session.UserName = request.UserName; - - _logger.Information("GameLift user authenticated (EndPoint={EndPoint}, UserId={UserId}, " + - "UserName={UserName}, PlayerSessionId={PlayerSessionId})", - session.EndPoint.ToString(), request.UserId, request.UserName, request.PlayerSessionId); - - return Task.FromResult(new AuthenticateGameLiftUserResponse() - { - Result = AuthenticateUserResult.Success - }); - } - - #endregion - - #region Hash utils - - private byte[] MakeSignature(byte[] clientRandom, byte[] serverRandom, byte[] publicKey) - { - var bufferWriter = new SpanBufferWriter(stackalloc byte[512]); - bufferWriter.WriteBytes(clientRandom); - bufferWriter.WriteBytes(serverRandom); - bufferWriter.WriteBytes(publicKey); - return _certificateSigningService.Sign(bufferWriter.Data.ToArray()); - } - - private byte[] MakeSeed(byte[] baseSeed, byte[] serverSeed, byte[] clientSeed) - { - var seed = new byte[baseSeed.Length + serverSeed.Length + clientSeed.Length]; - Array.Copy(baseSeed, 0, seed, 0, baseSeed.Length); - Array.Copy(serverSeed, 0, seed, baseSeed.Length, serverSeed.Length); - Array.Copy(clientSeed, 0, seed, baseSeed.Length + serverSeed.Length, clientSeed.Length); - return seed; - } - - private byte[] PRF(byte[] key, byte[] seed, int length) - { - var i = 0; - var array = new byte[length + seed.Length]; - while (i < length) - { - Array.Copy(seed, 0, array, i, seed.Length); - PRFHash(key, array, ref i); - } - - var array2 = new byte[length]; - Array.Copy(array, 0, array2, 0, length); - return array2; - } - - private void PRFHash(byte[] key, byte[] seed, ref int length) - { - using var hmacsha256 = new HMACSHA256(key); - var array = hmacsha256.ComputeHash(seed, 0, length); - var num = Math.Min(length + array.Length, seed.Length); - Array.Copy(array, 0, seed, length, num - length); - length = num; - } - - #endregion - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeSession.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeSession.cs deleted file mode 100644 index b812b4c3..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeSession.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Net; -using BeatTogether.Core.Messaging.Implementations; -using Org.BouncyCastle.Crypto.Parameters; - -namespace BeatTogether.DedicatedServer.Kernel.Handshake -{ - public enum HandshakeSessionState - { - None = 0, - New = 1, - Established = 2, - Authenticated = 3 - } - - public class HandshakeSession : BaseSession - { - - public byte[] Cookie { get; set; } - public byte[] ClientRandom { get; set; } - public byte[] ServerRandom { get; set; } - public byte[] ClientPublicKey { get; set; } - public ECPublicKeyParameters ClientPublicKeyParameters { get; set; } - public ECPrivateKeyParameters ServerPrivateKeyParameters { get; set; } - public byte[] PreMasterSecret { get; set; } - public DateTimeOffset LastKeepAlive { get; set; } - - public string? UserId { get; set; } = null; - public string? UserName { get; set; } = null; - public string? PlayerSessionId { get; set; } = null; - - public ConcurrentDictionary PendingRequests; - public ConcurrentDictionary PendingMultiparts; - - public HandshakeSession(EndPoint endPoint) : base(endPoint) - { - PendingRequests = new(); - PendingMultiparts = new(); - } - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeSessionRegistry.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeSessionRegistry.cs deleted file mode 100644 index f9550772..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/HandshakeSessionRegistry.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Collections.Concurrent; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Net; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using Serilog; - -namespace BeatTogether.DedicatedServer.Kernel.Handshake -{ - public class HandshakeSessionRegistry : IHandshakeSessionRegistry - { - private readonly ConcurrentDictionary _sessions; - private readonly ConcurrentDictionary _pendingPlayerSessionIds; - private readonly ConcurrentDictionary _pendingPlayerSessionData; - - private readonly ILogger _logger; - - public HandshakeSessionRegistry() - { - _sessions = new(); - _pendingPlayerSessionIds = new(); - _pendingPlayerSessionData = new(); - - _logger = Log.ForContext(); - } - - public HandshakeSession GetOrAdd(EndPoint endPoint) - { - return _sessions.GetOrAdd(endPoint, (ep) => new HandshakeSession(ep)); - } - - public HandshakeSession? TryGetByPlayerSessionId(string playerSessionId) - { - return (from s in _sessions - where s.Value.PlayerSessionId == playerSessionId - select s.Value).FirstOrDefault(); - } - - public void AddPendingPlayerSessionId(string playerSessionId) - { - _pendingPlayerSessionIds[playerSessionId] = true; - } - public void AddExtraPlayerSessionData(string playerSessionId, string ClientVersion, byte PlatformId, string PlayerPlatformUserId) - { - _pendingPlayerSessionData[playerSessionId] = (ClientVersion, PlatformId, PlayerPlatformUserId); - } - - public void RemoveExtraPlayerSessionData(string playerSessionId, out string ClientVersion, out byte Platform, out string PlayerPlatformUserId) - { - if(_pendingPlayerSessionData.TryRemove(playerSessionId, out var Values)) - { - ClientVersion = Values.Item1; - Platform = Values.Item2; - PlayerPlatformUserId = Values.Item3; - return; - } - ClientVersion = "ERROR"; - Platform = 0; - PlayerPlatformUserId = "ERROR"; - } - - public bool TryRemovePendingPlayerSessionId(string playerSessionId) - { - return _pendingPlayerSessionIds.TryRemove(playerSessionId, out _); - } - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs deleted file mode 100644 index c8de1b98..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedDispatcher.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Encryption; -using BeatTogether.DedicatedServer.Messaging.Messages.Handshake; -using BeatTogether.LiteNetLib; -using BeatTogether.LiteNetLib.Dispatchers; -using BeatTogether.LiteNetLib.Enums; -using Krypton.Buffers; -using Serilog; - -namespace BeatTogether.DedicatedServer.Kernel.Handshake -{ - public class UnconnectedDispatcher : UnconnectedMessageDispatcher, IUnconnectedDispatcher, IDisposable - { - private readonly IDedicatedInstance _instance; - private readonly IMessageWriter _messageWriter; - private readonly PacketEncryptionLayer _packetEncryptionLayer; - - private readonly ConcurrentDictionary _activeSessions; - private readonly CancellationTokenSource _stopCts; - private readonly ILogger _logger; - - public UnconnectedDispatcher(LiteNetServer server, IDedicatedInstance instance, IMessageWriter messageWriter, - PacketEncryptionLayer packetEncryptionLayer) : base(server) - { - _instance = instance; - _messageWriter = messageWriter; - _packetEncryptionLayer = packetEncryptionLayer; - - _activeSessions = new(); - _stopCts = new(); - _logger = Log.ForContext(); - - Task.Run(() => UpdateLoop(_stopCts.Token)); - _instance.StopEvent += HandleInstanceStop; - } - - public void Dispose() - { - _instance.StopEvent -= HandleInstanceStop; - } - - private void HandleInstanceStop(IDedicatedInstance inst) => _stopCts.Cancel(); - - #region API - - public void Send(HandshakeSession session, IMessage message, bool retry = false) - { - _logger.Debug("Sending handshake message of type {MessageType} (EndPoint={EndPoint})", - message.GetType().Name, session.EndPoint.ToString()); - - // Assign request ID to outgoing requests - if (message is IRequest requestMessage && !retry) - { - requestMessage.RequestId = session.GetNextRequestId(); - } - - // Track reliable requests for retry - if (message is IReliableRequest reliableRequest) - { - if (!retry) - { - session.PendingRequests[reliableRequest.RequestId] = - new HandshakePendingRequest(this, session, reliableRequest); - _activeSessions.TryAdd(session.EndPoint, session); - } - } - - var bufferWriter = new SpanBufferWriter(stackalloc byte[412]); - _messageWriter.WriteTo(ref bufferWriter, message); - Send(session.EndPoint, bufferWriter, UnconnectedMessageType.BasicMessage); - } - - public bool Acknowledge(HandshakeSession session, uint responseId, bool handled = true) - { - var ackOk = session.PendingRequests.TryRemove(responseId, out var ackedRequest); - - if (ackOk && handled) - { - if (ackedRequest!.Request is ChangeCipherSpecRequest) - { - // The client acknowledged & handled the change cipher request - // We can now turn on the encryption layer - _packetEncryptionLayer.AddEncryptedEndPoint((IPEndPoint)session.EndPoint, - session.EncryptionParameters!); - } - } - - return ackOk; - } - - #endregion - - #region Update / Retry - - private async Task UpdateLoop(CancellationToken cancellationToken) - { - while (!cancellationToken.IsCancellationRequested) - { - foreach (var session in _activeSessions.Values) - { - var pendingInSession = session.PendingRequests.Values; - - if (pendingInSession.Count == 0) - { - // Nothing left to retry in session, remove from tracked list - _activeSessions.TryRemove(session.EndPoint, out _); - continue; - } - - foreach (var pendingRequest in pendingInSession) - { - if (pendingRequest.HasExpired) - { - // Max retries exceeded - session.PendingRequests.TryRemove(pendingRequest.RequestId, out _); - break; - } - - if (!pendingRequest.ShouldRetry) - { - // Waiting for retry interval - continue; - } - - pendingRequest.Retry(); - } - } - - await Task.Delay(100, cancellationToken); - } - } - - #endregion - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedSource.cs b/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedSource.cs deleted file mode 100644 index 6279821e..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Handshake/UnconnectedSource.cs +++ /dev/null @@ -1,194 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.Core.Messaging.Messages; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Encryption; -using BeatTogether.DedicatedServer.Messaging.Messages.Handshake; -using BeatTogether.LiteNetLib.Enums; -using BeatTogether.LiteNetLib.Sources; -using BeatTogether.LiteNetLib.Util; -using Krypton.Buffers; -using Serilog; - -namespace BeatTogether.DedicatedServer.Kernel.Handshake -{ - public class UnconnectedSource : UnconnectedMessageSource, IDisposable - { - private readonly IDedicatedInstance _instance; - private readonly IServiceProvider _serviceProvider; - private readonly IUnconnectedDispatcher _unconnectedDispatcher; - private readonly IMessageReader _messageReader; - private readonly IHandshakeSessionRegistry _handshakeSessionRegistry; - private readonly PacketEncryptionLayer _packetEncryptionLayer; - - private readonly ConcurrentDictionary _activeSessions; - private readonly CancellationTokenSource _stopCts; - private readonly ILogger _logger; - - public UnconnectedSource( - IDedicatedInstance instance, - IServiceProvider serviceProvider, - IUnconnectedDispatcher unconnectedDispatcher, - IMessageReader messageReader, - IHandshakeSessionRegistry handshakeSessionRegistry, - PacketEncryptionLayer packetEncryptionLayer) - { - _instance = instance; - _serviceProvider = serviceProvider; - _unconnectedDispatcher = unconnectedDispatcher; - _messageReader = messageReader; - _handshakeSessionRegistry = handshakeSessionRegistry; - _packetEncryptionLayer = packetEncryptionLayer; - - _activeSessions = new(); - _stopCts = new(); - _logger = Log.ForContext(); - - Task.Run(() => UpdateLoop(_stopCts.Token)); - _instance.StopEvent += HandleInstanceStop; - } - - public void Dispose() - { - _instance.StopEvent -= HandleInstanceStop; - } - - private void HandleInstanceStop(IDedicatedInstance inst) => _stopCts.Cancel(); - - public IMessageReader GetMessageReader() => _messageReader; - - #region Receive - - public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, - UnconnectedMessageType type) - { - - SpanBufferReader spanBufferReader = new(reader.RemainingData); - var session = _handshakeSessionRegistry.GetOrAdd(remoteEndPoint); - var message = _messageReader.ReadFrom(ref spanBufferReader); - - Task.Run(() => HandleMessage(session, message)); - - } - - public async Task HandleMessage(HandshakeSession session, IMessage message) - { - var messageType = message.GetType(); - if (message is ClientHelloRequest) - { - // Received client hello, first handshake message - ensure encryption is OFF for this endpoint - // This prevents outbound encryption with stale parameters from previous/incomplete handshake - _packetEncryptionLayer.RemoveEncryptedEndPoint((IPEndPoint)session.EndPoint); - } - - // Skip previously handled messages - if (message is IRequest request && !session.ShouldHandleRequest(request.RequestId)) - { - _logger.Warning("Skipping duplicate request (MessageType={Type}, RequestId={RequestId})", - messageType.Name, request.RequestId - ); - return; - } - - // Acknowledge reliable messages - uint requestId = 0; - - if (message is IReliableRequest reliableRequest) - { - requestId = reliableRequest.RequestId; - - _unconnectedDispatcher.Send(session, new AcknowledgeMessage() - { - ResponseId = requestId, - MessageHandled = true - }); - } - - // Dispatch to handler - _logger.Debug("Handling handshake message of type {MessageType} (EndPoint={EndPoint})", - messageType.Name, session.EndPoint.ToString()); - - if (message is MultipartMessage multipartMessage) - { - if (!session.PendingMultiparts.ContainsKey(multipartMessage.MultipartMessageId)) - { - session.PendingMultiparts.TryAdd(multipartMessage.MultipartMessageId, - new HandshakePendingMultipart(this, session, multipartMessage.MultipartMessageId, - multipartMessage.TotalLength)); - } - - session.PendingMultiparts[multipartMessage.MultipartMessageId].AddMessage(multipartMessage); - return; - } - - var targetHandlerType = typeof(IHandshakeMessageHandler<>).MakeGenericType(messageType); - var messageHandler = _serviceProvider.GetService(targetHandlerType); - - if (messageHandler is null) - { - _logger.Warning("No handler exists for handshake message {MessageType}", - messageType.Name); - return; - } - - try - { - var replyMessage = await ((IHandshakeMessageHandler) messageHandler).Handle(session, message); - - // Send response, if any - if (replyMessage == null) - return; - - if (replyMessage is IResponse responseMessage) - responseMessage.ResponseId = requestId; - - _unconnectedDispatcher.Send(session, replyMessage); - } - catch (Exception ex) - { - _logger.Error(ex, "Exception handling message {MessageType} (EndPoint={EndPoint})", - messageType.Name, session.EndPoint.ToString()); - } - } - - #endregion - - #region Update / Retry - - private async Task UpdateLoop(CancellationToken cancellationToken) - { - while (!cancellationToken.IsCancellationRequested) - { - foreach (var session in _activeSessions.Values) - { - var pendingInSession = session.PendingMultiparts.Values; - - if (pendingInSession.Count == 0) - { - // Nothing left pending in session, remove from tracked list - _activeSessions.TryRemove(session.EndPoint, out _); - continue; - } - - foreach (var pendingRequest in pendingInSession) - { - if (pendingRequest.HasExpired || pendingRequest.IsComplete) - { - // Clean up completed / expired - session.PendingMultiparts.TryRemove(pendingRequest.MultipartMessageId, out _); - break; - } - } - } - - await Task.Delay(1000, cancellationToken); - } - } - - #endregion - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 8ee8e93d..2ae0fffc 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -85,12 +85,7 @@ private async void UpdateLoop(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { - if (_instance.ConnectDisconnectSemaphore.CurrentCount > 0) - { - _instance.ConnectDisconnectSemaphore.Wait(); - Update(); - _instance.ConnectDisconnectSemaphore.Release(); - } + Update(); try { await Task.Delay(LoopTime, cancellationToken); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index d94b7687..f2d3c161 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -1,19 +1,14 @@ -using System; -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.Extensions; using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Configuration; -using BeatTogether.LiteNetLib.Dispatchers; using BeatTogether.LiteNetLib.Enums; using BeatTogether.LiteNetLib.Util; using Serilog; -using System.Net; -using System.Numerics; -using System.Threading.Tasks; +using BeatTogether.DedicatedServer.Kernel.ENet; namespace BeatTogether.DedicatedServer.Kernel { - public sealed class PacketDispatcher : ConnectedMessageDispatcher, IPacketDispatcher + public sealed class PacketDispatcher : /*ConnectedMessageDispatcher,*/ IPacketDispatcher { public const byte LocalConnectionId = 0; public const byte ServerId = 0; @@ -21,36 +16,23 @@ public sealed class PacketDispatcher : ConnectedMessageDispatcher, IPacketDispat private readonly IPacketRegistry _packetRegistry; private readonly IPlayerRegistry _playerRegistry; - private readonly DedicatedInstance _dedicatedInstance; + private readonly ENetServer _serverInstance; private readonly ILogger _logger = Log.ForContext(); public PacketDispatcher( IPacketRegistry packetRegistry, IPlayerRegistry playerRegistry, - LiteNetConfiguration configuration, - DedicatedInstance dedicatedInstance) - : base ( - configuration, - dedicatedInstance) + ENetServer serverInstance) { _packetRegistry = packetRegistry; _playerRegistry = playerRegistry; - _dedicatedInstance = dedicatedInstance; + _serverInstance = serverInstance; } private void SendInternal(IPlayer player, ref SpanBuffer writer, DeliveryMethod deliveryMethod) { - if (player.IsENetConnection) - { - // ENet send - _logger.Verbose($"Sending packet (SenderId={ServerId}) to player {player.ConnectionId} with UserId {player.UserId} via ENet"); - _dedicatedInstance.ENetServer.Send(player.ENetPeerId!.Value, writer.Data, deliveryMethod); - return; - } - - // LiteNet send - _logger.Verbose($"Sending packet (SenderId={ServerId}) to player {player.ConnectionId} with UserId {player.UserId} via LiteNet"); - Send(player.Endpoint, writer.Data, deliveryMethod); + _logger.Verbose($"Sending packet (SenderId={ServerId}) to player {player.ConnectionId} with UserId {player.UserId}"); + _serverInstance.Send(player, writer.Data, deliveryMethod); } #region Sends @@ -223,231 +205,7 @@ public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMet var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); - Send(player.Endpoint, writer.Data, deliveryMethod); - } - #endregion - - #region AwaitableSends - //Sends with a task that completes when the packet/s have been rec - public Task SendToNearbyPlayersAndAwait(INetSerializable packet, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending packet of type '{packet.GetType().Name}' " + - $"(SenderId={ServerId})" - ); - - var writer = new SpanBuffer(stackalloc byte[412]); - writer.WriteRoutingHeader(ServerId, LocalConnectionId); - WriteOne(ref writer, packet); - _logger.Verbose("Packet: " + packet.GetType().Name + " Was entered into the spanbuffer correctly, now sending once to each player"); - var players = _playerRegistry.Players; - Task[] tasks = new Task[players.Length]; - for (int i = 0; i < players.Length; i++) - { - if (players[i].IsENetConnection) - { - tasks[i] = Task.CompletedTask; - SendInternal(players[i], ref writer, deliveryMethod); - continue; - } - tasks[i] = Send(players[i].Endpoint, writer.Data, deliveryMethod); - } - return Task.WhenAll(tasks); - } - public Task SendToNearbyPlayersAndAwait(INetSerializable[] packets, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending MultiPacket " + - $"(SenderId={ServerId})" - ); - - var writer = new SpanBuffer(stackalloc byte[1024]); - writer.WriteRoutingHeader(ServerId, LocalConnectionId); - WriteMany(ref writer, packets); - _logger.Verbose("Packets were entered into the spanbuffer correctly, now sending once to each player"); - var players = _playerRegistry.Players; - Task[] tasks = new Task[players.Length]; - for (int i = 0; i < players.Length; i++) - { - if (players[i].IsENetConnection) - { - tasks[i] = Task.CompletedTask; - SendInternal(players[i], ref writer, deliveryMethod); - continue; - } - tasks[i] = Send(players[i].Endpoint, writer.Data, deliveryMethod); - } - return Task.WhenAll(tasks); - } - - public Task SendExcludingPlayerAndAwait(IPlayer excludedPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending packet of type '{packet.GetType().Name}' " + - $"(ExcludedId={excludedPlayer.ConnectionId})" - ); - - var writer = new SpanBuffer(stackalloc byte[412]); - writer.WriteRoutingHeader(ServerId, LocalConnectionId); - WriteOne(ref writer, packet); - - var players = _playerRegistry.Players; - Task[] tasks = new Task[players.Length - 1]; - int i = 0; - foreach (var player in players) - if (player.ConnectionId != excludedPlayer.ConnectionId) - { - if (!player.IsENetConnection) - { - tasks[i] = Send(player.Endpoint, writer.Data, deliveryMethod); - } - else - { - tasks[i] = Task.CompletedTask; - SendInternal(player, ref writer, deliveryMethod); - } - i++; - } - return Task.WhenAll(tasks); - } - public Task SendExcludingPlayerAndAwait(IPlayer excludedPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending MultiPacket " + - $"(ExcludedId={excludedPlayer.ConnectionId})" - ); - - var writer = new SpanBuffer(stackalloc byte[1024]); - writer.WriteRoutingHeader(ServerId, LocalConnectionId); - WriteMany(ref writer, packets); - var players = _playerRegistry.Players; - Task[] tasks = new Task[players.Length-1]; - int i = 0; - foreach (var player in players) - if (player.ConnectionId != excludedPlayer.ConnectionId) - { - if (!player.IsENetConnection) - { - tasks[i] = Send(player.Endpoint, writer.Data, deliveryMethod); - } - else - { - tasks[i] = Task.CompletedTask; - SendInternal(player, ref writer, deliveryMethod); - } - i++; - } - return Task.WhenAll(tasks); - } - - public Task SendFromPlayerAndAwait(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending packet of type '{packet.GetType().Name}' " + - $"(SenderId={fromPlayer.ConnectionId})" - ); - - var writer = new SpanBuffer(stackalloc byte[412]); - writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); - WriteOne(ref writer, packet); - var players = _playerRegistry.Players; - Task[] tasks = new Task[players.Length]; - for (int i = 0; i < players.Length; i++) - { - if (players[i].IsENetConnection) - { - tasks[i] = Task.CompletedTask; - SendInternal(players[i], ref writer, deliveryMethod); - continue; - } - tasks[i] = Send(players[i].Endpoint, writer.Data, deliveryMethod); - } - return Task.WhenAll(tasks); - } - public Task SendFromPlayerAndAwait(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending MultiPacket " + - $"(SenderId={fromPlayer.ConnectionId})" - ); - - var writer = new SpanBuffer(stackalloc byte[1024]); - writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); - WriteMany(ref writer, packets); - - foreach (var player in _playerRegistry.Players) - SendInternal(player, ref writer, deliveryMethod); - var players = _playerRegistry.Players; - Task[] tasks = new Task[players.Length]; - for (int i = 0; i < players.Length; i++) - { - if (players[i].IsENetConnection) - { - tasks[i] = Task.CompletedTask; - SendInternal(players[i], ref writer, deliveryMethod); - continue; - } - tasks[i] = Send(players[i].Endpoint, writer.Data, deliveryMethod); - } - return Task.WhenAll(tasks); - } - - public Task SendFromPlayerToPlayerAndAwait(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending packet of type '{packet.GetType().Name}' " + - $"(SenderId={fromPlayer.ConnectionId}, ReceiverId={LocalConnectionId})." - ); - - var writer = new SpanBuffer(stackalloc byte[412]); - writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); - WriteOne(ref writer, packet); - if (toPlayer.IsENetConnection) - { - SendInternal(toPlayer, ref writer, deliveryMethod); - return Task.CompletedTask; - } - return Send(toPlayer.Endpoint, writer.Data, deliveryMethod); - } - public Task SendFromPlayerToPlayerAndAwait(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending MultiPacket" + - $"(SenderId={fromPlayer.ConnectionId}, ReceiverId={LocalConnectionId})." - ); - - var writer = new SpanBuffer(stackalloc byte[1024]); - writer.WriteRoutingHeader(fromPlayer.ConnectionId, LocalConnectionId); - WriteMany(ref writer, packets); - SendInternal(toPlayer, ref writer, deliveryMethod); - return Send(toPlayer.Endpoint, writer.Data, deliveryMethod); - } - - public Task SendToPlayerAndAwait(IPlayer player, INetSerializable packet, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending packet of type '{packet.GetType().Name}' " + - $"(SenderId={ServerId}, ReceiverId={LocalConnectionId})." - ); - - var writer = new SpanBuffer(stackalloc byte[412]); - writer.WriteRoutingHeader(ServerId, LocalConnectionId); - WriteOne(ref writer, packet); SendInternal(player, ref writer, deliveryMethod); - return Send(player.Endpoint, writer.Data, deliveryMethod); - } - public Task SendToPlayerAndAwait(IPlayer player, INetSerializable[] packets, DeliveryMethod deliveryMethod) - { - _logger.Debug( - $"Sending MultiPacket " + - $"(SenderId={ServerId}, ReceiverId={LocalConnectionId})." - ); - - var writer = new SpanBuffer(stackalloc byte[1024]); - writer.WriteRoutingHeader(ServerId, LocalConnectionId); - WriteMany(ref writer, packets); - SendInternal(player, ref writer, deliveryMethod); - return Send(player.Endpoint, writer.Data, deliveryMethod); } #endregion @@ -470,6 +228,7 @@ public void WriteOne(ref SpanBuffer writer, INetSerializable packet) packetWriter.WriteString(type.Name); //Presume it is a mpcore packet and use the mpcore packet ID, would thow an exeption here if not //throw new Exception($"Failed to retrieve identifier for packet of type '{type.Name}'"); + //this should be fine as its only for packets sent from the server } packet.WriteTo(ref packetWriter); writer.WriteVarUInt((uint)packetWriter.Size); @@ -482,5 +241,6 @@ public void WriteMany(ref SpanBuffer writer, INetSerializable[] packets) } #endregion + } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/LevelFinishedPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/LevelFinishedPacketHandler.cs index ced5e9af..7a8e294a 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/LevelFinishedPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/LevelFinishedPacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.GameplayRpc { @@ -17,7 +16,7 @@ public LevelFinishedPacketHandler( _gameplayManager = gameplayManager; } - public override Task Handle(IPlayer sender, LevelFinishedPacket packet) + public override void Handle(IPlayer sender, LevelFinishedPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(LevelFinishedPacket)}' " + @@ -25,7 +24,6 @@ public override Task Handle(IPlayer sender, LevelFinishedPacket packet) ); _gameplayManager.HandleLevelFinished(sender, packet); - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/RequestReturnToMenuPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/RequestReturnToMenuPacketHandler.cs index fcc52171..abafd1cd 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/RequestReturnToMenuPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/RequestReturnToMenuPacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.GameplayRpc { @@ -17,7 +16,7 @@ public RequestReturnToMenuPacketHandler( _gameplayManager = gameplayManager; } - public override Task Handle(IPlayer sender, RequestReturnToMenuPacket packet) + public override void Handle(IPlayer sender, RequestReturnToMenuPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(RequestReturnToMenuPacket)}' " + @@ -26,8 +25,6 @@ public override Task Handle(IPlayer sender, RequestReturnToMenuPacket packet) if (sender.IsServerOwner) _gameplayManager.SignalRequestReturnToMenu(); - - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacketHandler.cs index 509ba7df..8e1f23bb 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacketHandler.cs @@ -2,14 +2,13 @@ using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.GameplayRpc { public sealed class SetGameplaySceneReadyPacketHandler : BasePacketHandler { - private IGameplayManager _gameplayManager; - private ILogger _logger = Log.ForContext(); + private readonly IGameplayManager _gameplayManager; + private readonly ILogger _logger = Log.ForContext(); public SetGameplaySceneReadyPacketHandler( IGameplayManager gameplayManager) @@ -17,7 +16,7 @@ public SetGameplaySceneReadyPacketHandler( _gameplayManager = gameplayManager; } - public override Task Handle(IPlayer sender, SetGameplaySceneReadyPacket packet) + public override void Handle(IPlayer sender, SetGameplaySceneReadyPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SetGameplaySceneReadyPacket)}' " + @@ -25,7 +24,6 @@ public override Task Handle(IPlayer sender, SetGameplaySceneReadyPacket packet) ); _gameplayManager.HandleGameSceneLoaded(sender, packet); - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/SetGameplaySongReadyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/SetGameplaySongReadyPacketHandler.cs index 2e4329d1..4f9ff254 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/SetGameplaySongReadyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/SetGameplaySongReadyPacketHandler.cs @@ -2,14 +2,13 @@ using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.GameplayRpc { public sealed class SetGameplaySongReadyPacketHandler : BasePacketHandler { - private IGameplayManager _gameplayManager; - private ILogger _logger = Log.ForContext(); + private readonly IGameplayManager _gameplayManager; + private readonly ILogger _logger = Log.ForContext(); public SetGameplaySongReadyPacketHandler( IGameplayManager gameplayManager) @@ -17,7 +16,7 @@ public SetGameplaySongReadyPacketHandler( _gameplayManager = gameplayManager; } - public override Task Handle(IPlayer sender, SetGameplaySongReadyPacket packet) + public override void Handle(IPlayer sender, SetGameplaySongReadyPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SetGameplaySongReadyPacket)}' " + @@ -25,7 +24,6 @@ public override Task Handle(IPlayer sender, SetGameplaySongReadyPacket packet) ); _gameplayManager.HandleGameSongLoaded(sender); - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs index 9bbc6c82..f03567da 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs @@ -3,8 +3,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MPChat { @@ -20,7 +18,7 @@ public MpcCapabilitiesPacketHandler(IPacketDispatcher packetDispatcher, _instanceConfiguration = instanceConfiguration; } - public override Task Handle(IPlayer sender, MpcCapabilitiesPacket packet) + public override void Handle(IPlayer sender, MpcCapabilitiesPacket packet) { bool FirstJoin = !sender.CanTextChat && packet.CanTextChat; sender.CanReceiveVoiceChat = packet.CanReceiveVoiceChat; @@ -39,7 +37,6 @@ public override Task Handle(IPlayer sender, MpcCapabilitiesPacket packet) }, DeliveryMethod.ReliableOrdered); } - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs index 12534ac0..0a725d67 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs @@ -5,7 +5,6 @@ using BeatTogether.LiteNetLib.Enums; using Serilog; using System; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MPChat { @@ -29,7 +28,7 @@ public MpcTextChatPacketHandler(IPacketDispatcher packetDispatcher, _serviceProvider = serviceProvider; } - public override Task Handle(IPlayer sender, MpcTextChatPacket packet) + public override void Handle(IPlayer sender, MpcTextChatPacket packet) { if (packet.Text.Length < _instanceConfiguration.MaxLengthCommand && packet.Text.StartsWith("/")){ string[] CommandValues = packet.Text[1..].Split(' '); @@ -41,14 +40,13 @@ public override Task Handle(IPlayer sender, MpcTextChatPacket packet) var Command = _serviceProvider.GetService(packetHandlerType); if (Command != null) ((ICommandHandler)Command).Handle(sender, TextCommand); - return Task.CompletedTask; + return; } _packetDispatcher.SendToPlayer(sender, new MpcTextChatPacket { Text = "Command not found or too long" }, DeliveryMethod.ReliableOrdered); } - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs index 18d026bc..b96126ed 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs @@ -4,7 +4,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -22,7 +21,7 @@ public ClearRecommendedBeatmapPacketHandler( _lobbyManager = lobbyManager; } - public override Task Handle(IPlayer sender, ClearRecommendedBeatmapPacket packet) + public override void Handle(IPlayer sender, ClearRecommendedBeatmapPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(ClearRecommendedBeatmapPacket)}' " + @@ -34,7 +33,6 @@ public override Task Handle(IPlayer sender, ClearRecommendedBeatmapPacket packet { Reason = sender.IsServerOwner ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None }, DeliveryMethod.ReliableOrdered); - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedModifiersPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedModifiersPacketHandler.cs index f5c95387..66f9058a 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedModifiersPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedModifiersPacketHandler.cs @@ -1,9 +1,7 @@ using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; -using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -18,7 +16,7 @@ public ClearRecommendedModifiersPacketHandler( _lobbyManager = lobbyManager; } - public override Task Handle(IPlayer sender, ClearRecommendedModifiersPacket packet) + public override void Handle(IPlayer sender, ClearRecommendedModifiersPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(ClearRecommendedModifiersPacket)}' " + @@ -26,7 +24,6 @@ public override Task Handle(IPlayer sender, ClearRecommendedModifiersPacket pack ); sender.Modifiers = _lobbyManager.EmptyModifiers; - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs index 018efff0..8f9cc4d9 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs @@ -3,7 +3,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -21,7 +20,7 @@ public GetCountdownEndTimePacketHandler( _packetDispatcher = packetDispatcher; } - public override Task Handle(IPlayer sender, GetCountdownEndTimePacket packet) + public override void Handle(IPlayer sender, GetCountdownEndTimePacket packet) { _logger.Debug( $"Handling packet of type '{nameof(GetCountdownEndTimePacket)}' " + @@ -33,7 +32,6 @@ public override Task Handle(IPlayer sender, GetCountdownEndTimePacket packet) CountdownTime = _lobbyManager.CountdownEndTime }, DeliveryMethod.ReliableOrdered); - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsInLobbyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsInLobbyPacketHandler.cs index e0439fa9..4055a107 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsInLobbyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsInLobbyPacketHandler.cs @@ -1,11 +1,9 @@ using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -24,7 +22,7 @@ public GetIsInLobbyPacketHandler( _gameplayManager = gameplayManager; } - public override Task Handle(IPlayer sender, GetIsInLobbyPacket packet) + public override void Handle(IPlayer sender, GetIsInLobbyPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(GetIsInLobbyPacket)}' " + @@ -36,7 +34,6 @@ public override Task Handle(IPlayer sender, GetIsInLobbyPacket packet) IsInLobby = _instance.State != MultiplayerGameState.Game }, DeliveryMethod.ReliableOrdered); - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsReadyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsReadyPacketHandler.cs index 85c877eb..0167d652 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsReadyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsReadyPacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -17,7 +16,7 @@ public GetIsReadyPacketHandler( _packetDispatcher = packetDispatcher; } - public override Task Handle(IPlayer sender, GetIsReadyPacket packet) + public override void Handle(IPlayer sender, GetIsReadyPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(GetIsReadyPacket)}' " + @@ -28,8 +27,6 @@ public override Task Handle(IPlayer sender, GetIsReadyPacket packet) { IsReady = sender.IsReady }, DeliveryMethod.ReliableOrdered); - - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetMultiplayerGameStatePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetMultiplayerGameStatePacketHandler.cs index 27e98cdb..16ace7b3 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetMultiplayerGameStatePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetMultiplayerGameStatePacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -20,7 +19,7 @@ public GetMultiplayerGameStatePacketHandler( _packetDispatcher = packetDispatcher; } - public override Task Handle(IPlayer sender, GetMultiplayerGameStatePacket packet) + public override void Handle(IPlayer sender, GetMultiplayerGameStatePacket packet) { _logger.Debug( $"Handling packet of type '{nameof(GetMultiplayerGameStatePacket)}' " + @@ -31,8 +30,6 @@ public override Task Handle(IPlayer sender, GetMultiplayerGameStatePacket packet { State = _instance.State }, DeliveryMethod.ReliableOrdered); - - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs index f6785509..c7eaa1aa 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs @@ -4,7 +4,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -25,7 +24,7 @@ public GetPlayersPermissionConfigurationPacketHandler( _playerRegistry = playerRegistry; } - public override Task Handle(IPlayer sender, GetPlayersPermissionConfigurationPacket packet) + public override void Handle(IPlayer sender, GetPlayersPermissionConfigurationPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(GetPlayersPermissionConfigurationPacket)}' " + @@ -60,8 +59,6 @@ public override Task Handle(IPlayer sender, GetPlayersPermissionConfigurationPac PlayersPermission = playerPermissionConfigurations } }, DeliveryMethod.ReliableOrdered); - - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedBeatmapPacketHandler.cs index 6494f869..d5c714db 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedBeatmapPacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -17,7 +16,7 @@ public GetRecommendedBeatmapPacketHandler( _packetDispatcher = packetDispatcher; } - public override Task Handle(IPlayer sender, GetRecommendedBeatmapPacket packet) + public override void Handle(IPlayer sender, GetRecommendedBeatmapPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(GetRecommendedBeatmapPacket)}' " + @@ -29,8 +28,6 @@ public override Task Handle(IPlayer sender, GetRecommendedBeatmapPacket packet) { BeatmapIdentifier = sender.BeatmapIdentifier }, DeliveryMethod.ReliableOrdered); - - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedModifiersPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedModifiersPacketHandler.cs index ab5b9044..eabb433e 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedModifiersPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedModifiersPacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -17,7 +16,7 @@ public GetRecommendedModifiersPacketHandler( _packetDispatcher = packetDispatcher; } - public override Task Handle(IPlayer sender, GetRecommendedModifiersPacket packet) + public override void Handle(IPlayer sender, GetRecommendedModifiersPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(GetRecommendedModifiersPacket)}' " + @@ -27,8 +26,6 @@ public override Task Handle(IPlayer sender, GetRecommendedModifiersPacket packet { Modifiers = sender.Modifiers }, DeliveryMethod.ReliableOrdered); - - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedBeatmapHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedBeatmapHandler.cs index c64f29c5..2092d899 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedBeatmapHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedBeatmapHandler.cs @@ -3,7 +3,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -27,7 +26,7 @@ public GetSelectedBeatmapHandler( _instance = instance; } - public override Task Handle(IPlayer sender, GetSelectedBeatmap packet) + public override void Handle(IPlayer sender, GetSelectedBeatmap packet) { _logger.Debug( $"Handling packet of type '{nameof(GetSelectedBeatmap)}' " + @@ -39,7 +38,7 @@ public override Task Handle(IPlayer sender, GetSelectedBeatmap packet) { Beatmap = _lobbyManager.SelectedBeatmap }, DeliveryMethod.ReliableOrdered); - return Task.CompletedTask; + return; } if (_instance.State == Messaging.Enums.MultiplayerGameState.Game && _gameplayManager.CurrentBeatmap != null) { @@ -47,10 +46,9 @@ public override Task Handle(IPlayer sender, GetSelectedBeatmap packet) { Beatmap = _gameplayManager.CurrentBeatmap }, DeliveryMethod.ReliableOrdered); - return Task.CompletedTask; + return; } _packetDispatcher.SendToPlayer(sender, new ClearSelectedBeatmap(), DeliveryMethod.ReliableOrdered); - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedGameplayModifiersHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedGameplayModifiersHandler.cs index dfbe796b..8a493093 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedGameplayModifiersHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedGameplayModifiersHandler.cs @@ -3,7 +3,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -27,7 +26,7 @@ public GetSelectedGameplayModifiersHandler( _instance = dedicatedInstance; } - public override Task Handle(IPlayer sender, GetSelectedGameplayModifiers packet) + public override void Handle(IPlayer sender, GetSelectedGameplayModifiers packet) { _logger.Debug( $"Handling packet of type '{nameof(GetSelectedGameplayModifiers)}' " + @@ -39,7 +38,7 @@ public override Task Handle(IPlayer sender, GetSelectedGameplayModifiers packet) { Modifiers = _lobbyManager.SelectedModifiers }, DeliveryMethod.ReliableOrdered); - return Task.CompletedTask; + return; } if (_instance.State == Messaging.Enums.MultiplayerGameState.Game) { @@ -47,10 +46,9 @@ public override Task Handle(IPlayer sender, GetSelectedGameplayModifiers packet) { Modifiers = _gameplayManager.CurrentModifiers }, DeliveryMethod.ReliableOrdered); - return Task.CompletedTask; + return; } _packetDispatcher.SendToPlayer(sender, new ClearSelectedGameplayModifiers(), DeliveryMethod.ReliableOrdered); - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs index 6943708f..bfde60f5 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs @@ -8,7 +8,6 @@ using BeatTogether.LiteNetLib.Enums; using Serilog; using System.Linq; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -35,7 +34,7 @@ public GetStartedLevelPacketHandler( _packetDispatcher = packetDispatcher; } - public override Task Handle(IPlayer sender, GetStartedLevelPacket packet) + public override void Handle(IPlayer sender, GetStartedLevelPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(GetStartedLevelPacket)}' " + @@ -83,7 +82,6 @@ public override Task Handle(IPlayer sender, GetStartedLevelPacket packet) else _packetDispatcher.SendToPlayer(sender, new CancelLevelStartPacket(), DeliveryMethod.ReliableOrdered); } - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs index c25facad..df5e8036 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs @@ -4,7 +4,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -22,16 +21,13 @@ public RequestKickPlayerPacketHandler( _packetDispatcher = packetDispatcher; } - public override async Task Handle(IPlayer sender, RequestKickPlayerPacket packet) + public override void Handle(IPlayer sender, RequestKickPlayerPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(RequestKickPlayerPacket)}' " + $"(SenderId={sender.ConnectionId}, KickedPlayerId={packet.KickedPlayerId})." ); - await sender.PlayerAccessSemaphore.WaitAsync(); - bool CanKick = sender.CanKickVote; - sender.PlayerAccessSemaphore.Release(); - if (CanKick) + if (sender.CanKickVote) if (_playerRegistry.TryGetPlayer(packet.KickedPlayerId, out var kickedPlayer)) _packetDispatcher.SendToPlayer(kickedPlayer, new KickPlayerPacket { diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacketHandler.cs index f4a8f9e1..6160f3ac 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -23,21 +22,18 @@ public SetIsEntitledToLevelPacketHandler( _playerRegistry = playerRegistry; } - public override async Task Handle(IPlayer sender, SetIsEntitledToLevelPacket packet) + public override void Handle(IPlayer sender, SetIsEntitledToLevelPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SetIsEntitledToLevelPacket)}' " + $"(SenderId={sender.ConnectionId}, LevelId={packet.LevelId}, Entitlement={packet.Entitlement})." ); - await sender.PlayerAccessSemaphore.WaitAsync(); sender.SetEntitlement(packet.LevelId, packet.Entitlement); foreach (IPlayer player in _playerRegistry.Players) { if(player.BeatmapIdentifier != null && player.BeatmapIdentifier.LevelId == packet.LevelId) player.UpdateEntitlement = true; } - sender.PlayerAccessSemaphore.Release(); - return; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs index 737f9bf3..b8792afb 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs @@ -4,10 +4,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System; -using System.Linq; -using System.Numerics; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -34,22 +30,14 @@ public SetIsInLobbyPacketHandler( _lobbyManager = lobbyManager; } - public override async Task Handle(IPlayer sender, SetIsInLobbyPacket packet) + public override void Handle(IPlayer sender, SetIsInLobbyPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SetIsInLobbyPacket)}' " + $"(SenderId={sender.ConnectionId}, InLobby={packet.IsInLobby})." ); - await sender.PlayerAccessSemaphore.WaitAsync(); - bool InLobby = sender.InLobby; - if (packet.IsInLobby == sender.InLobby) - { - sender.PlayerAccessSemaphore.Release(); - return; - } sender.InLobby = packet.IsInLobby; - sender.PlayerAccessSemaphore.Release(); - if (InLobby) + if (sender.InLobby) { _packetDispatcher.SendToPlayer(sender, new SetIsStartButtonEnabledPacket { @@ -72,7 +60,6 @@ public override async Task Handle(IPlayer sender, SetIsInLobbyPacket packet) Modifiers = _lobbyManager.SelectedModifiers }, DeliveryMethod.ReliableOrdered); } - return; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs index eaa8a1ec..ce450e1f 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs @@ -5,7 +5,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -29,19 +28,15 @@ public SetIsReadyPacketHandler( _packetDispatcher = packetDispatcher; } - public override async Task Handle(IPlayer sender, SetIsReadyPacket packet) + public override void Handle(IPlayer sender, SetIsReadyPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SetIsReadyPacket)}' " + $"(SenderId={sender.ConnectionId}, IsReady={packet.IsReady})." ); - bool SendToSpectate = false; - await sender.PlayerAccessSemaphore.WaitAsync(); sender.IsReady = packet.IsReady; //If the player somehow is in the lobby during gameplay then readying should send them to spectate - SendToSpectate = sender.IsReady && _instance.State == MultiplayerGameState.Game && _gameplayManager.CurrentBeatmap != null && _gameplayManager.State == GameplayManagerState.Gameplay; - sender.PlayerAccessSemaphore.Release(); - if (SendToSpectate) + if (sender.IsReady && _instance.State == MultiplayerGameState.Game && _gameplayManager.CurrentBeatmap != null && _gameplayManager.State == GameplayManagerState.Gameplay) _packetDispatcher.SendToPlayer(sender, new StartLevelPacket { Beatmap = _gameplayManager.CurrentBeatmap!, diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs index be1a181a..a1a65cd9 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs @@ -24,32 +24,24 @@ public SetRecommendedBeatmapPacketHandler( _playerRegistry = playerRegistry; } - public override async Task Handle(IPlayer sender, SetRecommendedBeatmapPacket packet) + public override void Handle(IPlayer sender, SetRecommendedBeatmapPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SetRecommendedBeatmapPacket)}' " + $"(SenderId={sender.ConnectionId}, LevelId={packet.BeatmapIdentifier.LevelId}, Difficulty={packet.BeatmapIdentifier.Difficulty})." ); - bool GetEntitlementFromOtherPlayers = false; - await sender.PlayerAccessSemaphore.WaitAsync(); if (sender.CanRecommendBeatmaps) { sender.BeatmapIdentifier = packet.BeatmapIdentifier; if (sender.BeatmapIdentifier.LevelId != sender.MapHash) sender.ResetRecommendedMapRequirements(); - GetEntitlementFromOtherPlayers = true; sender.UpdateEntitlement = true; - } - sender.PlayerAccessSemaphore.Release(); - if (GetEntitlementFromOtherPlayers) - { _packetDispatcher.SendToNearbyPlayers(new GetIsEntitledToLevelPacket { LevelId = packet.BeatmapIdentifier.LevelId }, DeliveryMethod.ReliableOrdered); } - return; - } + } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacketHandler.cs index 3d754382..75c14da9 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacketHandler.cs @@ -2,8 +2,6 @@ using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using Serilog; -using System; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -21,17 +19,14 @@ public SetRecommendedModifiersPacketHandler( _lobbyManager = lobbyManager; } - public override async Task Handle(IPlayer sender, SetRecommendedModifiersPacket packet) + public override void Handle(IPlayer sender, SetRecommendedModifiersPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SetRecommendedModifiersPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - await sender.PlayerAccessSemaphore.WaitAsync(); if (sender.CanRecommendModifiers) sender.Modifiers = packet.Modifiers; - sender.PlayerAccessSemaphore.Release(); - return; - } + } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs index 38610279..c7bcb496 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs @@ -6,7 +6,6 @@ using BeatTogether.LiteNetLib.Enums; using Serilog; using System.Linq; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -27,7 +26,7 @@ public DediPacketSetNewManagerPacketHandler( _configuration = configuration; } - public override Task Handle(IPlayer sender, DediPacketSetNewManagerPacket packet) + public override void Handle(IPlayer sender, DediPacketSetNewManagerPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(DediPacketSetNewManagerPacket)}' " + @@ -54,7 +53,6 @@ public override Task Handle(IPlayer sender, DediPacketSetNewManagerPacket packet } }, DeliveryMethod.ReliableOrdered); } - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs index 6e3faaad..32c52d45 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Kernel.Extensions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; using BeatTogether.LiteNetLib.Enums; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -19,7 +18,7 @@ public GetMpPlayerDataPacketHandler( _PlayerRegistry = playerRegistry; } - public override Task Handle(IPlayer sender, MpPlayerData packet) + public override void Handle(IPlayer sender, MpPlayerData packet) { foreach (var Player in _PlayerRegistry.Players) @@ -31,7 +30,6 @@ public override Task Handle(IPlayer sender, MpPlayerData packet) ClientVersion = Player.ClientVersion }, DeliveryMethod.ReliableOrdered); } - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MPBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MPBeatmapPacketHandler.cs index bb76730f..fb916041 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MPBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MPBeatmapPacketHandler.cs @@ -5,7 +5,6 @@ using Serilog; using System; using System.Linq; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -20,7 +19,7 @@ public MpBeatmapPacketHandler( _lobbyManager = lobbyManager; } - public override Task Handle(IPlayer sender, MpBeatmapPacket packet) + public override void Handle(IPlayer sender, MpBeatmapPacket packet) { _logger.Debug( @@ -35,7 +34,6 @@ public override Task Handle(IPlayer sender, MpBeatmapPacket packet) sender.MappingExtensions = Requirements.Contains("Mapping Extensions"); } sender.BeatmapDifficulties = packet.requirements.Keys.Select(b => (BeatmapDifficulty)b).ToArray(); - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PingPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PingPacketHandler.cs index 4b035c3e..a2bc00d2 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PingPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PingPacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers { @@ -16,7 +15,7 @@ public PingPacketHandler(IPacketDispatcher packetDispatcher) _packetDispatcher = packetDispatcher; } - public override Task Handle(IPlayer sender, PingPacket packet) + public override void Handle(IPlayer sender, PingPacket packet) { _logger.Verbose( $"Handling packet of type '{nameof(PingPacket)}' " + @@ -27,8 +26,6 @@ public override Task Handle(IPlayer sender, PingPacket packet) { PingTime = packet.PingTime }, DeliveryMethod.ReliableOrdered); - - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerAvatarPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerAvatarPacketHandler.cs index b9f4c311..d35a5ab4 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerAvatarPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerAvatarPacketHandler.cs @@ -1,5 +1,4 @@ -using System.Threading.Tasks; -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets; using Serilog; @@ -18,15 +17,13 @@ public PlayerAvatarPacketHandler( _instance = instance; } - public override async Task Handle(IPlayer sender, PlayerAvatarPacket packet) + public override void Handle(IPlayer sender, PlayerAvatarPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(PlayerAvatarPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - await sender.PlayerAccessSemaphore.WaitAsync(); sender.Avatar = packet.PlayerAvatar; - sender.PlayerAccessSemaphore.Release(); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs index 52cf3716..3dc553f7 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs @@ -1,5 +1,4 @@ using System; -using System.Threading.Tasks; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets; using BeatTogether.LiteNetLib.Enums; @@ -20,18 +19,16 @@ public PlayerIdentityPacketHandler( _instance = instance; } - public override async Task Handle(IPlayer sender, PlayerIdentityPacket packet) + public override void Handle(IPlayer sender, PlayerIdentityPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(PlayerIdentityPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - await sender.PlayerAccessSemaphore.WaitAsync(); sender.Avatar = packet.PlayerAvatar; sender.State = packet.PlayerState; sender.Random = packet.Random.Data ?? Array.Empty(); sender.PublicEncryptionKey = packet.PublicEncryptionKey.Data ?? Array.Empty(); - sender.PlayerAccessSemaphore.Release(); _packetDispatcher.SendFromPlayer(sender, packet, DeliveryMethod.ReliableOrdered); } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs index 01151031..5cdf07c0 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers { @@ -17,26 +16,18 @@ public PlayerLatencyPacketHandler( _packetDispatcher = packetDispatcher; } - public override async Task Handle(IPlayer sender, PlayerLatencyPacket packet) + public override void Handle(IPlayer sender, PlayerLatencyPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(PlayerLatencyPacket)}' " + $"(SenderId={sender.ConnectionId}, Latency={packet.Latency})." ); - await sender.PlayerAccessSemaphore.WaitAsync(); sender.Latency.Update(packet.Latency); - sender.PlayerAccessSemaphore.Release(); _packetDispatcher.SendFromPlayer(sender, new PlayerLatencyPacket { Latency = sender.Latency.CurrentAverage }, DeliveryMethod.ReliableOrdered); - - _logger.Verbose( - $"Preparing packet of type '{nameof(PlayerLatencyPacket)}' " + - $"(SenderId={sender.ConnectionId}, Latency={sender.Latency.CurrentAverage})." - ); - return; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs index fbe4d865..b7f20879 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers { @@ -16,23 +15,18 @@ public PlayerSortOrderPacketHandler(IPacketDispatcher packetDispatcher) _packetDispatcher = packetDispatcher; } - public override async Task Handle(IPlayer sender, PlayerSortOrderPacket packet) + public override void Handle(IPlayer sender, PlayerSortOrderPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(PlayerSortOrderPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - bool Send = false; - await sender.PlayerAccessSemaphore.WaitAsync(); if (sender.UserId == packet.UserId && sender.SortIndex != packet.SortIndex) //If they send themselves as being in the wrong place, correct them. Although this probably shouldnt have a handler { packet.SortIndex = sender.SortIndex; - Send = true; - } - sender.PlayerAccessSemaphore.Release(); - if(Send) _packetDispatcher.SendToPlayer(sender, packet, DeliveryMethod.ReliableOrdered); - return; + } + } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs index 91e3882a..4efd833a 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers { @@ -16,7 +15,7 @@ public PlayerStatePacketHandler(ILobbyManager lobbyManager) _lobbyManager = lobbyManager; } - public override async Task Handle(IPlayer sender, PlayerStatePacket packet) + public override void Handle(IPlayer sender, PlayerStatePacket packet) { _logger.Debug( $"Handling packet of type '{nameof(PlayerStatePacket)}' " + @@ -27,12 +26,9 @@ public override async Task Handle(IPlayer sender, PlayerStatePacket packet) $"was_active_at_level_start={packet.PlayerState.Contains("was_active_at_level_start")}, finished_level={packet.PlayerState.Contains("finished_level")})." ); - await sender.PlayerAccessSemaphore.WaitAsync(); sender.State = packet.PlayerState; if (packet.PlayerState.Contains("spectating") != sender.State.Contains("spectating") || packet.PlayerState.Contains("wants_to_play_next_level") != sender.State.Contains("wants_to_play_next_level")) _lobbyManager.SpectatingPlayersUpdated = true; - sender.PlayerAccessSemaphore.Release(); - return; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/SyncTimePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/SyncTimePacketHandler.cs index 025c956a..f6322777 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/SyncTimePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/SyncTimePacketHandler.cs @@ -2,7 +2,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets; using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers { @@ -16,7 +15,7 @@ public SyncTimePacketHandler(IPacketDispatcher packetDispatcher) _packetDispatcher = packetDispatcher; } - public override Task Handle(IPlayer sender, SyncTimePacket packet) + public override void Handle(IPlayer sender, SyncTimePacket packet) { _logger.Debug( $"Handling packet of type '{nameof(SyncTimePacket)}' " + @@ -27,12 +26,6 @@ public override Task Handle(IPlayer sender, SyncTimePacket packet) { SyncTime = sender.SyncTime }, DeliveryMethod.ReliableOrdered); - - _logger.Verbose( - $"Preparing '{nameof(SyncTimePacket)}' " + - $"(SenderId={sender.ConnectionId}, SyncTime={sender.SyncTime})." - ); - return Task.CompletedTask; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/AcknowledgeMessageHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/AcknowledgeMessageHandler.cs deleted file mode 100644 index b54912ab..00000000 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/AcknowledgeMessageHandler.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Threading.Tasks; -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.Core.Messaging.Messages; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Handshake; - -namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.Unconnected -{ - public class AcknowledgeMessageHandler : BaseHandshakeMessageHandler - { - private readonly IUnconnectedDispatcher _unconnectedDispatcher; - - public AcknowledgeMessageHandler(IUnconnectedDispatcher unconnectedDispatcher) - { - _unconnectedDispatcher = unconnectedDispatcher; - } - - public override Task Handle(HandshakeSession session, AcknowledgeMessage message) - { - _unconnectedDispatcher.Acknowledge(session, message.ResponseId, message.MessageHandled); - return Task.FromResult(default(IMessage?)); - } - - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/AuthenticateGameLiftUserRequestHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/AuthenticateGameLiftUserRequestHandler.cs deleted file mode 100644 index ce923161..00000000 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/AuthenticateGameLiftUserRequestHandler.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading.Tasks; -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Handshake; -using BeatTogether.DedicatedServer.Messaging.Messages.GameLift; - -namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.Unconnected -{ - public class AuthenticateGameLiftUserRequestHandler : BaseHandshakeMessageHandler - { - private readonly IHandshakeService _handshakeService; - - public AuthenticateGameLiftUserRequestHandler(IHandshakeService handshakeService) - { - _handshakeService = handshakeService; - } - - public override async Task Handle(HandshakeSession session, AuthenticateGameLiftUserRequest message) - => await _handshakeService.AuthenticateGameLiftUser(session, message); - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/ClientHelloRequestHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/ClientHelloRequestHandler.cs deleted file mode 100644 index 70794e61..00000000 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/ClientHelloRequestHandler.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading.Tasks; -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Handshake; -using BeatTogether.DedicatedServer.Messaging.Messages.Handshake; - -namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.Unconnected -{ - public class ClientHelloRequestHandler : BaseHandshakeMessageHandler - { - private readonly IHandshakeService _handshakeService; - - public ClientHelloRequestHandler(IHandshakeService handshakeService) - { - _handshakeService = handshakeService; - } - - public override async Task Handle(HandshakeSession session, ClientHelloRequest message) => - await _handshakeService.ClientHello(session, message); - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/ClientHelloWithCookieRequestHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/ClientHelloWithCookieRequestHandler.cs deleted file mode 100644 index 7ed2f787..00000000 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/ClientHelloWithCookieRequestHandler.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading.Tasks; -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Handshake; -using BeatTogether.DedicatedServer.Messaging.Messages.Handshake; - -namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.Unconnected -{ - public class ClientHelloWithCookieRequestHandler : BaseHandshakeMessageHandler - { - private readonly IHandshakeService _handshakeService; - - public ClientHelloWithCookieRequestHandler(IHandshakeService handshakeService) - { - _handshakeService = handshakeService; - } - - public override async Task Handle(HandshakeSession session, ClientHelloWithCookieRequest message) => - await _handshakeService.ClientHelloWithCookie(session, message); - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/ClientKeyExchangeRequestHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/ClientKeyExchangeRequestHandler.cs deleted file mode 100644 index bec43716..00000000 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/Unconnected/ClientKeyExchangeRequestHandler.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading.Tasks; -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Handshake; -using BeatTogether.DedicatedServer.Messaging.Messages.Handshake; - -namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.Unconnected -{ - public class ClientKeyExchangeRequestHandler : BaseHandshakeMessageHandler - { - private readonly IHandshakeService _handshakeService; - - public ClientKeyExchangeRequestHandler(IHandshakeService handshakeService) - { - _handshakeService = handshakeService; - } - - public override async Task Handle(HandshakeSession session, ClientKeyExchangeRequest message) => - await _handshakeService.ClientKeyExchange(session, message); - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index 6c972f48..7fae7d21 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -7,18 +7,15 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; using BeatTogether.DedicatedServer.Messaging.Registries; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib; using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Configuration; using BeatTogether.LiteNetLib.Enums; -using BeatTogether.LiteNetLib.Sources; using BeatTogether.LiteNetLib.Util; using Krypton.Buffers; using Serilog; namespace BeatTogether.DedicatedServer.Kernel { - public sealed class PacketSource : ConnectedMessageSource + public sealed class PacketSource { public const byte LocalConnectionId = 0; public const byte AllConnectionIds = 127; @@ -35,12 +32,7 @@ public PacketSource( IPacketRegistry packetRegistry, IPlayerRegistry playerRegistry, PacketDispatcher packetDispatcher, - InstanceConfiguration instconfiguration, - LiteNetConfiguration configuration, - LiteNetServer server) - : base ( - configuration, - server) + InstanceConfiguration instconfiguration) { _serviceProvider = serviceProvider; _packetRegistry = packetRegistry; @@ -49,7 +41,7 @@ public PacketSource( _configuration = instconfiguration; } - public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, DeliveryMethod method) + public void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, DeliveryMethod method) { if (!reader.TryReadRoutingHeader(out var routingHeader)) { @@ -133,7 +125,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D { if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncState) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets()) { - _logger.Verbose($"Skipping sync state packet from {sender.ConnectionId} (Secret='{sender.Secret}')."); + _logger.Verbose($"Skipping sync state packet from {sender.ConnectionId} (Secret='{sender.Instance._configuration.Secret}')."); return; } method = DeliveryMethod.Unreliable; @@ -143,7 +135,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, D { if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncStateDelta) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets()) { - _logger.Verbose($"Skipping sync state packet from {sender.ConnectionId} (Secret='{sender.Secret}')."); + _logger.Verbose($"Skipping sync state packet from {sender.ConnectionId} (Secret='{sender.Instance._configuration.Secret}')."); return; } sender.TicksAtLastSyncStateDelta = DateTime.UtcNow.Ticks; @@ -202,7 +194,7 @@ private void RoutePacket(IPlayer sender, _logger.Verbose( $"Routing packet from {routingHeader.SenderId} -> all players " + $"PacketOption='{routingHeader.PacketOption}' " + - $"(Secret='{sender.Secret}', DeliveryMethod={deliveryMethod})." + $"(Secret='{sender.Instance._configuration.Secret}', DeliveryMethod={deliveryMethod})." ); _packetDispatcher.RouteExcludingPlayer(sender, ref writer, deliveryMethod); } @@ -215,14 +207,14 @@ private void RoutePacket(IPlayer sender, { _logger.Warning( "Failed to retrieve receiver " + - $"(Secret='{sender.Secret}', ReceiverId={routingHeader.ReceiverId})." + $"(Secret='{sender.Instance._configuration.Secret}', ReceiverId={routingHeader.ReceiverId})." ); return; } _logger.Verbose( $"Routing packet from {routingHeader.SenderId} -> {routingHeader.ReceiverId} " + $"PacketOption='{routingHeader.PacketOption}' " + - $"(Secret='{sender.Secret}', DeliveryMethod={deliveryMethod})." + $"(Secret='{sender.Instance._configuration.Secret}', DeliveryMethod={deliveryMethod})." ); _packetDispatcher.RouteFromPlayerToPlayer(sender, receiver, ref writer, deliveryMethod); } diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index 592ed759..ed49c435 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Concurrent; using System.Net; -using System.Threading; -using System.Threading.Tasks; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Types; @@ -13,18 +11,16 @@ namespace BeatTogether.DedicatedServer.Kernel { public sealed class Player : IPlayer { - public SemaphoreSlim PlayerAccessSemaphore { get; set; } = new(1); public EndPoint Endpoint { get; } public IDedicatedInstance Instance { get; } public byte ConnectionId { get; } public byte RemoteConnectionId => 0; - public string Secret { get; } public string UserId { get; } public string UserName { get; } - public string? PlayerSessionId { get; } + public string PlayerSessionId { get; } public uint? ENetPeerId { get; set; } - public bool IsENetConnection => ENetPeerId.HasValue; + public bool IsENetConnection => true; //ENetPeerId.HasValue; public RollingAverage Latency { get; } = new(30); public long SyncTime => Math.Min(Instance.RunTime - Latency.CurrentAverage - _syncTimeOffset, @@ -32,7 +28,7 @@ public sealed class Player : IPlayer public int SortIndex { get; set; } public byte[]? Random { get; set; } public byte[]? PublicEncryptionKey { get; set; } - public string ClientVersion { get; set; } = "Pre-1.29"; + public string ClientVersion { get; set; } = "Unknown"; public Platform Platform { get; set; } = Platform.Test; //Unknown public string PlatformUserId { get; set; } = ""; public MultiplayerAvatarsData Avatar { get; set; } = new(); @@ -62,15 +58,14 @@ public sealed class Player : IPlayer public bool InMenu => State.Contains("in_menu"); //Should be true while in lobby private const long _syncTimeOffset = 6L; - private readonly ConcurrentDictionary _entitlements = new(); + private readonly ConcurrentDictionary _entitlements = new(); //Set a max amount of like 50 or something. public Player(EndPoint endPoint, IDedicatedInstance instance, - byte connectionId, string secret, string userId, string userName, string? playerSessionId, AccessLevel accessLevel = AccessLevel.Player) + byte connectionId, string userId, string userName, string? playerSessionId, AccessLevel accessLevel = AccessLevel.Player) { Endpoint = endPoint; Instance = instance; ConnectionId = connectionId; - Secret = secret; UserId = userId; UserName = userName; PlayerSessionId = playerSessionId; @@ -114,7 +109,7 @@ public void SetEntitlement(string levelId, EntitlementStatus entitlement) public void ResetRecommendedMapRequirements() { - MapHash= string.Empty; + MapHash = string.Empty; Chroma = false; NoodleExtensions = false; MappingExtensions = false; diff --git a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs index fbcded48..5cfcef4d 100644 --- a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs @@ -16,6 +16,40 @@ public sealed class PlayerRegistry : IPlayerRegistry private readonly Dictionary _playersByConnectionId = new(); private readonly Dictionary _playersByUserId = new(); + private readonly object pendingPlayerSessionData_Lock = new(); + private readonly Dictionary _pendingPlayerSessionData = new(); + + + + public void AddExtraPlayerSessionData(string playerSessionId, string ClientVersion, byte PlatformId, string PlayerPlatformUserId) + { + lock (pendingPlayerSessionData_Lock) + { + _pendingPlayerSessionData[playerSessionId] = (ClientVersion, PlatformId, PlayerPlatformUserId); + } + } + + public bool RemoveExtraPlayerSessionData(string playerSessionId, out string ClientVersion, out byte Platform, out string PlayerPlatformUserId) + { + lock (pendingPlayerSessionData_Lock) + { + if (_pendingPlayerSessionData.Remove(playerSessionId, out var Values)) + { + ClientVersion = Values.Item1; + Platform = Values.Item2; + PlayerPlatformUserId = Values.Item3; + return true; + } + ClientVersion = "ERROR"; + Platform = 0; + PlayerPlatformUserId = "ERROR"; + return false; + } + } + + + + private int _PlayerCount = 0; public int GetPlayerCount() diff --git a/BeatTogether.DedicatedServer.Messaging/Enums/EntitlementStatus.cs b/BeatTogether.DedicatedServer.Messaging/Enums/EntitlementStatus.cs index 3fca870a..0bd96c6d 100644 --- a/BeatTogether.DedicatedServer.Messaging/Enums/EntitlementStatus.cs +++ b/BeatTogether.DedicatedServer.Messaging/Enums/EntitlementStatus.cs @@ -1,10 +1,11 @@ namespace BeatTogether.DedicatedServer.Messaging.Enums { + //Unknown public enum EntitlementStatus { - Unknown = 0, - NotOwned = 1, - NotDownloaded = 2, - Ok = 3 + Unknown = 0,//means the server does not current have that users entitlement + NotOwned = 1,//Player cannot download or play the map + NotDownloaded = 2, //Player can play once downloaded + Ok = 3 //Has map } } diff --git a/BeatTogether.DedicatedServer.Messaging/Enums/GameLiftMessageType.cs b/BeatTogether.DedicatedServer.Messaging/Enums/GameLiftMessageType.cs deleted file mode 100644 index 0ef1c819..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Enums/GameLiftMessageType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace BeatTogether.DedicatedServer.Messaging.Enums -{ - public enum GameLiftMessageType : uint - { - AuthenticateUserRequest, - AuthenticateUserResponse, - MessageReceivedAcknowledge, - MultipartMessage - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserRequest.cs b/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserRequest.cs deleted file mode 100644 index a6b4adb3..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserRequest.cs +++ /dev/null @@ -1,31 +0,0 @@ -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.Extensions; -using Krypton.Buffers; - -namespace BeatTogether.DedicatedServer.Messaging.Messages.GameLift -{ - public sealed class AuthenticateGameLiftUserRequest : IEncryptedMessage, IReliableRequest, IReliableResponse - { - public uint SequenceId { get; set; } - public uint RequestId { get; set; } - public uint ResponseId { get; set; } - - public string UserId { get; set; } - public string UserName { get; set; } - public string PlayerSessionId { get; set; } - - public void ReadFrom(ref SpanBufferReader reader) - { - UserId = reader.ReadString(); - UserName = reader.ReadString(); - PlayerSessionId = reader.ReadString(); - } - - public void WriteTo(ref SpanBufferWriter writer) - { - writer.WriteString(UserId); - writer.WriteString(UserName); - writer.WriteString(PlayerSessionId); - } - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserResponse.cs b/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserResponse.cs deleted file mode 100644 index 1493cca9..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Messages/GameLift/AuthenticateGameLiftUserResponse.cs +++ /dev/null @@ -1,32 +0,0 @@ -using BeatTogether.Core.Messaging.Abstractions; -using Krypton.Buffers; - -namespace BeatTogether.DedicatedServer.Messaging.Messages.GameLift -{ - public enum AuthenticateUserResult : byte - { - Success = 0, - Failed = 1, - UnknownError = 2 - } - - public sealed class AuthenticateGameLiftUserResponse : IEncryptedMessage, IReliableRequest, IReliableResponse - { - public uint SequenceId { get; set; } - public uint RequestId { get; set; } - public uint ResponseId { get; set; } - public AuthenticateUserResult Result { get; set; } - - public bool Success => Result == AuthenticateUserResult.Success; - - public void WriteTo(ref SpanBufferWriter bufferWriter) - { - bufferWriter.WriteUInt8((byte)Result); - } - - public void ReadFrom(ref SpanBufferReader bufferReader) - { - Result = (AuthenticateUserResult)bufferReader.ReadByte(); - } - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ChangeCipherSpecRequest.cs b/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ChangeCipherSpecRequest.cs deleted file mode 100644 index f01f6a6d..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ChangeCipherSpecRequest.cs +++ /dev/null @@ -1,19 +0,0 @@ -using BeatTogether.Core.Messaging.Abstractions; -using Krypton.Buffers; - -namespace BeatTogether.DedicatedServer.Messaging.Messages.Handshake -{ - public sealed class ChangeCipherSpecRequest : IMessage, IReliableRequest, IReliableResponse - { - public uint RequestId { get; set; } - public uint ResponseId { get; set; } - - public void WriteTo(ref SpanBufferWriter bufferWriter) - { - } - - public void ReadFrom(ref SpanBufferReader bufferReader) - { - } - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ClientHelloRequest.cs b/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ClientHelloRequest.cs deleted file mode 100644 index 0d145997..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ClientHelloRequest.cs +++ /dev/null @@ -1,21 +0,0 @@ -using BeatTogether.Core.Messaging.Abstractions; -using Krypton.Buffers; - -namespace BeatTogether.DedicatedServer.Messaging.Messages.Handshake -{ - public sealed class ClientHelloRequest : IMessage, IReliableRequest - { - public uint RequestId { get; set; } - public byte[] Random { get; set; } - - public void WriteTo(ref SpanBufferWriter bufferWriter) - { - bufferWriter.WriteBytes(Random); - } - - public void ReadFrom(ref SpanBufferReader bufferReader) - { - Random = bufferReader.ReadBytes(32).ToArray(); - } - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ClientHelloWithCookieRequest.cs b/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ClientHelloWithCookieRequest.cs deleted file mode 100644 index b0811e3c..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ClientHelloWithCookieRequest.cs +++ /dev/null @@ -1,27 +0,0 @@ -using BeatTogether.Core.Messaging.Abstractions; -using Krypton.Buffers; - -namespace BeatTogether.DedicatedServer.Messaging.Messages.Handshake -{ - public sealed class ClientHelloWithCookieRequest : IMessage, IReliableRequest - { - public uint RequestId { get; set; } - public uint CertificateResponseId { get; set; } - public byte[] Random { get; set; } - public byte[] Cookie { get; set; } - - public void WriteTo(ref SpanBufferWriter bufferWriter) - { - bufferWriter.WriteUInt32(CertificateResponseId); - bufferWriter.WriteBytes(Random); - bufferWriter.WriteBytes(Cookie); - } - - public void ReadFrom(ref SpanBufferReader bufferReader) - { - CertificateResponseId = bufferReader.ReadUInt32(); - Random = bufferReader.ReadBytes(32).ToArray(); - Cookie = bufferReader.ReadBytes(32).ToArray(); - } - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ClientKeyExchangeRequest.cs b/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ClientKeyExchangeRequest.cs deleted file mode 100644 index 34a40101..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ClientKeyExchangeRequest.cs +++ /dev/null @@ -1,23 +0,0 @@ -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.Extensions; -using Krypton.Buffers; - -namespace BeatTogether.DedicatedServer.Messaging.Messages.Handshake -{ - public sealed class ClientKeyExchangeRequest : IMessage, IReliableRequest, IReliableResponse - { - public uint RequestId { get; set; } - public uint ResponseId { get; set; } - public byte[] ClientPublicKey { get; set; } - - public void WriteTo(ref SpanBufferWriter bufferWriter) - { - bufferWriter.WriteVarBytes(ClientPublicKey); - } - - public void ReadFrom(ref SpanBufferReader bufferReader) - { - ClientPublicKey = bufferReader.ReadVarBytes().ToArray(); - } - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/HelloVerifyRequest.cs b/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/HelloVerifyRequest.cs deleted file mode 100644 index cd4addda..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/HelloVerifyRequest.cs +++ /dev/null @@ -1,22 +0,0 @@ -using BeatTogether.Core.Messaging.Abstractions; -using Krypton.Buffers; - -namespace BeatTogether.DedicatedServer.Messaging.Messages.Handshake -{ - public sealed class HelloVerifyRequest : IMessage, IRequest, IResponse - { - public uint RequestId { get; set; } - public uint ResponseId { get; set; } - public byte[] Cookie { get; set; } - - public void WriteTo(ref SpanBufferWriter bufferWriter) - { - bufferWriter.WriteBytes(Cookie); - } - - public void ReadFrom(ref SpanBufferReader bufferReader) - { - Cookie = bufferReader.ReadBytes(32).ToArray(); - } - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ServerCertificateRequest.cs b/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ServerCertificateRequest.cs deleted file mode 100644 index 42f2585f..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ServerCertificateRequest.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Generic; -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.Extensions; -using Krypton.Buffers; - -namespace BeatTogether.DedicatedServer.Messaging.Messages.Handshake -{ - public sealed class ServerCertificateRequest : IMessage, IReliableRequest, IReliableResponse - { - public uint RequestId { get; set; } - public uint ResponseId { get; set; } - public List Certificates { get; set; } - - public void WriteTo(ref SpanBufferWriter bufferWriter) - { - bufferWriter.WriteVarUInt((uint)Certificates.Count); - foreach (var certificate in Certificates) - bufferWriter.WriteVarBytes(certificate); - } - - public void ReadFrom(ref SpanBufferReader bufferReader) - { - Certificates = new List(); - var certificateCount = bufferReader.ReadVarUInt(); - for (var i = 0; i < certificateCount; i++) - Certificates.Add(bufferReader.ReadVarBytes().ToArray()); - } - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ServerHelloRequest.cs b/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ServerHelloRequest.cs deleted file mode 100644 index fee39237..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Messages/Handshake/ServerHelloRequest.cs +++ /dev/null @@ -1,29 +0,0 @@ -using BeatTogether.Core.Messaging.Abstractions; -using BeatTogether.Extensions; -using Krypton.Buffers; - -namespace BeatTogether.DedicatedServer.Messaging.Messages.Handshake -{ - public sealed class ServerHelloRequest : IMessage, IReliableRequest, IReliableResponse - { - public uint RequestId { get; set; } - public uint ResponseId { get; set; } - public byte[] Random { get; set; } - public byte[] PublicKey { get; set; } - public byte[] Signature { get; set; } - - public void WriteTo(ref SpanBufferWriter bufferWriter) - { - bufferWriter.WriteBytes(Random); - bufferWriter.WriteVarBytes(PublicKey); - bufferWriter.WriteVarBytes(Signature); - } - - public void ReadFrom(ref SpanBufferReader bufferReader) - { - Random = bufferReader.ReadBytes(32).ToArray(); - PublicKey = bufferReader.ReadVarBytes().ToArray(); - Signature = bufferReader.ReadVarBytes().ToArray(); - } - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs index 2d3aaf9e..177ad1a5 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs @@ -1,75 +1,34 @@ -using System; -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.LiteNetLib.Abstractions; using BeatTogether.LiteNetLib.Extensions; using BeatTogether.LiteNetLib.Util; -using BinaryRecords.Exceptions; namespace BeatTogether.DedicatedServer.Messaging.Models { public sealed class ConnectionRequestData : INetSerializable { - public const string SessionIdPrefix = "ps:bt$"; + //public const string SessionIdPrefix = "ps:bt$"; - // Beat Saber public string UserId { get; set; } = null!; public string UserName { get; set; } = null!; public bool IsConnectionOwner { get; set; } - - // BasicConnectionRequestHandler - public string? Secret { get; set; } = null!; - - // GameLiftClientConnectionRequestHandler - public string? PlayerSessionId { get; set; } = null!; + public string PlayerSessionId { get; set; } = null!; public void ReadFrom(ref SpanBuffer reader) { - Secret = null; - PlayerSessionId = null; - - var initialOffset = reader.Offset; - - // Try to read as a GameLift connection request - try - { - UserId = reader.ReadString(); - UserName = reader.ReadString(); - IsConnectionOwner = reader.ReadBool(); - PlayerSessionId = reader.ReadString(); - } - catch (EndOfBufferException) { } - - if (PlayerSessionId != null && PlayerSessionId.StartsWith(SessionIdPrefix)) - // Read OK, valid session identifier - return; - - // Rewind, try to read as basic request - //reader.SkipBytes(initialOffset - reader.Offset); - reader.SetOffset(initialOffset); - Secret = reader.ReadString(); + //read as a GameLift connection request UserId = reader.ReadString(); UserName = reader.ReadString(); IsConnectionOwner = reader.ReadBool(); - PlayerSessionId = null; + PlayerSessionId = reader.ReadString(); } public void WriteTo(ref SpanBuffer writer) { - if (!string.IsNullOrEmpty(PlayerSessionId)) - { - // GameLift - writer.WriteString(UserId); - writer.WriteString(UserName); - writer.WriteBool(IsConnectionOwner); - writer.WriteString(PlayerSessionId); - } - else - { - // Basic - writer.WriteString(Secret ?? ""); - writer.WriteString(UserId); - writer.WriteString(UserName); - writer.WriteBool(IsConnectionOwner); - } + // GameLift + writer.WriteString(UserId); + writer.WriteString(UserName); + writer.WriteBool(IsConnectionOwner); + writer.WriteString(PlayerSessionId); } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/Unconnected/GameLiftMessageRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/Unconnected/GameLiftMessageRegistry.cs deleted file mode 100644 index 354be19b..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Registries/Unconnected/GameLiftMessageRegistry.cs +++ /dev/null @@ -1,20 +0,0 @@ -using BeatTogether.Core.Messaging.Implementations.Registries; -using BeatTogether.Core.Messaging.Messages; -using BeatTogether.DedicatedServer.Messaging.Enums; -using BeatTogether.DedicatedServer.Messaging.Messages.GameLift; - -namespace BeatTogether.DedicatedServer.Messaging.Registries.Unconnected -{ - public class GameLiftMessageRegistry : BaseMessageRegistry - { - public override uint MessageGroup => 3U; - - public GameLiftMessageRegistry() - { - Register(GameLiftMessageType.AuthenticateUserRequest); - Register(GameLiftMessageType.AuthenticateUserResponse); - Register(GameLiftMessageType.MessageReceivedAcknowledge); - Register(GameLiftMessageType.MultipartMessage); - } - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/Unconnected/HandshakeMessageRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/Unconnected/HandshakeMessageRegistry.cs deleted file mode 100644 index 9bba5d8c..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Registries/Unconnected/HandshakeMessageRegistry.cs +++ /dev/null @@ -1,25 +0,0 @@ -using BeatTogether.Core.Messaging.Implementations.Registries; -using BeatTogether.Core.Messaging.Messages; -using BeatTogether.DedicatedServer.Messaging.Messages.Handshake; -using BeatTogether.MasterServer.Messaging.Enums; - -namespace BeatTogether.DedicatedServer.Messaging.Registries.Unconnected -{ - public class HandshakeMessageRegistry : BaseMessageRegistry - { - public override uint MessageGroup => 3192347326U; - - public HandshakeMessageRegistry() - { - Register(HandshakeMessageType.ClientHelloRequest); - Register(HandshakeMessageType.HelloVerifyRequest); - Register(HandshakeMessageType.ClientHelloWithCookieRequest); - Register(HandshakeMessageType.ServerHelloRequest); - Register(HandshakeMessageType.ServerCertificateRequest); - Register(HandshakeMessageType.ClientKeyExchangeRequest); - Register(HandshakeMessageType.ChangeCipherSpecRequest); - Register(HandshakeMessageType.MessageReceivedAcknowledge); - Register(HandshakeMessageType.MultipartMessage); - } - } -} diff --git a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs index 142cda79..82ca1287 100644 --- a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs +++ b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs @@ -3,7 +3,7 @@ public sealed class NodeConfiguration { public string HostName { get; set; } = "127.0.0.1"; - public string NodeVersion { get; } = "1.5.0"; + public string NodeVersion { get; } = "1.6.0"; public int BasePort { get; set; } = 30000; public int MaximumSlots { get; set; } = 10000; } diff --git a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs index 54755343..97dea86a 100644 --- a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs +++ b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs @@ -41,17 +41,16 @@ public InstanceFactory( bool AllowNE ) { - var liteNetPort = _portAllocator.AcquirePort(); - var eNetPort = _portAllocator.AcquirePort(); + var Port = _portAllocator.AcquirePort(); - if (!liteNetPort.HasValue || !eNetPort.HasValue) + if (!Port.HasValue) return null; var scope = _serviceProvider.CreateScope(); var instanceConfig = scope.ServiceProvider.GetRequiredService(); - instanceConfig.LiteNetPort = (int)liteNetPort!; - instanceConfig.ENetPort = (int)eNetPort!; + //instanceConfig.LiteNetPort = (int)liteNetPort!; + instanceConfig.Port = (int)Port!; instanceConfig.Secret = secret; instanceConfig.ServerOwnerId = managerId; instanceConfig.MaxPlayerCount = Math.Min(config.MaxPlayerCount,250); //max size of 254, id 127 routes packets to all, max is 250, last 4 ID's will be reserved for future features @@ -84,8 +83,8 @@ bool AllowNE private void HandleStopEvent(IDedicatedInstance Instance) { _instanceRegistry.RemoveInstance(Instance); - _portAllocator.ReleasePort(Instance.LiteNetPort); - _portAllocator.ReleasePort(Instance.ENetPort); + //_portAllocator.ReleasePort(Instance.LiteNetPort); + _portAllocator.ReleasePort(Instance.Port); } } } diff --git a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs index 6fc49ec6..3b9feb65 100644 --- a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs +++ b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs @@ -89,17 +89,18 @@ private Task HandlePlayerConnectedToMatchmaking(PlayerConnectedToMatchmakingServ } else { - _logger.Verbose( - "Master server notified us of connecting graph client " + - $"(RemoteEndPoint='{remoteEndPoint}', " + - $"PlayerSessionId='{playerSessionId}')." - ); - - var HandshakeRegistry = TryGetDedicatedInstance(serverSecret)? - .GetHandshakeSessionRegistry(); - HandshakeRegistry?.AddPendingPlayerSessionId(playerSessionId); - HandshakeRegistry?.AddExtraPlayerSessionData(playerSessionId, PlayerClientVersion, PlayerPlatform, PlayerPlatformUserId); + //_logger.Verbose( + // "Master server notified us of connecting graph client " + + // $"(RemoteEndPoint='{remoteEndPoint}', " + + // $"PlayerSessionId='{playerSessionId}')." + //); + + //var HandshakeRegistry = TryGetDedicatedInstance(serverSecret)? + // .GetHandshakeSessionRegistry(); + //HandshakeRegistry?.AddPendingPlayerSessionId(playerSessionId); + //HandshakeRegistry?.AddExtraPlayerSessionData(playerSessionId, PlayerClientVersion, PlayerPlatform, PlayerPlatformUserId); } + TryGetDedicatedInstance(serverSecret)?.GetPlayerRegistry().AddExtraPlayerSessionData(playerSessionId, PlayerClientVersion, PlayerPlatform, PlayerPlatformUserId); _autobus.Publish(new NodeReceivedPlayerEncryptionEvent(_configuration.HostName, @event.RemoteEndPoint)); return Task.CompletedTask; diff --git a/BeatTogether.DedicatedServer.Node/NodeService.cs b/BeatTogether.DedicatedServer.Node/NodeService.cs index 064f7f7a..14f2b04d 100644 --- a/BeatTogether.DedicatedServer.Node/NodeService.cs +++ b/BeatTogether.DedicatedServer.Node/NodeService.cs @@ -76,10 +76,9 @@ public async Task CreateMatchmakingServer(Creat await matchmakingServer.Start(); return new CreateMatchmakingServerResponse( CreateMatchmakingServerError.None, - $"{_configuration.HostName}:{matchmakingServer.LiteNetPort}", + $"{_configuration.HostName}:{matchmakingServer.Port}", _packetEncryptionLayer.Random, - _packetEncryptionLayer.KeyPair.PublicKey, - $"{_configuration.HostName}:{matchmakingServer.ENetPort}" + _packetEncryptionLayer.KeyPair.PublicKey ); } @@ -121,12 +120,12 @@ private void HandleStopEvent(IDedicatedInstance inst) } private void HandleUpdatePlayerEvent(IPlayer player) { - _autobus.Publish(new PlayerJoinEvent(player.Secret, ((IPEndPoint)player.Endpoint).ToString(), player.UserId)); + _autobus.Publish(new PlayerJoinEvent(player.Instance._configuration.Secret, ((IPEndPoint)player.Endpoint).ToString(), player.UserId)); } private void HandlePlayerDisconnectEvent(IPlayer player) { _packetEncryptionLayer.RemoveEncryptedEndPoint((IPEndPoint)player.Endpoint); - _autobus.Publish(new PlayerLeaveServerEvent(player.Secret, player.UserId, ((IPEndPoint)player.Endpoint).ToString())); + _autobus.Publish(new PlayerLeaveServerEvent(player.Instance._configuration.Secret, player.UserId, ((IPEndPoint)player.Endpoint).ToString())); } private void HandlePlayerLeaveBeforeJoining(string Secret, EndPoint endPoint, string[] Players) { diff --git a/BeatTogether.DedicatedServer.Node/PortAllocator.cs b/BeatTogether.DedicatedServer.Node/PortAllocator.cs index 5fcd20be..f3abc82d 100644 --- a/BeatTogether.DedicatedServer.Node/PortAllocator.cs +++ b/BeatTogether.DedicatedServer.Node/PortAllocator.cs @@ -9,8 +9,6 @@ public sealed class PortAllocator : IPortAllocator { private readonly NodeConfiguration _configuration; - private readonly object _lock = new(); - private readonly HashSet _acquiredPorts = new(); private readonly HashSet _releasedPorts = new(); @@ -26,32 +24,27 @@ public PortAllocator( public int? AcquirePort() { - lock (_lock) + if (_acquiredPorts.Count >= _configuration.MaximumSlots) + return null; + int port; + if (_releasedPorts.Any()) { - if (_acquiredPorts.Count >= _configuration.MaximumSlots) - return null; - int port; - if (_releasedPorts.Any()) - { - port = _releasedPorts.First(); - _releasedPorts.Remove(port); - } - else - port = ++_lastPort; - _acquiredPorts.Add(port); - return port; + port = _releasedPorts.First(); + _releasedPorts.Remove(port); } + else + port = ++_lastPort; + _acquiredPorts.Add(port); + return port; } public bool ReleasePort(int port) { - lock (_lock) - { - if (!_acquiredPorts.Remove(port)) - return false; - _releasedPorts.Add(port); - return true; - } + + if (!_acquiredPorts.Remove(port)) + return false; + _releasedPorts.Add(port); + return true; } } } From 355656f8d8f6187b4c53f75a5164aa9ccda8cc87 Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 1 Apr 2024 01:47:16 +0100 Subject: [PATCH 082/120] Completely removed lnl --- .../Events/NodeOnlineEvent.cs | 2 +- .../Events/NodeStartedEvent.cs | 2 +- .../Abstractions/BasePacketHandler.cs | 2 +- .../Abstractions/IPacketDispatcher.cs | 24 +- .../Abstractions/IPacketHandler.cs | 2 +- .../CommandHandlers/HelpCommandHandler.cs | 9 +- .../SetBeatmapRoutingHandler.cs | 5 +- .../SetChromaCommandHandler.cs | 5 +- .../SetCountdownTimeHandler.cs | 5 +- .../SetMappingExtensionsHandler.cs | 5 +- .../SetNoodleExtensionsHandler.cs | 5 +- .../SetPerPlayerDiffHandler.cs | 5 +- .../CommandHandlers/SetPerPlayerModHandler.cs | 5 +- .../CommandHandlers/SetResultsTimeHandler.cs | 5 +- .../CommandHandlers/SetServerNameHandler.cs | 5 +- .../SetWelcomeMessageHandler.cs | 5 +- .../StartBeatmapTimeHandler.cs | 5 +- .../Configuration/InstanceConfiguration.cs | 1 + .../DedicatedInstance.cs | 55 +- .../ENet/ENetServer.cs | 36 +- .../Encryption/EncryptedPacketWriter.cs | 2 +- .../Encryption/PacketEncryptionLayer.cs | 2 +- .../Managers/GameplayManager.cs | 27 +- .../Managers/LobbyManager.cs | 38 +- .../PacketDispatcher.cs | 34 +- .../MPChat/MpcCapabilitiesPacketHandler.cs | 8 +- .../MPChat/MpcTextChatPacketHandler.cs | 6 +- .../ClearRecommendedBeatmapPacketHandler.cs | 6 +- .../GetCountdownEndTimePacketHandler.cs | 6 +- .../MenuRpc/GetIsInLobbyPacketHandler.cs | 6 +- .../MenuRpc/GetIsReadyPacketHandler.cs | 6 +- .../GetMultiplayerGameStatePacketHandler.cs | 6 +- ...ersPermissionConfigurationPacketHandler.cs | 6 +- .../GetRecommendedBeatmapPacketHandler.cs | 6 +- .../GetRecommendedModifiersPacketHandler.cs | 6 +- .../MenuRpc/GetSelectedBeatmapHandler.cs | 10 +- .../GetSelectedGameplayModifiersHandler.cs | 10 +- .../MenuRpc/GetStartedLevelPacketHandler.cs | 12 +- .../MenuRpc/RequestKickPlayerPacketHandler.cs | 6 +- .../MenuRpc/SetIsInLobbyPacketHandler.cs | 14 +- .../MenuRpc/SetIsReadyPacketHandler.cs | 6 +- .../SetRecommendedBeatmapPacketHandler.cs | 7 +- .../DediPacketSetNewManagerHandler.cs | 6 +- .../GetExtraPlayerDataPacketHandler.cs | 6 +- .../PacketHandlers/PingPacketHandler.cs | 6 +- .../PlayerIdentityPacketHandler.cs | 4 +- .../PlayerLatencyPacketHandler.cs | 6 +- .../PlayerSortOrderPacketHandler.cs | 6 +- .../PacketHandlers/SyncTimePacketHandler.cs | 6 +- .../PacketSource.cs | 23 +- BeatTogether.DedicatedServer.Kernel/Player.cs | 2 +- .../Abstractions/BasePacketRegistry.cs | 123 +++++ .../Abstractions/BaseRpcPacket.cs | 12 +- .../Abstractions/BaseRpcWithValuesPacket.cs | 12 +- .../Abstractions/INetSerializable.cs | 11 + .../Abstractions/IPacketLayer.cs | 11 + .../Abstractions/IPacketRegistry.cs | 132 +++++ ...tTogether.DedicatedServer.Messaging.csproj | 1 - ...atarDataMultiplayerAvatarsDataConverter.cs | 2 +- .../Delegates/PacketFactory.cs | 2 +- .../Extensions/BinaryReadWriteExtension.cs | 2 +- .../Extensions/MemoryBufferExtensions.cs | 176 ------- .../Extensions/ServiceCollectionExtensions.cs | 2 +- .../Extensions/SpanBufferExtensions.cs | 22 +- .../Extensions/SpanBufferReaderExtensions.cs | 96 +++- .../Extensions/SpanBufferWriterExtensions.cs | 58 +++ .../Models/AvatarData.cs | 4 +- .../Models/BeatmapIdentifier.cs | 7 +- .../Models/BitMask128.cs | 4 +- .../Models/BitMask256.cs | 4 +- .../Models/ByteArray.cs | 8 +- .../Models/Color.cs | 4 +- .../Models/ColorNoAlpha.cs | 5 +- .../Models/ColorScheme.cs | 5 +- .../Models/ConnectionRequestData.cs | 6 +- .../Models/GameplayModifiers.cs | 4 +- .../Models/LevelCompletionResults.cs | 6 +- .../Models/MultiplayerAvatarsData.cs | 4 +- .../MultiplayerLevelCompletionResults.cs | 6 +- .../Models/NodePoseSyncState.cs | 4 +- .../Models/NoteCutInfo.cs | 6 +- .../Models/NoteMissInfo.cs | 6 +- .../Models/PlayerPermissionConfiguration.cs | 6 +- .../Models/PlayerSpecificSettings.cs | 6 +- .../Models/PlayerSpecificSettingsAtStart.cs | 4 +- .../Models/PlayersPermissionConfiguration.cs | 4 +- .../Models/Pose.cs | 5 +- .../Models/Quaternion.cs | 6 +- .../Models/StandardScoreSyncState.cs | 6 +- .../Models/Vector3.cs | 6 +- .../Packets/KickPlayerPacket.cs | 6 +- .../GameplayRpc/LevelFinishedPacket.cs | 2 +- .../GameplayRpc/NoteCutPacket.cs | 2 +- .../GameplayRpc/NoteMissPacket.cs | 2 +- .../GameplayRpc/NoteSpawn.cs | 2 +- .../GameplayRpc/ObstacleSpawnPacket.cs | 2 +- .../SetGameplaySceneReadyPacket.cs | 2 +- .../SetGameplaySceneSyncFinishedPacket.cs | 4 +- .../SetPlayerDidConnectLatePacket.cs | 4 +- .../GameplayRpc/SetSongStartTimePacket.cs | 2 +- .../GameplayRpc/SliderSpawnPacket.cs | 2 +- .../MPChatPackets/MpcBasePacket.cs | 4 +- .../MPChatPackets/MpcCapabilitiesPacket.cs | 2 +- .../MPChatPackets/MpcTextChatPacket.cs | 2 +- .../MPChatPackets/MpcVoicePacket.cs | 4 +- .../MenuRpc/ClearSelectedBeatmap.cs | 1 - .../MenuRpc/GetIsEntitledToLevelPacket.cs | 4 +- .../MenuRpc/RequestKickPlayerPacket.cs | 4 +- .../MenuRpc/SetCountdownEndTimePacket.cs | 2 +- .../MenuRpc/SetIsEntitledToLevelPacket.cs | 4 +- .../MenuRpc/SetIsInLobbyPacket.cs | 2 +- .../MenuRpc/SetIsReadyPacket.cs | 2 +- .../MenuRpc/SetIsStartButtonEnabledPacket.cs | 4 +- .../MenuRpc/SetMultiplayerGameStatePacket.cs | 4 +- .../MenuRpc/SetOwnedSongPacksPacket.cs | 2 +- ...PlayersMissingEntitlementsToLevelPacket.cs | 4 +- ...SetPlayersPermissionConfigurationPacket.cs | 2 +- .../MenuRpc/SetRecommendedBeatmapPacket.cs | 2 +- .../MenuRpc/SetRecommendedModifiersPacket.cs | 2 +- .../MenuRpc/SetSelectedBeatmap.cs | 2 +- .../MenuRpc/SetSelectedGameplayModifiers.cs | 2 +- .../MenuRpc/SetStartGameTimePacket.cs | 2 +- .../MenuRpc/StartLevelPacket.cs | 2 +- .../MpCorePackets/DediPacketSetNewManager.cs | 6 +- .../MpCorePackets/GetMpPlayerData.cs | 4 +- .../MpCorePackets/MpBeatmapPacket.cs | 6 +- .../MpNodePoseSyncStatePacket.cs | 4 +- .../MpCorePackets/MpPlayerData.cs | 4 +- .../NodePoseSyncStateDeltaPacket.cs | 6 +- .../NodePoseSyncStatePacket.cs | 6 +- .../ScoreSyncStateDeltaPacket.cs | 6 +- .../ScoreSyncStatePacket.cs | 4 +- .../Packets/PingPacket.cs | 4 +- .../Packets/PlayerAvatarPacket.cs | 4 +- .../Packets/PlayerConnectedPacket.cs | 6 +- .../Packets/PlayerDisconnectedPacket.cs | 6 +- .../Packets/PlayerIdentityPacket.cs | 4 +- .../Packets/PlayerLatencyPacket.cs | 4 +- .../Packets/PlayerSortOrderPacket.cs | 6 +- .../Packets/PlayerStatePacket.cs | 4 +- .../Packets/PongPacket.cs | 4 +- .../Packets/SyncTimePacket.cs | 4 +- .../Registries/GameplayRpcPacketRegistry.cs | 2 +- .../Registries/MenuRpcPacketRegistry.cs | 2 +- .../MultiplayerCorePacketRegistry.cs | 2 +- .../MultiplayerSessionPacketRegistry.cs | 2 +- .../Registries/PacketRegistry.cs | 2 +- .../Structs/AvatarSystemIdentifier.cs | 7 +- .../Structs/MultiplayerAvatarData.cs | 8 +- .../Util/SpanBuffer.cs | 488 ++++++++++++++++++ .../Configuration/NodeConfiguration.cs | 6 +- .../Extensions/HostBuilderExtensions.cs | 2 +- .../MasterServerEventHandler.cs | 6 +- 153 files changed, 1348 insertions(+), 631 deletions(-) create mode 100644 BeatTogether.DedicatedServer.Messaging/Abstractions/BasePacketRegistry.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Abstractions/INetSerializable.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Abstractions/IPacketLayer.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Abstractions/IPacketRegistry.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Extensions/MemoryBufferExtensions.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferWriterExtensions.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Util/SpanBuffer.cs diff --git a/BeatTogether.DedicatedServer.Interface/Events/NodeOnlineEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/NodeOnlineEvent.cs index d90479f7..284550dc 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/NodeOnlineEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/NodeOnlineEvent.cs @@ -1,4 +1,4 @@ -using System.Net; +using System; namespace BeatTogether.DedicatedServer.Interface.Events { diff --git a/BeatTogether.DedicatedServer.Interface/Events/NodeStartedEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/NodeStartedEvent.cs index fefe835d..5ddee634 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/NodeStartedEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/NodeStartedEvent.cs @@ -1,4 +1,4 @@ -using System.Net; +using System; namespace BeatTogether.DedicatedServer.Interface.Events { diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/BasePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/BasePacketHandler.cs index c290a7e1..46935353 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/BasePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/BasePacketHandler.cs @@ -1,4 +1,4 @@ -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Abstractions; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs index 81ae9192..1cefe924 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs @@ -1,20 +1,20 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Enums; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Messaging.Abstractions; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { public interface IPacketDispatcher { - void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod deliveryMethod); - void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMethod deliveryMethod); - void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable packet, DeliveryMethod deliveryMethod); - void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); - void SendToNearbyPlayers(INetSerializable packet, DeliveryMethod deliveryMethod); - void SendToNearbyPlayers(INetSerializable[] packets, DeliveryMethod deliveryMethod); - void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, DeliveryMethod deliveryMethod); - void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); - void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod); - void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); + void SendToPlayer(IPlayer player, INetSerializable packet, IgnoranceChannelTypes deliveryMethod); + void SendToPlayer(IPlayer player, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod); + void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable packet, IgnoranceChannelTypes deliveryMethod); + void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod); + void SendToNearbyPlayers(INetSerializable packet, IgnoranceChannelTypes deliveryMethod); + void SendToNearbyPlayers(INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod); + void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, IgnoranceChannelTypes deliveryMethod); + void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod); + void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, IgnoranceChannelTypes deliveryMethod); + void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod); /* Task SendToNearbyPlayersAndAwait(INetSerializable packet, DeliveryMethod deliveryMethod); diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketHandler.cs index fd1cbacf..f52a69cf 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketHandler.cs @@ -1,4 +1,4 @@ -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Abstractions; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/HelpCommandHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/HelpCommandHandler.cs index ca5007ab..0c85c67a 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/HelpCommandHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/HelpCommandHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; using System.Text; @@ -25,12 +26,12 @@ public override void Handle(IPlayer player, HelpCommand command) _packetDisapatcher.SendToPlayer(player, new MpcTextChatPacket { Text = "Command you searched help for does not exist or is above your access level" - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } _packetDisapatcher.SendToPlayer(player, new MpcTextChatPacket { Text = textCommand.CommandName + " : " + textCommand.Description + " : ShortHand: " + textCommand.ShortHandName - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); return; } string[] CommandList = _commandRepository.GetTextCommandNames(player.GetAccessLevel()); @@ -43,7 +44,7 @@ public override void Handle(IPlayer player, HelpCommand command) _packetDisapatcher.SendToPlayer(player, new MpcTextChatPacket { Text = Response.ToString() - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetBeatmapRoutingHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetBeatmapRoutingHandler.cs index 6a20a14a..3dc42bdd 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetBeatmapRoutingHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetBeatmapRoutingHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; @@ -22,7 +23,7 @@ public override void Handle(IPlayer player, SetNoteRouting command) _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Beatmap notes: " + command.Enabled - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetChromaCommandHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetChromaCommandHandler.cs index 5521d2c3..4ba6d6cd 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetChromaCommandHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetChromaCommandHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; @@ -22,7 +23,7 @@ public override void Handle(IPlayer player, SetChroma command) _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Chroma: " + command.Enabled - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetCountdownTimeHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetCountdownTimeHandler.cs index 4d7152c0..34c473f1 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetCountdownTimeHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetCountdownTimeHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; @@ -22,7 +23,7 @@ public override void Handle(IPlayer player, SetCountdown command) _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Countdown time is now: " + command.Countdown - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetMappingExtensionsHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetMappingExtensionsHandler.cs index be6b056d..98d3ac8d 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetMappingExtensionsHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetMappingExtensionsHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; @@ -22,7 +23,7 @@ public override void Handle(IPlayer player, SetMappingExtensions command) _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Mapping Extensions: " + command.Enabled - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetNoodleExtensionsHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetNoodleExtensionsHandler.cs index 1f659ea2..9c61dc41 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetNoodleExtensionsHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetNoodleExtensionsHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; @@ -22,7 +23,7 @@ public override void Handle(IPlayer player, SetNoodleExtensions command) _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Noodle Extensions: " + command.Enabled - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs index 143ba9ee..ff743992 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; @@ -22,7 +23,7 @@ public override void Handle(IPlayer player, SetPerPlayerDifficulties command) _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Per player difficulties: " + command.Enabled - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs index 87da208a..bec00152 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; @@ -22,7 +23,7 @@ public override void Handle(IPlayer player, SetPerPlayerModifiers command) _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Per player modifiers: " + command.Enabled - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetResultsTimeHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetResultsTimeHandler.cs index 4ca980cb..0fb524db 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetResultsTimeHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetResultsTimeHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; @@ -22,7 +23,7 @@ public override void Handle(IPlayer player, SetResultsTime command) _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Results screen time is now: " + command.Countdown - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetServerNameHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetServerNameHandler.cs index 3585aa7e..115d3b83 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetServerNameHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetServerNameHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; @@ -25,7 +26,7 @@ public override void Handle(IPlayer player, SetServerName command) _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Server name is now: " + command.Name - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetWelcomeMessageHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetWelcomeMessageHandler.cs index 98a99edb..a5a591af 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetWelcomeMessageHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetWelcomeMessageHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; @@ -24,7 +25,7 @@ public override void Handle(IPlayer player, SetWelcomeMessage command) _packetDisapatcher.SendToPlayer(player, new MpcTextChatPacket { Text = "Server name is now: " + command.Text - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/StartBeatmapTimeHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/StartBeatmapTimeHandler.cs index 856610b8..38d69d9e 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/StartBeatmapTimeHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/StartBeatmapTimeHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; @@ -22,7 +23,7 @@ public override void Handle(IPlayer player, SetBeatmapStartTime command) _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Beatmap start time is now: " + command.Countdown - }, LiteNetLib.Enums.DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs index a8e9a827..2ba9300f 100644 --- a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs +++ b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs @@ -31,6 +31,7 @@ public sealed class InstanceConfiguration public long SendPlayersWithoutEntitlementToSpectateTimeout { get; set; } = 30000L; public int MaxLengthCommand { get; set; } = 200; public bool ApplyNoFailModifier { get; set; } = true; + public int DisableNotesPlayerCount { get; set; } = 16; } public sealed class CountdownConfig diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index b493cb98..7a93aa9d 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -16,10 +16,10 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Enums; +using BeatTogether.DedicatedServer.Messaging.Abstractions; + //using BeatTogether.LiteNetLib.Sources; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; //using BeatTogether.LiteNetLib; //using BeatTogether.LiteNetLib.Abstractions; @@ -29,10 +29,11 @@ //using BeatTogether.LiteNetLib.Sources; //using Microsoft.Extensions.DependencyInjection; using Serilog; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; namespace BeatTogether.DedicatedServer.Kernel { - public sealed class DedicatedInstance : ENetServer, /*LiteNetServer,*/ IDedicatedInstance + public sealed class DedicatedInstance : ENetServer, IDedicatedInstance { // Milliseconds instance will wait for a player to connect. public const int WaitForPlayerTimeLimit = 10000; @@ -185,7 +186,7 @@ public async Task Stop(CancellationToken cancellationToken = default) PacketDispatcher.SendToNearbyPlayers(new KickPlayerPacket { DisconnectedReason = DisconnectedReason.ServerTerminated - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); KickAllPeers(); @@ -240,7 +241,7 @@ public void SetState(MultiplayerGameState state) PacketDispatcher.SendToNearbyPlayers(new SetMultiplayerGameStatePacket() { State = state - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); GameIsInLobby?.Invoke(_configuration.Secret, state == MultiplayerGameState.Lobby); } @@ -383,7 +384,7 @@ public void SetState(MultiplayerGameState state) fullStateUpdateFrequency = 100L, deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() }, - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); return player; @@ -398,7 +399,7 @@ public void SetState(MultiplayerGameState state) return null; } - public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, DeliveryMethod method) + public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, IgnoranceChannelTypes method) { ConnectedMessageSource.OnReceive(remoteEndPoint, ref reader, method); } @@ -459,7 +460,7 @@ public override void OnConnect(EndPoint endPoint) }, }; - PacketDispatcher.SendToPlayer(player, Player_ConnectPacket, DeliveryMethod.ReliableOrdered); + PacketDispatcher.SendToPlayer(player, Player_ConnectPacket, IgnoranceChannelTypes.Reliable); List MakeBigPacketToSendToPlayer = new(); foreach (IPlayer p in PlayersAtJoin) @@ -482,7 +483,7 @@ public override void OnConnect(EndPoint endPoint) } foreach (var SubPacket in MakeBigPacketToSendToPlayer.Chunk(20)) { - PacketDispatcher.SendToPlayer(player, SubPacket.ToArray(), DeliveryMethod.ReliableOrdered); + PacketDispatcher.SendToPlayer(player, SubPacket.ToArray(), IgnoranceChannelTypes.Reliable); } //End of sending other players to player @@ -508,7 +509,7 @@ public override void OnConnect(EndPoint endPoint) } } } - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } if (player.Platform == Enums.Platform.Test) //If the player is a bot, send permissions. Normal players request this in a packet when they join @@ -540,7 +541,7 @@ public override void OnConnect(EndPoint endPoint) { PlayersPermission = playerPermissionConfigurations } - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } //Start of sending player avatars and states of other players to new player @@ -564,7 +565,7 @@ public override void OnConnect(EndPoint endPoint) // Send all player avatars and states to just joined player - PacketDispatcher.SendFromPlayerToPlayer(p, player, SendToPlayerFromPlayers, DeliveryMethod.ReliableOrdered); + PacketDispatcher.SendFromPlayerToPlayer(p, player, SendToPlayerFromPlayers, IgnoranceChannelTypes.Reliable); //Sends them one by one to avoid server lag } } @@ -579,7 +580,7 @@ public override void OnConnect(EndPoint endPoint) PlatformID = player.PlatformUserId!, Platform = player.Platform.Convert(), ClientVersion = player.ClientVersion! - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } @@ -588,7 +589,7 @@ public override void OnConnect(EndPoint endPoint) { if (p.CanTextChat) { - PacketDispatcher.SendToPlayer(p, packet, DeliveryMethod.ReliableOrdered); + PacketDispatcher.SendToPlayer(p, packet, IgnoranceChannelTypes.Reliable); } } } @@ -600,23 +601,17 @@ public void DisconnectPlayer(string UserId) //Used by master servers kick player PacketDispatcher.SendToPlayer(player, new KickPlayerPacket { DisconnectedReason = DisconnectedReason.Kicked - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } - public override void OnDisconnect(EndPoint endPoint, DisconnectReason reason) + public override void OnDisconnect(EndPoint endPoint) { _logger.Information( "Endpoint disconnected " + - $"(RemoteEndPoint='{endPoint}', DisconnectReason={reason})." + $"(RemoteEndPoint='{endPoint}')." ); - if (reason == DisconnectReason.Reconnect || reason == DisconnectReason.PeerToPeerConnection) - { - _logger.Information( - "Endpoint reconnecting or is peer to peer." - ); - return; - } + if (_playerRegistry.TryGetPlayer(endPoint, out var player)) { //Sends to all players that they have disconnected @@ -624,7 +619,7 @@ public override void OnDisconnect(EndPoint endPoint, DisconnectReason reason) PacketDispatcher.SendFromPlayer(player, new PlayerDisconnectedPacket { DisconnectedReason = DisconnectedReason.ClientConnectionClosed - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); if (_configuration.ServerOwnerId == player.UserId) _configuration.ServerOwnerId = ""; @@ -659,14 +654,14 @@ public override void OnDisconnect(EndPoint endPoint, DisconnectReason reason) } } } - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); // Disable start button if they are server owner without selected song if (serverOwner.BeatmapIdentifier == null) PacketDispatcher.SendToPlayer(serverOwner, new SetIsStartButtonEnabledPacket { Reason = CannotStartGameReason.NoSongSelected - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } @@ -674,7 +669,7 @@ public override void OnDisconnect(EndPoint endPoint, DisconnectReason reason) { fullStateUpdateFrequency = 100L, deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); if (_playerRegistry.GetPlayerCount() == 0) { @@ -709,7 +704,7 @@ private async void SendSyncTime(CancellationToken cancellationToken) PacketDispatcher.SendToPlayer(player, new SyncTimePacket() { SyncTime = player.SyncTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } try { diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs index 1c7c2a6d..d948d1df 100644 --- a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs @@ -2,17 +2,15 @@ using System.Buffers; using System.Collections.Generic; using System.Net; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using BeatTogether.DedicatedServer.Ignorance.ENet; using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Ignorance.Util; using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Enums; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Sources; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; using Krypton.Buffers; using Serilog; @@ -157,7 +155,7 @@ private void HandleIncomingEvents() return; } // Process actual payload - var deliveryMethod = e.Channel == 0 ? DeliveryMethod.ReliableOrdered : DeliveryMethod.Unreliable; + var deliveryMethod = e.Channel == 0 ? IgnoranceChannelTypes.Reliable : IgnoranceChannelTypes.Unreliable; OnReceive(connection.EndPoint, ref bufferReader, deliveryMethod); } } @@ -224,7 +222,7 @@ public void KickPeer(uint peerId, bool sendKick = true) connection.NativePeerId, connection.EndPoint); connection.State = ENetConnectionState.Disconnected; - OnDisconnect(connection.EndPoint, DisconnectReason.DisconnectPeerCalled); + OnDisconnect(connection.EndPoint); if (!IsAlive || !sendKick) // Can't or won't send kick @@ -247,7 +245,7 @@ public void KickAllPeers() #region Send - public void Send(IPlayer player, ReadOnlySpan message, DeliveryMethod deliveryMethod) + public void Send(IPlayer player, ReadOnlySpan message, IgnoranceChannelTypes deliveryMethod) { if (!player.ENetPeerId.HasValue) // Not an ENet peer @@ -256,7 +254,7 @@ public void Send(IPlayer player, ReadOnlySpan message, DeliveryMethod deli Send(player.ENetPeerId.Value, message, deliveryMethod); } - public void Send(uint peerId, ReadOnlySpan message, DeliveryMethod deliveryMethod) + public void Send(uint peerId, ReadOnlySpan message, IgnoranceChannelTypes deliveryMethod) { if (!_connections.TryGetValue(peerId, out var connection)) // Invalid peer @@ -265,7 +263,7 @@ public void Send(uint peerId, ReadOnlySpan message, DeliveryMethod deliver Send(connection, message, deliveryMethod); } - public void Send(ENetConnection connection, ReadOnlySpan message, DeliveryMethod deliveryMethod) + public void Send(ENetConnection connection, ReadOnlySpan message, IgnoranceChannelTypes deliveryMethod) { if (!IsAlive) return; @@ -275,11 +273,11 @@ public void Send(ENetConnection connection, ReadOnlySpan message, Delivery return; var eNetPacket = default(Packet); - eNetPacket.Create(message.ToArray(), message.Length); - + eNetPacket.Create(message.ToArray(), message.Length, (PacketFlags)deliveryMethod); + _ignorance.Outgoing.Enqueue(new IgnoranceOutgoingPacket() { - Channel = (byte)(deliveryMethod == DeliveryMethod.ReliableOrdered ? 0 : 1), // 1 = Unreliable + Channel = (byte)(deliveryMethod == IgnoranceChannelTypes.Reliable ? 0 : 1), // 1 = Unreliable, 0 = reliable NativePeerId = connection.NativePeerId, Payload = eNetPacket }); @@ -325,7 +323,7 @@ public virtual void OnConnect(EndPoint endPoint) { } - public virtual void OnDisconnect(EndPoint endPoint, DisconnectReason reason) + public virtual void OnDisconnect(EndPoint endPoint) { } @@ -333,18 +331,10 @@ public virtual void OnLatencyUpdate(EndPoint endPoint, int latency) { } - public virtual void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, DeliveryMethod method) + public virtual void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, IgnoranceChannelTypes method) { } -/* public virtual void SendAsync(EndPoint endPoint, INetSerializable packet) - { - Span buffer = stackalloc byte[412]; - SpanBuffer bufferWriter = new SpanBuffer(buffer); - packet.WriteTo(ref bufferWriter); - SendAsync(endPoint, new Memory(bufferWriter.Data.ToArray())); - }*/ - #endregion } } \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs index 64797183..dffec1bd 100644 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs +++ b/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs @@ -1,7 +1,7 @@ using System; using System.Security.Cryptography; using BeatTogether.DedicatedServer.Kernel.Encryption.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; using Krypton.Buffers; namespace BeatTogether.DedicatedServer.Kernel.Encryption diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs index ff61a5be..a014f519 100644 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs @@ -7,7 +7,7 @@ using BeatTogether.Core.Security.Abstractions; using BeatTogether.Core.Security.Models; using BeatTogether.DedicatedServer.Kernel.Encryption.Abstractions; -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Abstractions; using Krypton.Buffers; using Serilog; diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs index 7d490ac9..020ad1b6 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs @@ -1,10 +1,11 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; -using BeatTogether.LiteNetLib.Enums; +//using BeatTogether.LiteNetLib.Enums; using Serilog; using System; using System.Collections.Concurrent; @@ -132,7 +133,7 @@ public async void StartSong(CancellationToken cancellationToken) }); // Wait for scene ready - _packetDispatcher.SendToNearbyPlayers(new GetGameplaySceneReadyPacket(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToNearbyPlayers(new GetGameplaySceneReadyPacket(), IgnoranceChannelTypes.Reliable); sceneReadyCts.CancelAfter((int)((SceneLoadTimeLimit + (PlayersAtStart.Count * 0.3f)) * 1000)); await Task.WhenAll(_sceneReadyTcs.Values.Select(p => p.Task)); @@ -143,13 +144,13 @@ public async void StartSong(CancellationToken cancellationToken) { ActivePlayerSpecificSettingsAtStart = _playerSpecificSettings.Values.ToArray() } - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); // Set scene sync finished State = GameplayManagerState.SongLoad; //Wait for players to have the song ready - _packetDispatcher.SendToNearbyPlayers(new GetGameplaySongReadyPacket(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToNearbyPlayers(new GetGameplaySongReadyPacket(), IgnoranceChannelTypes.Reliable); songReadyCts.CancelAfter((int)((SongLoadTimeLimit + (PlayersAtStart.Count*0.3f)) * 1000)); await Task.WhenAll(_songReadyTcs.Values.Select(p => p.Task)); @@ -173,7 +174,7 @@ public async void StartSong(CancellationToken cancellationToken) _packetDispatcher.SendToNearbyPlayers(new SetSongStartTimePacket { StartTime = _songStartTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); //Initiates the song start process for forced late joiners foreach(IPlayer p in _playerRegistry.Players) @@ -185,7 +186,7 @@ public async void StartSong(CancellationToken cancellationToken) Beatmap = CurrentBeatmap, Modifiers = CurrentModifiers, StartTime = _songStartTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } @@ -200,7 +201,7 @@ public async void StartSong(CancellationToken cancellationToken) SetBeatmap(null, new()); ResetValues(); _instance.SetState(MultiplayerGameState.Lobby); - _packetDispatcher.SendToNearbyPlayers( new ReturnToMenuPacket(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToNearbyPlayers( new ReturnToMenuPacket(), IgnoranceChannelTypes.Reliable); } private void ResetValues() @@ -227,7 +228,7 @@ public void HandleGameSceneLoaded(IPlayer player, SetGameplaySceneReadyPacket pa if (_instance.State != MultiplayerGameState.Game || State == GameplayManagerState.Results || State == GameplayManagerState.None) //Returns player to lobby { - _packetDispatcher.SendToPlayer(player, new ReturnToMenuPacket(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToPlayer(player, new ReturnToMenuPacket(), IgnoranceChannelTypes.Reliable); LeaveGameplay(player.UserId); return; } @@ -242,8 +243,8 @@ public void HandleGameSceneLoaded(IPlayer player, SetGameplaySceneReadyPacket pa ActivePlayerSpecificSettingsAtStart = _playerSpecificSettings.Values.ToArray() }, SessionGameId = SessionGameId - }, DeliveryMethod.ReliableOrdered); - _packetDispatcher.SendToPlayer(player, new GetGameplaySongReadyPacket(), DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); + _packetDispatcher.SendToPlayer(player, new GetGameplaySongReadyPacket(), IgnoranceChannelTypes.Reliable); } } @@ -256,7 +257,7 @@ public void HandleGameSongLoaded(IPlayer player) } if (_instance.State != MultiplayerGameState.Game || State == GameplayManagerState.Results || State == GameplayManagerState.None) //Player is sent back to lobby { - _packetDispatcher.SendToPlayer(player, new ReturnToMenuPacket(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToPlayer(player, new ReturnToMenuPacket(), IgnoranceChannelTypes.Reliable); HandlePlayerLeaveGameplay(player); return; } @@ -265,7 +266,7 @@ public void HandleGameSongLoaded(IPlayer player) _packetDispatcher.SendToPlayer(player, new SetSongStartTimePacket { StartTime = _songStartTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } public void HandleLevelFinished(IPlayer player, LevelFinishedPacket packet) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 2ae0fffc..281fd3cd 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Kernel.Enums; @@ -10,7 +11,6 @@ using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; /*Lobby manager code @@ -117,7 +117,7 @@ public void ForceStartBeatmapUpdate() { LevelId = SelectedBeatmap.LevelId, Entitlement = EntitlementStatus.Ok - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } //The clients need to be sent that all the payers have OK entitlement @@ -149,7 +149,7 @@ public void ForceStartBeatmapUpdate() { LevelId = SelectedBeatmap.LevelId, Entitlement = EntitlementStatus.Ok - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); p.ForceLateJoin = true; } } @@ -172,7 +172,7 @@ public void Update() _packetDispatcher.SendToPlayer(OldManager, new SetIsStartButtonEnabledPacket { Reason = CannotStartGameReason.None - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); if (ForceStartSelectedBeatmap) { @@ -192,7 +192,7 @@ public void Update() PlayersWithoutEntitlements = _playerRegistry.Players .Where(p => (p.GetEntitlement(player.BeatmapIdentifier.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) && !p.IsSpectating && p.WantsToPlayNextLevel) .Select(p => p.UserId).ToArray() - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); _logger.Debug("Sent missing entitlement packet"); } } @@ -207,7 +207,7 @@ public void Update() _packetDispatcher.SendToPlayer(serverOwner!, new SetIsStartButtonEnabledPacket { Reason = GetCannotStartGameReason(serverOwner!, allPlayersOwnBeatmap) - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } _AllOwnMap = allPlayersOwnBeatmap; @@ -276,7 +276,7 @@ private void CountingDown(bool isReady, bool NotStartable) { LevelId = SelectedBeatmap!.LevelId, Entitlement = EntitlementStatus.Ok - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } _logger.Debug($"All players have entitlement, starting map"); @@ -295,8 +295,8 @@ private void CountingDown(bool isReady, bool NotStartable) { //Force the player to join late p.ForceLateJoin = true; - _packetDispatcher.SendToPlayer(p, new CancelLevelStartPacket(), DeliveryMethod.ReliableOrdered); - _packetDispatcher.SendToPlayer(p, new SetIsReadyPacket() { IsReady = false }, DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToPlayer(p, new CancelLevelStartPacket(), IgnoranceChannelTypes.Reliable); + _packetDispatcher.SendToPlayer(p, new SetIsReadyPacket() { IsReady = false }, IgnoranceChannelTypes.Reliable); } } } @@ -317,9 +317,9 @@ private void UpdateBeatmap(BeatmapIdentifier? beatmap, GameplayModifiers modifie _packetDispatcher.SendToNearbyPlayers(new SetSelectedBeatmap() { Beatmap = SelectedBeatmap - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); else - _packetDispatcher.SendToNearbyPlayers(new ClearSelectedBeatmap(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToNearbyPlayers(new ClearSelectedBeatmap(), IgnoranceChannelTypes.Reliable); } if (SelectedModifiers != modifiers) { @@ -328,9 +328,9 @@ private void UpdateBeatmap(BeatmapIdentifier? beatmap, GameplayModifiers modifie _packetDispatcher.SendToNearbyPlayers(new SetSelectedGameplayModifiers() { Modifiers = SelectedModifiers - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); else - _packetDispatcher.SendToNearbyPlayers(new ClearSelectedGameplayModifiers(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToNearbyPlayers(new ClearSelectedGameplayModifiers(), IgnoranceChannelTypes.Reliable); } } @@ -372,7 +372,7 @@ private void SetCountdown(CountdownState countdownState, long countdown = 0) _packetDispatcher.SendToNearbyPlayers(new SetCountdownEndTimePacket { CountdownTime = CountdownEndTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); break; case CountdownState.StartBeatmapCountdown: if (countdown == 0) @@ -397,7 +397,7 @@ private void StartBeatmapPacket() Beatmap = SelectedBeatmap!, Modifiers = SelectedModifiers, StartTime = CountdownEndTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); return; } BeatmapDifficulty[] diff = GetSelectedBeatmapDifficulties(); @@ -411,7 +411,7 @@ private void StartBeatmapPacket() Beatmap = bm!, Modifiers = _configuration.AllowPerPlayerModifiers ? player.Modifiers : SelectedModifiers, StartTime = CountdownEndTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } @@ -420,15 +420,15 @@ private void CancelCountdown() switch (CountDownState) { case CountdownState.CountingDown or CountdownState.NotCountingDown: - _packetDispatcher.SendToNearbyPlayers(new CancelCountdownPacket(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToNearbyPlayers(new CancelCountdownPacket(), IgnoranceChannelTypes.Reliable); break; case CountdownState.StartBeatmapCountdown or CountdownState.WaitingForEntitlement: foreach (IPlayer player in _playerRegistry.Players) //This stays because players dont send they are un-ready after the level is canceled causing bad client behaviour { player.IsReady = false; } - _packetDispatcher.SendToNearbyPlayers(new CancelLevelStartPacket(), DeliveryMethod.ReliableOrdered); - _packetDispatcher.SendToNearbyPlayers(new SetIsReadyPacket() { IsReady = false }, DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToNearbyPlayers(new CancelLevelStartPacket(), IgnoranceChannelTypes.Reliable); + _packetDispatcher.SendToNearbyPlayers(new SetIsReadyPacket() { IsReady = false }, IgnoranceChannelTypes.Reliable); break; default: _logger.Warning("Canceling countdown when there is no countdown to cancel"); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index f2d3c161..5e5f0aab 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -1,14 +1,14 @@ using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Enums; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; using Serilog; using BeatTogether.DedicatedServer.Kernel.ENet; namespace BeatTogether.DedicatedServer.Kernel { - public sealed class PacketDispatcher : /*ConnectedMessageDispatcher,*/ IPacketDispatcher + public sealed class PacketDispatcher : IPacketDispatcher { public const byte LocalConnectionId = 0; public const byte ServerId = 0; @@ -29,14 +29,14 @@ public PacketDispatcher( _serverInstance = serverInstance; } - private void SendInternal(IPlayer player, ref SpanBuffer writer, DeliveryMethod deliveryMethod) + private void SendInternal(IPlayer player, ref SpanBuffer writer, IgnoranceChannelTypes deliveryMethod) { _logger.Verbose($"Sending packet (SenderId={ServerId}) to player {player.ConnectionId} with UserId {player.UserId}"); _serverInstance.Send(player, writer.Data, deliveryMethod); } #region Sends - public void SendToNearbyPlayers(INetSerializable packet, DeliveryMethod deliveryMethod) + public void SendToNearbyPlayers(INetSerializable packet, IgnoranceChannelTypes deliveryMethod) { _logger.Debug( $"Sending packet of type '{packet.GetType().Name}' " + @@ -51,7 +51,7 @@ public void SendToNearbyPlayers(INetSerializable packet, DeliveryMethod delivery SendInternal(player, ref writer, deliveryMethod); } - public void SendToNearbyPlayers(INetSerializable[] packets, DeliveryMethod deliveryMethod) + public void SendToNearbyPlayers(INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod) { _logger.Debug( $"Sending MultiPacket " + @@ -66,7 +66,7 @@ public void SendToNearbyPlayers(INetSerializable[] packets, DeliveryMethod deliv SendInternal(player, ref writer, deliveryMethod); } - public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) + public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, IgnoranceChannelTypes deliveryMethod) { _logger.Debug( $"Sending packet of type '{packet.GetType().Name}' " + @@ -82,7 +82,7 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, SendInternal(player, ref writer, deliveryMethod); } - public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) + public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod) { _logger.Debug( $"Sending MultiPacket " + @@ -105,7 +105,7 @@ public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packe SendInternal(player, ref writer, deliveryMethod); } - public void RouteExcludingPlayer(IPlayer excludedPlayer, ref SpanBuffer writer, DeliveryMethod deliveryMethod) + public void RouteExcludingPlayer(IPlayer excludedPlayer, ref SpanBuffer writer, IgnoranceChannelTypes deliveryMethod) { _logger.Debug( $"Sending routed packet " + @@ -118,7 +118,7 @@ public void RouteExcludingPlayer(IPlayer excludedPlayer, ref SpanBuffer writer, } - public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) + public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, IgnoranceChannelTypes deliveryMethod) { _logger.Debug( $"Sending packet of type '{packet.GetType().Name}' " + @@ -132,7 +132,7 @@ public void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, Delivery foreach (var player in _playerRegistry.Players) SendInternal(player, ref writer, deliveryMethod); } - public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) + public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod) { _logger.Debug( $"Sending MultiPacket " + @@ -147,7 +147,7 @@ public void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, Deliv SendInternal(player, ref writer, deliveryMethod); } - public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable packet, DeliveryMethod deliveryMethod) + public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable packet, IgnoranceChannelTypes deliveryMethod) { _logger.Debug( $"Sending packet of type '{packet.GetType().Name}' " + @@ -160,7 +160,7 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer SendInternal(toPlayer, ref writer, deliveryMethod); } - public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod) + public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod) { _logger.Debug( $"Sending MultiPacket" + @@ -173,7 +173,7 @@ public void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSer SendInternal(toPlayer, ref writer, deliveryMethod); } - public void RouteFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, ref SpanBuffer writer, DeliveryMethod deliveryMethod) + public void RouteFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, ref SpanBuffer writer, IgnoranceChannelTypes deliveryMethod) { _logger.Debug( $"Sending routed packet " + @@ -183,7 +183,7 @@ public void RouteFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, ref Sp SendInternal(toPlayer, ref writer, deliveryMethod); } - public void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod deliveryMethod) + public void SendToPlayer(IPlayer player, INetSerializable packet, IgnoranceChannelTypes deliveryMethod) { _logger.Debug( $"Sending packet of type '{packet.GetType().Name}' " + @@ -195,7 +195,7 @@ public void SendToPlayer(IPlayer player, INetSerializable packet, DeliveryMethod WriteOne(ref writer, packet); SendInternal(player, ref writer, deliveryMethod); } - public void SendToPlayer(IPlayer player, INetSerializable[] packets, DeliveryMethod deliveryMethod) + public void SendToPlayer(IPlayer player, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod) { _logger.Debug( $"Sending MultiPacket " + diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs index f03567da..f7614884 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs @@ -1,7 +1,7 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MPChat @@ -29,12 +29,12 @@ public override void Handle(IPlayer sender, MpcCapabilitiesPacket packet) _packetDispatcher.SendToPlayer(sender, new MpcTextChatPacket { Text = "Welcome to " + _instanceConfiguration.ServerName + " Type /help to get a list of commands!" - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); if (_instanceConfiguration.WelcomeMessage != string.Empty) _packetDispatcher.SendToPlayer(sender, new MpcTextChatPacket { Text = _instanceConfiguration.WelcomeMessage - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs index 0a725d67..094636a1 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs @@ -1,8 +1,8 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; -using BeatTogether.LiteNetLib.Enums; using Serilog; using System; @@ -45,7 +45,7 @@ public override void Handle(IPlayer sender, MpcTextChatPacket packet) _packetDispatcher.SendToPlayer(sender, new MpcTextChatPacket { Text = "Command not found or too long" - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs index b96126ed..c287e186 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs @@ -1,8 +1,8 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -32,7 +32,7 @@ public override void Handle(IPlayer sender, ClearRecommendedBeatmapPacket packet _packetDispatcher.SendToPlayer(sender, new SetIsStartButtonEnabledPacket { Reason = sender.IsServerOwner ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs index 8f9cc4d9..009f4872 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs @@ -1,7 +1,7 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -30,7 +30,7 @@ public override void Handle(IPlayer sender, GetCountdownEndTimePacket packet) _packetDispatcher.SendToPlayer(sender, new SetCountdownEndTimePacket { CountdownTime = _lobbyManager.CountdownEndTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsInLobbyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsInLobbyPacketHandler.cs index 4055a107..0412283d 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsInLobbyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsInLobbyPacketHandler.cs @@ -1,8 +1,8 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -32,7 +32,7 @@ public override void Handle(IPlayer sender, GetIsInLobbyPacket packet) _packetDispatcher.SendToPlayer(sender, new SetIsInLobbyPacket { IsInLobby = _instance.State != MultiplayerGameState.Game - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsReadyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsReadyPacketHandler.cs index 0167d652..7206fe23 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsReadyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsReadyPacketHandler.cs @@ -1,6 +1,6 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -26,7 +26,7 @@ public override void Handle(IPlayer sender, GetIsReadyPacket packet) _packetDispatcher.SendToPlayer(sender, new SetIsReadyPacket { IsReady = sender.IsReady - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetMultiplayerGameStatePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetMultiplayerGameStatePacketHandler.cs index 16ace7b3..3eca4464 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetMultiplayerGameStatePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetMultiplayerGameStatePacketHandler.cs @@ -1,6 +1,6 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -29,7 +29,7 @@ public override void Handle(IPlayer sender, GetMultiplayerGameStatePacket packet _packetDispatcher.SendToPlayer(sender, new SetMultiplayerGameStatePacket { State = _instance.State - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs index c7eaa1aa..bddaaaf6 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs @@ -1,8 +1,8 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -58,7 +58,7 @@ public override void Handle(IPlayer sender, GetPlayersPermissionConfigurationPac { PlayersPermission = playerPermissionConfigurations } - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedBeatmapPacketHandler.cs index d5c714db..99deced7 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedBeatmapPacketHandler.cs @@ -1,6 +1,6 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -27,7 +27,7 @@ public override void Handle(IPlayer sender, GetRecommendedBeatmapPacket packet) _packetDispatcher.SendToPlayer(sender, new SetRecommendedBeatmapPacket { BeatmapIdentifier = sender.BeatmapIdentifier - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedModifiersPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedModifiersPacketHandler.cs index eabb433e..bc7bfd59 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedModifiersPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedModifiersPacketHandler.cs @@ -1,6 +1,6 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -25,7 +25,7 @@ public override void Handle(IPlayer sender, GetRecommendedModifiersPacket packet _packetDispatcher.SendToPlayer(sender, new SetRecommendedModifiersPacket { Modifiers = sender.Modifiers - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedBeatmapHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedBeatmapHandler.cs index 2092d899..b3f2a60e 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedBeatmapHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedBeatmapHandler.cs @@ -1,7 +1,7 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -37,7 +37,7 @@ public override void Handle(IPlayer sender, GetSelectedBeatmap packet) _packetDispatcher.SendToPlayer(sender, new SetSelectedBeatmap { Beatmap = _lobbyManager.SelectedBeatmap - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); return; } if (_instance.State == Messaging.Enums.MultiplayerGameState.Game && _gameplayManager.CurrentBeatmap != null) @@ -45,10 +45,10 @@ public override void Handle(IPlayer sender, GetSelectedBeatmap packet) _packetDispatcher.SendToPlayer(sender, new SetSelectedBeatmap { Beatmap = _gameplayManager.CurrentBeatmap - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); return; } - _packetDispatcher.SendToPlayer(sender, new ClearSelectedBeatmap(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToPlayer(sender, new ClearSelectedBeatmap(), IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedGameplayModifiersHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedGameplayModifiersHandler.cs index 8a493093..0c32148e 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedGameplayModifiersHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedGameplayModifiersHandler.cs @@ -1,7 +1,7 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -37,7 +37,7 @@ public override void Handle(IPlayer sender, GetSelectedGameplayModifiers packet) _packetDispatcher.SendToPlayer(sender, new SetSelectedGameplayModifiers { Modifiers = _lobbyManager.SelectedModifiers - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); return; } if (_instance.State == Messaging.Enums.MultiplayerGameState.Game) @@ -45,10 +45,10 @@ public override void Handle(IPlayer sender, GetSelectedGameplayModifiers packet) _packetDispatcher.SendToPlayer(sender, new SetSelectedGameplayModifiers { Modifiers = _gameplayManager.CurrentModifiers - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); return; } - _packetDispatcher.SendToPlayer(sender, new ClearSelectedGameplayModifiers(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToPlayer(sender, new ClearSelectedGameplayModifiers(), IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs index bfde60f5..1d154d49 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs @@ -1,11 +1,11 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; using System.Linq; @@ -47,7 +47,7 @@ public override void Handle(IPlayer sender, GetStartedLevelPacket packet) Beatmap = _gameplayManager.CurrentBeatmap, Modifiers = _gameplayManager.CurrentModifiers, StartTime = _instance.RunTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } else { @@ -57,7 +57,7 @@ public override void Handle(IPlayer sender, GetStartedLevelPacket packet) _packetDispatcher.SendToPlayer(sender, new GetIsEntitledToLevelPacket { LevelId = _lobbyManager.SelectedBeatmap.LevelId - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); if(_lobbyManager.CountDownState == CountdownState.WaitingForEntitlement || _lobbyManager.CountDownState == CountdownState.StartBeatmapCountdown) { @@ -76,11 +76,11 @@ public override void Handle(IPlayer sender, GetStartedLevelPacket packet) Beatmap = Beatmap, Modifiers = Modifiers, StartTime = _lobbyManager.CountdownEndTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } else - _packetDispatcher.SendToPlayer(sender, new CancelLevelStartPacket(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToPlayer(sender, new CancelLevelStartPacket(), IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs index df5e8036..9d96db99 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs @@ -1,8 +1,8 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -32,7 +32,7 @@ public override void Handle(IPlayer sender, RequestKickPlayerPacket packet) _packetDispatcher.SendToPlayer(kickedPlayer, new KickPlayerPacket { DisconnectedReason = DisconnectedReason.Kicked - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs index b8792afb..18af1124 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs @@ -1,8 +1,8 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -42,23 +42,23 @@ public override void Handle(IPlayer sender, SetIsInLobbyPacket packet) _packetDispatcher.SendToPlayer(sender, new SetIsStartButtonEnabledPacket { Reason = sender.IsServerOwner ? _lobbyManager.GetCannotStartGameReason(sender, _lobbyManager.DoesEveryoneOwnBeatmap) : CannotStartGameReason.None - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); if (_lobbyManager.SelectedBeatmap is null) - _packetDispatcher.SendToPlayer(sender, new ClearSelectedBeatmap(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToPlayer(sender, new ClearSelectedBeatmap(), IgnoranceChannelTypes.Reliable); else _packetDispatcher.SendToPlayer(sender, new SetSelectedBeatmap { Beatmap = _lobbyManager.SelectedBeatmap - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); if (_lobbyManager.SelectedModifiers == _lobbyManager.EmptyModifiers) - _packetDispatcher.SendToPlayer(sender, new ClearSelectedGameplayModifiers(), DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToPlayer(sender, new ClearSelectedGameplayModifiers(), IgnoranceChannelTypes.Reliable); else _packetDispatcher.SendToPlayer(sender, new SetSelectedGameplayModifiers { Modifiers = _lobbyManager.SelectedModifiers - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs index ce450e1f..aa06740a 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs @@ -1,9 +1,9 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc @@ -42,7 +42,7 @@ public override void Handle(IPlayer sender, SetIsReadyPacket packet) Beatmap = _gameplayManager.CurrentBeatmap!, Modifiers = _gameplayManager.CurrentModifiers, StartTime = _instance.RunTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs index a1a65cd9..7d45c29d 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs @@ -1,9 +1,8 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Enums; using Serilog; -using System.Threading.Tasks; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -40,7 +39,7 @@ public override void Handle(IPlayer sender, SetRecommendedBeatmapPacket packet) _packetDispatcher.SendToNearbyPlayers(new GetIsEntitledToLevelPacket { LevelId = packet.BeatmapIdentifier.LevelId - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs index c7bcb496..b415076d 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs @@ -1,9 +1,9 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; -using BeatTogether.LiteNetLib.Enums; using Serilog; using System.Linq; @@ -51,7 +51,7 @@ public override void Handle(IPlayer sender, DediPacketSetNewManagerPacket packet HasInvitePermission = x.CanInvite }).ToArray() } - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs index 32c52d45..6f34093a 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs @@ -1,7 +1,7 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Extensions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; -using BeatTogether.LiteNetLib.Enums; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -28,7 +28,7 @@ public override void Handle(IPlayer sender, MpPlayerData packet) PlatformID = Player.PlatformUserId, Platform = Player.Platform.Convert(), ClientVersion = Player.ClientVersion - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PingPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PingPacketHandler.cs index a2bc00d2..a84dbd61 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PingPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PingPacketHandler.cs @@ -1,6 +1,6 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers @@ -25,7 +25,7 @@ public override void Handle(IPlayer sender, PingPacket packet) _packetDispatcher.SendToPlayer(sender, new PongPacket { PingTime = packet.PingTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs index 3dc553f7..98b9c688 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerIdentityPacketHandler.cs @@ -1,7 +1,7 @@ using System; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers @@ -29,7 +29,7 @@ public override void Handle(IPlayer sender, PlayerIdentityPacket packet) sender.State = packet.PlayerState; sender.Random = packet.Random.Data ?? Array.Empty(); sender.PublicEncryptionKey = packet.PublicEncryptionKey.Data ?? Array.Empty(); - _packetDispatcher.SendFromPlayer(sender, packet, DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendFromPlayer(sender, packet, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs index 5cdf07c0..46ee08d7 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerLatencyPacketHandler.cs @@ -1,6 +1,6 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers @@ -27,7 +27,7 @@ public override void Handle(IPlayer sender, PlayerLatencyPacket packet) _packetDispatcher.SendFromPlayer(sender, new PlayerLatencyPacket { Latency = sender.Latency.CurrentAverage - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs index b7f20879..049ebb16 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs @@ -1,6 +1,6 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers @@ -24,7 +24,7 @@ public override void Handle(IPlayer sender, PlayerSortOrderPacket packet) if (sender.UserId == packet.UserId && sender.SortIndex != packet.SortIndex) //If they send themselves as being in the wrong place, correct them. Although this probably shouldnt have a handler { packet.SortIndex = sender.SortIndex; - _packetDispatcher.SendToPlayer(sender, packet, DeliveryMethod.ReliableOrdered); + _packetDispatcher.SendToPlayer(sender, packet, IgnoranceChannelTypes.Reliable); } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/SyncTimePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/SyncTimePacketHandler.cs index f6322777..26d4c094 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/SyncTimePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/SyncTimePacketHandler.cs @@ -1,6 +1,6 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets; -using BeatTogether.LiteNetLib.Enums; using Serilog; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers @@ -25,7 +25,7 @@ public override void Handle(IPlayer sender, SyncTimePacket packet) _packetDispatcher.SendToPlayer(sender, new SyncTimePacket { SyncTime = sender.SyncTime - }, DeliveryMethod.ReliableOrdered); + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index 7fae7d21..dd1f3b88 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -7,11 +7,11 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; using BeatTogether.DedicatedServer.Messaging.Registries; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Enums; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; using Krypton.Buffers; using Serilog; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; namespace BeatTogether.DedicatedServer.Kernel { @@ -41,7 +41,7 @@ public PacketSource( _configuration = instconfiguration; } - public void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, DeliveryMethod method) + public void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, IgnoranceChannelTypes method) { if (!reader.TryReadRoutingHeader(out var routingHeader)) { @@ -116,22 +116,22 @@ public void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, DeliveryMe } if(packet is NoteSpawnPacket || packet is ObstacleSpawnPacket || packet is SliderSpawnPacket) //Note packet logic { - if (_configuration.DisableNotes || (_playerRegistry.GetPlayerCount() > 16) && !_configuration.ForceEnableNotes) + if (_configuration.DisableNotes || (_playerRegistry.GetPlayerCount() >= _configuration.DisableNotesPlayerCount) && !_configuration.ForceEnableNotes) return; - method = DeliveryMethod.Unreliable; + method = IgnoranceChannelTypes.Unthrottled; break; } - if (packet is NodePoseSyncStatePacket) + else if (packet is NodePoseSyncStatePacket) { if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncState) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets()) { _logger.Verbose($"Skipping sync state packet from {sender.ConnectionId} (Secret='{sender.Instance._configuration.Secret}')."); return; } - method = DeliveryMethod.Unreliable; + method = IgnoranceChannelTypes.Unthrottled; sender.TicksAtLastSyncState = DateTime.UtcNow.Ticks; } - if (packet is NodePoseSyncStateDeltaPacket) + else if (packet is NodePoseSyncStateDeltaPacket) { if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncStateDelta) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets()) { @@ -146,8 +146,7 @@ public void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, DeliveryMe var packetHandler = _serviceProvider.GetService(packetHandlerType); if (packetHandler is null) { - //if (!packetType.Name.StartsWith("NodePoseSyncState")) - _logger.Verbose($"No handler exists for packet of type '{packetType.Name}'."); + _logger.Verbose($"No handler exists for packet of type '{packetType.Name}'."); // skip any unprocessed bytes var processedBytes = HandleRead.Offset - prevPosition; @@ -182,7 +181,7 @@ public void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, DeliveryMe private void RoutePacket(IPlayer sender, (byte SenderId, byte ReceiverId, PacketOption PacketOption) routingHeader, - ref SpanBuffer reader, DeliveryMethod deliveryMethod) + ref SpanBuffer reader, IgnoranceChannelTypes deliveryMethod) { routingHeader.SenderId = sender.ConnectionId; var writer = new SpanBuffer(stackalloc byte[412]); diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index ed49c435..0482dd86 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -61,7 +61,7 @@ public sealed class Player : IPlayer private readonly ConcurrentDictionary _entitlements = new(); //Set a max amount of like 50 or something. public Player(EndPoint endPoint, IDedicatedInstance instance, - byte connectionId, string userId, string userName, string? playerSessionId, AccessLevel accessLevel = AccessLevel.Player) + byte connectionId, string userId, string userName, string playerSessionId, AccessLevel accessLevel = AccessLevel.Player) { Endpoint = endPoint; Instance = instance; diff --git a/BeatTogether.DedicatedServer.Messaging/Abstractions/BasePacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Abstractions/BasePacketRegistry.cs new file mode 100644 index 00000000..38b90a05 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Abstractions/BasePacketRegistry.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; + +namespace BeatTogether.DedicatedServer.Messaging.Abstractions +{ + public abstract class BasePacketRegistry : IPacketRegistry + { + public delegate INetSerializable PacketFactory(); + + private readonly Dictionary _types = new(); + private readonly Dictionary> _packetIds = new(); + private readonly Dictionary _subPacketRegistries = new(); + private readonly Dictionary _factories = new(); + + #region Public Methods + + public BasePacketRegistry() => Register(); + + public abstract void Register(); + + /// + public IReadOnlyDictionary> GetAllPacketIds() => + _packetIds; + + /// + /// broke but too lazy to fix + public IEnumerable GetPacketIds(Type type) => + _packetIds[type]; + + /// + /// broke but too lazy to fix + public IEnumerable GetPacketIds() + where T : class, INetSerializable => + GetPacketIds(typeof(T)); + + /// + public Type GetPacketType(object packetId) => + _types[(byte)packetId]; + + /// + public IPacketRegistry GetSubPacketRegistry(object packetRegistryId) => + _subPacketRegistries[(byte)packetRegistryId]; + + /// + public INetSerializable CreatePacket(object packetId) => + _factories[(byte)packetId](); + + /// + public bool TryGetPacketIds(Type type, [MaybeNullWhen(false)] out IEnumerable packetIds) + { + if (_packetIds.TryGetValue(type, out packetIds)) + return true; + foreach (var (id, subRegistry) in _subPacketRegistries) + { + if (subRegistry.TryGetPacketIds(type, out IEnumerable? subPacketIds)) + { + packetIds = Enumerable.Empty().Append((byte)id).Concat(subPacketIds); + return true; + } + } + return false; + } + + /// + public bool TryGetPacketIds([MaybeNullWhen(false)] out IEnumerable packetIds) + where T : class, INetSerializable => + TryGetPacketIds(typeof(T), out packetIds); + + /// + public bool TryGetPacketType(object packetId, [MaybeNullWhen(false)] out Type type) => + _types.TryGetValue((byte)packetId, out type); + + /// + public bool TryGetSubPacketRegistry(object packetRegistryId, [MaybeNullWhen(false)] out IPacketRegistry packetRegistry) => + _subPacketRegistries.TryGetValue((byte)packetRegistryId, out packetRegistry); + + /// + public bool TryCreatePacket(object packetId, [MaybeNullWhen(false)] out INetSerializable packet) + { + if (_factories.TryGetValue((byte)packetId, out var factory)) + { + packet = factory(); + return true; + } + + packet = null; + return false; + } + + #endregion + + #region Private Methods + + protected void AddPacket(object packetId) + where T : class, INetSerializable, new() + { + var type = typeof(T); + if (_types.ContainsKey((byte)packetId) || _packetIds.ContainsKey(type)) + throw new Exception( + $"Duplicate registration for packet of type '{type.Name}' " + + $"(PacketId={packetId})." + ); + + _types[(byte)packetId] = type; + _packetIds[type] = Enumerable.Empty() + .Append((byte)packetId); + _factories[(byte)packetId] = () => new T(); + } + + protected void AddSubPacketRegistry(object packetRegistryId) + where T : class, IPacketRegistry, new() + { + var subPacketRegistry = new T(); + _subPacketRegistries[(byte)packetRegistryId] = subPacketRegistry; + //foreach (var (packetType, packetIds) in subPacketRegistry.GetAllPacketIds()) + // _packetIds[packetType] = packetIds; + } + + #endregion + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcPacket.cs b/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcPacket.cs index 8d32328c..cf70f3fd 100644 --- a/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcPacket.cs @@ -1,6 +1,5 @@ using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Abstractions { @@ -17,14 +16,5 @@ public virtual void WriteTo(ref SpanBuffer writer) { writer.WriteVarULong((ulong)SyncTime); } - public virtual void ReadFrom(ref MemoryBuffer reader) - { - SyncTime = (long)reader.ReadVarULong(); - } - - public virtual void WriteTo(ref MemoryBuffer writer) - { - writer.WriteVarULong((ulong)SyncTime); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcWithValuesPacket.cs b/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcWithValuesPacket.cs index 4aa4194a..495b3793 100644 --- a/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcWithValuesPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Abstractions/BaseRpcWithValuesPacket.cs @@ -1,4 +1,4 @@ -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Abstractions { @@ -42,16 +42,6 @@ public override void WriteTo(ref SpanBuffer writer) base.WriteTo(ref writer); writer.WriteUInt8(HasValues); } - public override void ReadFrom(ref MemoryBuffer reader) - { - base.ReadFrom(ref reader); - HasValues = reader.ReadUInt8(); - } - public override void WriteTo(ref MemoryBuffer writer) - { - base.WriteTo(ref writer); - writer.WriteUInt8(HasValues); - } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Abstractions/INetSerializable.cs b/BeatTogether.DedicatedServer.Messaging/Abstractions/INetSerializable.cs new file mode 100644 index 00000000..7943681b --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Abstractions/INetSerializable.cs @@ -0,0 +1,11 @@ +using BeatTogether.DedicatedServer.Messaging.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Abstractions +{ + public interface INetSerializable + { + void WriteTo(ref SpanBuffer bufferWriter); + + void ReadFrom(ref SpanBuffer bufferReader); + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Abstractions/IPacketLayer.cs b/BeatTogether.DedicatedServer.Messaging/Abstractions/IPacketLayer.cs new file mode 100644 index 00000000..716432e0 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Abstractions/IPacketLayer.cs @@ -0,0 +1,11 @@ +using System; +using System.Net; + +namespace BeatTogether.DedicatedServer.Messaging.Abstractions +{ + public interface IPacketLayer + { + public void ProcessInboundPacket(EndPoint endPoint, ref Span data); + public void ProcessOutBoundPacket(EndPoint endPoint, ref Span data); + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Abstractions/IPacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Abstractions/IPacketRegistry.cs new file mode 100644 index 00000000..a95ba21a --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Abstractions/IPacketRegistry.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace BeatTogether.DedicatedServer.Messaging.Abstractions +{ + public interface IPacketRegistry + { + /// + /// Retrieves the identifiers of all registered packets. + /// + /// The identifiers of all registered packets. + IReadOnlyDictionary> GetAllPacketIds(); + + /// + /// Retrieves the identifiers associated with the packet + /// of the given . + /// + /// The of packet. + /// The identifiers associated with the packet. + IEnumerable GetPacketIds(Type type); + + /// + /// Retrieves the identifiers associated with the packet of type . + /// + /// The type of packet. + /// The identifiers associated with the packet. + IEnumerable GetPacketIds() + where T : class, INetSerializable; + + /// + /// Retrieves the of the packet + /// associated with the given . + /// + /// + /// The identifier associated with the packet. + /// This must be castable to a . + /// + /// The object of the packet. + Type GetPacketType(object packetId); + + /// + /// Retrieves the instance + /// associated with the given . + /// + /// + /// The identifier associated with the sub packet registry. + /// This must be castable to a . + /// + /// The instance associated with the given identifier. + IPacketRegistry GetSubPacketRegistry(object packetRegistryId); + + /// + /// Creates a new instance of the packet associated with the given . + /// + /// + /// The identifier associated with the packet. + /// This must be castable to a . + /// + /// The packet instance. + INetSerializable CreatePacket(object packetId); + + /// + /// Retrieves the identifiers associated with the packet + /// of the given . + /// + /// The of packet. + /// The identifiers associated with the packet. + /// + /// when the were retrieved successfully; + /// otherwise. + /// + bool TryGetPacketIds(Type type, [MaybeNullWhen(false)] out IEnumerable packetIds); + + /// + /// Retrieves the identifiers associated with the packet of type . + /// + /// The type of packet. + /// The identifiers associated with the packet. + /// + /// when the were retrieved successfully; + /// otherwise. + /// + bool TryGetPacketIds([MaybeNullWhen(false)] out IEnumerable packetIds) + where T : class, INetSerializable; + + /// + /// Retrieves the of the packet + /// associated with the given . + /// + /// + /// The identifier associated with the packet. + /// This must be castable to a . + /// + /// The object of the packet. + /// + /// when the was retrieved successfully; + /// otherwise. + bool TryGetPacketType(object packetId, [MaybeNullWhen(false)] out Type type); + + /// + /// Retrieves the instance + /// associated with the given . + /// + /// + /// The identifier associated with the sub packet registry. + /// This must be castable to a . + /// + /// + /// The instance + /// associated with the given identifier. + /// + /// + /// when the was retrieved successfully; + /// otherwise. + bool TryGetSubPacketRegistry(object packetRegistryId, [MaybeNullWhen(false)] out IPacketRegistry packetRegistry); + + /// + /// Creates a new instance of the packet associated with the given . + /// + /// + /// The identifier associated with the packet. + /// This must be castable to a . + /// + /// The packet instance. + /// + /// when the was created successfully; + /// otherwise. + /// + bool TryCreatePacket(object packetId, [MaybeNullWhen(false)] out INetSerializable packet); + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj index 754dba28..05ac0b57 100644 --- a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj +++ b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj @@ -9,7 +9,6 @@ - diff --git a/BeatTogether.DedicatedServer.Messaging/Converter/AvatarDataMultiplayerAvatarsDataConverter.cs b/BeatTogether.DedicatedServer.Messaging/Converter/AvatarDataMultiplayerAvatarsDataConverter.cs index 9a52d13a..3778d8c2 100644 --- a/BeatTogether.DedicatedServer.Messaging/Converter/AvatarDataMultiplayerAvatarsDataConverter.cs +++ b/BeatTogether.DedicatedServer.Messaging/Converter/AvatarDataMultiplayerAvatarsDataConverter.cs @@ -1,4 +1,4 @@ -using BeatTogether.DedicatedServer.Messaging.Extensions; +using BeatTogether.Extensions; using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Structs; using System.IO; diff --git a/BeatTogether.DedicatedServer.Messaging/Delegates/PacketFactory.cs b/BeatTogether.DedicatedServer.Messaging/Delegates/PacketFactory.cs index d13e324a..5e6efbaf 100644 --- a/BeatTogether.DedicatedServer.Messaging/Delegates/PacketFactory.cs +++ b/BeatTogether.DedicatedServer.Messaging/Delegates/PacketFactory.cs @@ -1,4 +1,4 @@ -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Abstractions; namespace BeatTogether.DedicatedServer.Messaging.Delegates { diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/BinaryReadWriteExtension.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/BinaryReadWriteExtension.cs index 449b7af8..8db6bcf6 100644 --- a/BeatTogether.DedicatedServer.Messaging/Extensions/BinaryReadWriteExtension.cs +++ b/BeatTogether.DedicatedServer.Messaging/Extensions/BinaryReadWriteExtension.cs @@ -1,7 +1,7 @@ using System.IO; using BeatTogether.DedicatedServer.Messaging.Models; -namespace BeatTogether.DedicatedServer.Messaging.Extensions +namespace BeatTogether.Extensions { public static class BinaryReadWriteExtension { diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/MemoryBufferExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/MemoryBufferExtensions.cs deleted file mode 100644 index 65843dc4..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Extensions/MemoryBufferExtensions.cs +++ /dev/null @@ -1,176 +0,0 @@ -using BeatTogether.LiteNetLib.Util; -using System; -using System.Diagnostics.CodeAnalysis; -using System.Net; -using System.Text; - -namespace BeatTogether.Extensions -{ - public static class MemoryBufferExtensions - { - public static (byte SenderId, byte ReceiverId) ReadRoutingHeader(this MemoryBuffer reader) => - (reader.ReadUInt8(), reader.ReadUInt8()); - - public static bool TryReadRoutingHeader(this MemoryBuffer reader, [MaybeNullWhen(false)] out (byte SenderId, byte ReceiverId) routingHeader) - { - if (reader.RemainingSize < 2) - { - routingHeader = default; - return false; - } - - routingHeader = (reader.ReadUInt8(), reader.ReadUInt8()); - return true; - } - - public static void WriteRoutingHeader(this MemoryBuffer writer, byte senderId, byte receiverId) - { - writer.WriteUInt8(senderId); - writer.WriteUInt8(receiverId); - } - - public static ulong ReadVarULong(this MemoryBuffer bufferReader) - { - ulong num = 0uL; - int num2 = 0; - byte b = bufferReader.ReadByte(); - while (((ulong)b & 0x80uL) != 0L) - { - num |= ((ulong)b & 0x7FuL) << num2; - num2 += 7; - b = bufferReader.ReadByte(); - } - - return num | ((ulong)b << num2); - } - - public static long ReadVarLong(this MemoryBuffer bufferReader) - { - long num = (long)bufferReader.ReadVarULong(); - if ((num & 1) != 1) - { - return num >> 1; - } - - return -(num >> 1) + 1; - } - - public static uint ReadVarUInt(this MemoryBuffer bufferReader) - { - return (uint)bufferReader.ReadVarULong(); - } - - public static int ReadVarInt(this MemoryBuffer bufferReader) - { - return (int)bufferReader.ReadVarLong(); - } - - public static bool TryReadVarULong(this MemoryBuffer bufferReader, out ulong value) - { - value = 0uL; - int num = 0; - while (num <= 63 && bufferReader.RemainingSize >= 1) - { - byte b = bufferReader.ReadByte(); - value |= (ulong)((long)(b & 0x7F) << num); - num += 7; - if ((b & 0x80) == 0) - { - return true; - } - } - - value = 0uL; - return false; - } - - public static bool TryReadVarUInt(this MemoryBuffer bufferReader, out uint value) - { - if (bufferReader.TryReadVarULong(out var value2) && value2 >> 32 == 0L) - { - value = (uint)value2; - return true; - } - - value = 0u; - return false; - } - - public static ReadOnlySpan ReadVarBytes(this MemoryBuffer bufferReader) - { - uint count = bufferReader.ReadVarUInt(); - return bufferReader.ReadBytes((int)count).Span; - } - - public static string ReadString(this MemoryBuffer bufferReader, int maxLength = 65535) - { - int num = bufferReader.ReadInt32(); - if (num <= 0 || num > maxLength) - { - return string.Empty; - } - - ReadOnlySpan bytes = bufferReader.ReadBytes(num).Span; - return Encoding.UTF8.GetString(bytes); - } - - public static IPEndPoint ReadIPEndPoint(this MemoryBuffer bufferReader) - { - if (!IPAddress.TryParse(bufferReader.ReadString(512), out var address)) - { - throw new ArgumentException("Failed to parse IP address"); - } - - int port = bufferReader.ReadInt32(); - return new IPEndPoint(address, port); - } - public static void WriteVarULong(this MemoryBuffer bufferWriter, ulong value) - { - do - { - byte b = (byte)(value & 0x7F); - value >>= 7; - if (value != 0L) - { - b = (byte)(b | 0x80u); - } - - bufferWriter.WriteUInt8(b); - } - while (value != 0L); - } - - public static void WriteVarLong(this MemoryBuffer bufferWriter, long value) - { - bufferWriter.WriteVarULong((ulong)((value < 0) ? ((-value << 1) - 1) : (value << 1))); - } - - public static void WriteVarUInt(this MemoryBuffer buffer, uint value) - { - buffer.WriteVarULong(value); - } - - public static void WriteVarInt(this MemoryBuffer bufferWriter, int value) - { - bufferWriter.WriteVarLong(value); - } - - public static void WriteVarBytes(this MemoryBuffer bufferWriter, ReadOnlySpan bytes) - { - bufferWriter.WriteVarUInt((uint)bytes.Length); - bufferWriter.WriteBytes(bytes); - } - - public static void WriteString(this MemoryBuffer bufferWriter, string value) - { - bufferWriter.WriteInt32(Encoding.UTF8.GetByteCount(value)); - bufferWriter.WriteBytes(Encoding.UTF8.GetBytes(value)); - } - - public static void WriteIPEndPoint(this MemoryBuffer bufferWriter, IPEndPoint ipEndPoint) - { - bufferWriter.WriteString(ipEndPoint.Address.ToString()); - bufferWriter.WriteInt32(ipEndPoint.Port); - } - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/ServiceCollectionExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/ServiceCollectionExtensions.cs index e374a8c2..4be8279f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Extensions/ServiceCollectionExtensions.cs +++ b/BeatTogether.DedicatedServer.Messaging/Extensions/ServiceCollectionExtensions.cs @@ -1,5 +1,5 @@ using BeatTogether.DedicatedServer.Messaging.Registries; -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Abstractions; using Microsoft.Extensions.DependencyInjection; namespace BeatTogether.Extensions diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs index 480538ae..c122d1bb 100644 --- a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs +++ b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferExtensions.cs @@ -1,8 +1,8 @@ using BeatTogether.DedicatedServer.Messaging.Enums; -using BeatTogether.LiteNetLib.Util; -using Krypton.Buffers; +using BeatTogether.DedicatedServer.Messaging.Util; using System; using System.Diagnostics.CodeAnalysis; +using System.Drawing; using System.Net; using System.Text; @@ -138,6 +138,16 @@ public static IPEndPoint ReadIPEndPoint(this ref SpanBuffer bufferReader) int port = bufferReader.ReadInt32(); return new IPEndPoint(address, port); } + + public static Color ReadColor(this ref SpanBuffer reader) + { + var r = reader.ReadByte(); + var g = reader.ReadByte(); + var b = reader.ReadByte(); + var a = reader.ReadByte(); + return Color.FromArgb(a, r, g, b); + } + public static void WriteVarULong(this ref SpanBuffer bufferWriter, ulong value) { do @@ -196,5 +206,13 @@ public static void WriteIPEndPoint(this ref SpanBuffer bufferWriter, IPEndPoint bufferWriter.WriteString(ipEndPoint.Address.ToString()); bufferWriter.WriteInt32(ipEndPoint.Port); } + + public static void WriteColor(this ref SpanBuffer writer, Color value) + { + writer.WriteUInt8(value.R); + writer.WriteUInt8(value.G); + writer.WriteUInt8(value.B); + writer.WriteUInt8(value.A); + } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferReaderExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferReaderExtensions.cs index fa204c01..7865e03a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferReaderExtensions.cs +++ b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferReaderExtensions.cs @@ -1,8 +1,11 @@ using BeatTogether.DedicatedServer.Messaging.Models; using Krypton.Buffers; +using System; using System.Diagnostics.CodeAnalysis; +using System.Net; +using System.Text; -namespace BeatTogether.Extensions +namespace BeatTogether.DedicatedServer.Messaging.Extensions { public static class SpanBufferReaderExtensions { @@ -27,7 +30,7 @@ public static void ReadBytesArray(this ref SpanBufferReader reader, ref byte[]? array = reader.ReadBytes(length).ToArray(); } - public static void ReadColor(this ref SpanBufferReader reader, ref Color color) + public static void ReadColor(this ref SpanBufferReader reader, ref Models.Color color) { color.r = reader.ReadFloat32(); color.g = reader.ReadFloat32(); @@ -48,5 +51,94 @@ public static void ReadBeatmapIdentifier(this ref SpanBufferReader reader, ref B beatmapIdentifier.Characteristic = reader.ReadString(); beatmapIdentifier.Difficulty = (BeatmapDifficulty)reader.ReadVarUInt(); } + public static ulong ReadVarULong(this ref SpanBufferReader bufferReader) + { + var value = 0UL; + var shift = 0; + var b = bufferReader.ReadByte(); + while ((b & 128UL) != 0UL) + { + value |= (b & 127UL) << shift; + shift += 7; + b = bufferReader.ReadByte(); + } + return value | (ulong)b << shift; + } + + public static long ReadVarLong(this ref SpanBufferReader bufferReader) + { + var varULong = (long)bufferReader.ReadVarULong(); + if ((varULong & 1L) != 1L) + return varULong >> 1; + return -(varULong >> 1) + 1L; + } + + public static uint ReadVarUInt(this ref SpanBufferReader bufferReader) + => (uint)bufferReader.ReadVarULong(); + + public static int ReadVarInt(this ref SpanBufferReader bufferReader) + => (int)bufferReader.ReadVarLong(); + + public static bool TryReadVarULong(this ref SpanBufferReader bufferReader, out ulong value) + { + value = 0UL; + var shift = 0; + while (shift <= 63 && bufferReader.RemainingSize >= 1) + { + var b = bufferReader.ReadByte(); + value |= (ulong)(b & 127) << shift; + shift += 7; + if ((b & 128) == 0) + return true; + } + + value = 0UL; + return false; + } + + public static bool TryReadVarUInt(this ref SpanBufferReader bufferReader, out uint value) + { + ulong num; + if (bufferReader.TryReadVarULong(out num) && (num >> 32) == 0UL) + { + value = (uint)num; + return true; + } + + value = 0U; + return false; + } + + public static ReadOnlySpan ReadVarBytes(this ref SpanBufferReader bufferReader) + { + var length = bufferReader.ReadVarUInt(); + return bufferReader.ReadBytes((int)length); + } + + public static string ReadString(this ref SpanBufferReader bufferReader, int maxLength = 65535) + { + var length = bufferReader.ReadInt32(); + if (length <= 0 | length > maxLength) + return string.Empty; + var bytes = bufferReader.ReadBytes(length); + return Encoding.UTF8.GetString(bytes); + } + + public static IPEndPoint ReadIPEndPoint(this ref SpanBufferReader bufferReader) + { + if (!IPAddress.TryParse(bufferReader.ReadString(512), out var address)) + throw new ArgumentException("Failed to parse IP address"); + var port = bufferReader.ReadInt32(); + return new IPEndPoint(address, port); + } + + public static System.Drawing.Color ReadColor(this ref SpanBufferReader reader) + { + var r = reader.ReadByte(); + var g = reader.ReadByte(); + var b = reader.ReadByte(); + var a = reader.ReadByte(); + return System.Drawing.Color.FromArgb(a, r, g, b); + } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferWriterExtensions.cs b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferWriterExtensions.cs new file mode 100644 index 00000000..7e6ced42 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Extensions/SpanBufferWriterExtensions.cs @@ -0,0 +1,58 @@ +using Krypton.Buffers; +using System; +using System.Drawing; +using System.Net; +using System.Text; + +namespace BeatTogether.DedicatedServer.Messaging.Extensions +{ + public static class SpanBufferWriterExtensions + { + public static void WriteVarULong(this ref SpanBufferWriter bufferWriter, ulong value) + { + do + { + var b = (byte)(value & 127UL); + value >>= 7; + if (value != 0UL) + b |= 128; + bufferWriter.WriteUInt8(b); + } while (value != 0UL); + } + + public static void WriteVarLong(this ref SpanBufferWriter bufferWriter, long value) + => bufferWriter.WriteVarULong((value < 0L ? (ulong)((-value << 1) - 1L) : (ulong)(value << 1))); + + public static void WriteVarUInt(this ref SpanBufferWriter buffer, uint value) + => buffer.WriteVarULong(value); + + public static void WriteVarInt(this ref SpanBufferWriter bufferWriter, int value) + => bufferWriter.WriteVarLong(value); + + public static void WriteVarBytes(this ref SpanBufferWriter bufferWriter, ReadOnlySpan bytes) + { + bufferWriter.WriteVarUInt((uint)bytes.Length); + bufferWriter.WriteBytes(bytes); + } + + public static void WriteString(this ref SpanBufferWriter bufferWriter, string value) + { + bufferWriter.WriteInt32(Encoding.UTF8.GetByteCount(value)); + bufferWriter.WriteBytes(Encoding.UTF8.GetBytes(value)); + } + + public static void WriteIPEndPoint(this ref SpanBufferWriter bufferWriter, IPEndPoint ipEndPoint) + { + bufferWriter.WriteString(ipEndPoint.Address.ToString()); + bufferWriter.WriteInt32(ipEndPoint.Port); + } + + public static void WriteColor(this ref SpanBufferWriter writer, Color value) + { + writer.WriteUInt8(value.R); + writer.WriteUInt8(value.G); + writer.WriteUInt8(value.B); + writer.WriteUInt8(value.A); + } + } +} diff --git a/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs b/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs index 637e73a3..72cc8db7 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/AvatarData.cs @@ -1,5 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; using System; namespace BeatTogether.DedicatedServer.Messaging.Models diff --git a/BeatTogether.DedicatedServer.Messaging/Models/BeatmapIdentifier.cs b/BeatTogether.DedicatedServer.Messaging/Models/BeatmapIdentifier.cs index dbd1868e..9503c20e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/BeatmapIdentifier.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/BeatmapIdentifier.cs @@ -1,7 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; -using Krypton.Buffers; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs index bef731c6..1454b9ec 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs @@ -1,5 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/BitMask256.cs b/BeatTogether.DedicatedServer.Messaging/Models/BitMask256.cs index d539af60..b3c9ea95 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/BitMask256.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/BitMask256.cs @@ -1,5 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ByteArray.cs b/BeatTogether.DedicatedServer.Messaging/Models/ByteArray.cs index bd4b4ff9..885ece12 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ByteArray.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ByteArray.cs @@ -1,8 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; -using Krypton.Buffers; -using System; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/Color.cs b/BeatTogether.DedicatedServer.Messaging/Models/Color.cs index e0337d71..b2710739 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/Color.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/Color.cs @@ -1,5 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ColorNoAlpha.cs b/BeatTogether.DedicatedServer.Messaging/Models/ColorNoAlpha.cs index 8642c282..e5bfdfde 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ColorNoAlpha.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ColorNoAlpha.cs @@ -1,6 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; -using Krypton.Buffers; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ColorScheme.cs b/BeatTogether.DedicatedServer.Messaging/Models/ColorScheme.cs index b94b2a9b..5f7590c9 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ColorScheme.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ColorScheme.cs @@ -1,6 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; -using Krypton.Buffers; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs index 177ad1a5..904a01a2 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/ConnectionRequestData.cs @@ -1,6 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/GameplayModifiers.cs b/BeatTogether.DedicatedServer.Messaging/Models/GameplayModifiers.cs index 7ee4dc61..3283e223 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/GameplayModifiers.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/GameplayModifiers.cs @@ -1,5 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs b/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs index 0728d1a3..b970401f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Enums; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs index 7086e558..3cdc7c24 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerAvatarsData.cs @@ -1,8 +1,8 @@ using BeatTogether.DedicatedServer.Messaging.Converter; using BeatTogether.DedicatedServer.Messaging.Structs; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; using System; using System.Collections.Generic; using System.Linq; diff --git a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerLevelCompletionResults.cs b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerLevelCompletionResults.cs index 63efd302..8d4e1eaf 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerLevelCompletionResults.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/MultiplayerLevelCompletionResults.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Enums; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/NodePoseSyncState.cs b/BeatTogether.DedicatedServer.Messaging/Models/NodePoseSyncState.cs index d2b8abda..41a55e85 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/NodePoseSyncState.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/NodePoseSyncState.cs @@ -1,5 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/NoteCutInfo.cs b/BeatTogether.DedicatedServer.Messaging/Models/NoteCutInfo.cs index 890d66f4..94701734 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/NoteCutInfo.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/NoteCutInfo.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Enums; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/NoteMissInfo.cs b/BeatTogether.DedicatedServer.Messaging/Models/NoteMissInfo.cs index 98dbe7a8..9e194d5e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/NoteMissInfo.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/NoteMissInfo.cs @@ -1,6 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/PlayerPermissionConfiguration.cs b/BeatTogether.DedicatedServer.Messaging/Models/PlayerPermissionConfiguration.cs index a0e707f1..014b1a07 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/PlayerPermissionConfiguration.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/PlayerPermissionConfiguration.cs @@ -1,6 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettings.cs b/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettings.cs index 7ae7ce6a..0b9ce624 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettings.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettings.cs @@ -1,6 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettingsAtStart.cs b/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettingsAtStart.cs index b2fc948d..49e35c43 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettingsAtStart.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/PlayerSpecificSettingsAtStart.cs @@ -1,5 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/PlayersPermissionConfiguration.cs b/BeatTogether.DedicatedServer.Messaging/Models/PlayersPermissionConfiguration.cs index 435033d2..e8e7b0f3 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/PlayersPermissionConfiguration.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/PlayersPermissionConfiguration.cs @@ -1,5 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/Pose.cs b/BeatTogether.DedicatedServer.Messaging/Models/Pose.cs index 31ad728a..e0847b83 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/Pose.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/Pose.cs @@ -1,6 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; -using Krypton.Buffers; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/Quaternion.cs b/BeatTogether.DedicatedServer.Messaging/Models/Quaternion.cs index 7312ff1f..b93cf37b 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/Quaternion.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/Quaternion.cs @@ -1,6 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/StandardScoreSyncState.cs b/BeatTogether.DedicatedServer.Messaging/Models/StandardScoreSyncState.cs index 8ce31866..9b33eaa1 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/StandardScoreSyncState.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/StandardScoreSyncState.cs @@ -1,6 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Models/Vector3.cs b/BeatTogether.DedicatedServer.Messaging/Models/Vector3.cs index 81e77059..cba2e83f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/Vector3.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/Vector3.cs @@ -1,6 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Models { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/KickPlayerPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/KickPlayerPacket.cs index 11d20307..9542d897 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/KickPlayerPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/KickPlayerPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Enums; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/LevelFinishedPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/LevelFinishedPacket.cs index 1f822918..e9d0bb28 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/LevelFinishedPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/LevelFinishedPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteCutPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteCutPacket.cs index a1382dcd..224d3632 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteCutPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteCutPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteMissPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteMissPacket.cs index a1ac658b..e08c95a5 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteMissPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteMissPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteSpawn.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteSpawn.cs index e5b6166e..4aad7a04 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteSpawn.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/NoteSpawn.cs @@ -1,5 +1,5 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/ObstacleSpawnPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/ObstacleSpawnPacket.cs index 874859c3..499271c5 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/ObstacleSpawnPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/ObstacleSpawnPacket.cs @@ -1,5 +1,5 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacket.cs index e410a0d6..1a1e872d 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneReadyPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneSyncFinishedPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneSyncFinishedPacket.cs index a2bd9479..01565a05 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneSyncFinishedPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetGameplaySceneSyncFinishedPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetPlayerDidConnectLatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetPlayerDidConnectLatePacket.cs index 35296123..dcfe5035 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetPlayerDidConnectLatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetPlayerDidConnectLatePacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs index a298eceb..81a17305 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SetSongStartTimePacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SliderSpawnPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SliderSpawnPacket.cs index c0d3f7d0..9de2db5a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SliderSpawnPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/GameplayRpc/SliderSpawnPacket.cs @@ -1,5 +1,5 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcBasePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcBasePacket.cs index 67c08941..5dd52672 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcBasePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcBasePacket.cs @@ -1,6 +1,6 @@ using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcCapabilitiesPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcCapabilitiesPacket.cs index 4ec207dc..f165e7bf 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcCapabilitiesPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcCapabilitiesPacket.cs @@ -1,4 +1,4 @@ -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcTextChatPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcTextChatPacket.cs index 79ae54bf..98345d8c 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcTextChatPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcTextChatPacket.cs @@ -1,5 +1,5 @@ using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcVoicePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcVoicePacket.cs index fcd44571..ef9fd13b 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcVoicePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MPChatPackets/MpcVoicePacket.cs @@ -1,5 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/ClearSelectedBeatmap.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/ClearSelectedBeatmap.cs index 5c9db5ca..57489e70 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/ClearSelectedBeatmap.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/ClearSelectedBeatmap.cs @@ -1,5 +1,4 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using Krypton.Buffers; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/GetIsEntitledToLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/GetIsEntitledToLevelPacket.cs index a46c404f..9b59a522 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/GetIsEntitledToLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/GetIsEntitledToLevelPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/RequestKickPlayerPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/RequestKickPlayerPacket.cs index a892511a..d34b32a3 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/RequestKickPlayerPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/RequestKickPlayerPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs index af235b09..6964fe18 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetCountdownEndTimePacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacket.cs index da82342c..b49f23a3 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsEntitledToLevelPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsInLobbyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsInLobbyPacket.cs index 8bac21b9..3e76fe33 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsInLobbyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsInLobbyPacket.cs @@ -1,5 +1,5 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsReadyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsReadyPacket.cs index 2714ade7..c6f37b3e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsReadyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsReadyPacket.cs @@ -1,5 +1,5 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsStartButtonEnabledPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsStartButtonEnabledPacket.cs index eedf9f3e..bc3fc098 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsStartButtonEnabledPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetIsStartButtonEnabledPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs index 0965ea4e..d6d2b986 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetOwnedSongPacksPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetOwnedSongPacksPacket.cs index 693cd0f8..f7849354 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetOwnedSongPacksPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetOwnedSongPacksPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersMissingEntitlementsToLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersMissingEntitlementsToLevelPacket.cs index a127c77a..d2634bc2 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersMissingEntitlementsToLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersMissingEntitlementsToLevelPacket.cs @@ -1,7 +1,7 @@ using System; using BeatTogether.DedicatedServer.Messaging.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersPermissionConfigurationPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersPermissionConfigurationPacket.cs index 6152c16a..bb576bea 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersPermissionConfigurationPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetPlayersPermissionConfigurationPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacket.cs index dd12e1a3..72bf8979 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacket.cs index faa5fc5d..546fe871 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetRecommendedModifiersPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedBeatmap.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedBeatmap.cs index fd74c077..5f00bdb1 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedBeatmap.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedBeatmap.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedGameplayModifiers.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedGameplayModifiers.cs index 7edb19c3..b9d61765 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedGameplayModifiers.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetSelectedGameplayModifiers.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs index 65038454..169b8f66 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetStartGameTimePacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs index 864f91c3..0de6f601 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/StartLevelPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/DediPacketSetNewManager.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/DediPacketSetNewManager.cs index efe1c4bf..010c1be0 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/DediPacketSetNewManager.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/DediPacketSetNewManager.cs @@ -1,6 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetMpPlayerData.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetMpPlayerData.cs index 03d709ca..bb835900 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetMpPlayerData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetMpPlayerData.cs @@ -1,5 +1,5 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs index 990d3738..726d00dd 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs @@ -1,6 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; using System.Collections.Generic; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpNodePoseSyncStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpNodePoseSyncStatePacket.cs index b32127b5..3eb37b11 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpNodePoseSyncStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpNodePoseSyncStatePacket.cs @@ -1,6 +1,6 @@ using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPlayerData.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPlayerData.cs index eee64196..73156606 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPlayerData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPlayerData.cs @@ -1,6 +1,6 @@ using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStateDeltaPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStateDeltaPacket.cs index 2c5aa246..417cfd23 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStateDeltaPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStateDeltaPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs index 228d47d6..88fb4012 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/NodePoseSyncStatePacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStateDeltaPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStateDeltaPacket.cs index bbf20f12..0e1ab249 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStateDeltaPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStateDeltaPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs index 60bac637..b5ee181f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/ScoreSyncStatePacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs index 8642c0d6..f8dfec9b 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PingPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerAvatarPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerAvatarPacket.cs index 5218b1ac..93c43cde 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerAvatarPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerAvatarPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerConnectedPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerConnectedPacket.cs index 85b1d35e..3921f2ad 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerConnectedPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerConnectedPacket.cs @@ -1,6 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerDisconnectedPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerDisconnectedPacket.cs index 174d0c01..601b7b34 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerDisconnectedPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerDisconnectedPacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Enums; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs index eaa22709..da9879db 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerIdentityPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { public sealed class PlayerIdentityPacket : INetSerializable diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs index 5f64c8e2..f95371ad 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerLatencyPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerSortOrderPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerSortOrderPacket.cs index 57cc5ab8..bf740655 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerSortOrderPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerSortOrderPacket.cs @@ -1,6 +1,6 @@ -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Extensions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerStatePacket.cs index 1dd0d132..80f34fa4 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PlayerStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PlayerStatePacket.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs index e18c4f43..f29b7454 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/PongPacket.cs @@ -1,6 +1,6 @@ using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs index bdcba96d..ee5d31ee 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/SyncTimePacket.cs @@ -1,6 +1,6 @@ using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; -using BeatTogether.LiteNetLib.Util; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; namespace BeatTogether.DedicatedServer.Messaging.Packets { diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/GameplayRpcPacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/GameplayRpcPacketRegistry.cs index fcf0a75a..8b76666e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/GameplayRpcPacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/GameplayRpcPacketRegistry.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Abstractions; namespace BeatTogether.DedicatedServer.Messaging.Registries { diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/MenuRpcPacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/MenuRpcPacketRegistry.cs index e7aa2e19..f7655f43 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/MenuRpcPacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/MenuRpcPacketRegistry.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Abstractions; namespace BeatTogether.DedicatedServer.Messaging.Registries { diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs index 75dcc0ef..74c9b0ba 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Abstractions; using System; using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerSessionPacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerSessionPacketRegistry.cs index 8183ecff..27c82779 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerSessionPacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerSessionPacketRegistry.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession; -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Abstractions; namespace BeatTogether.DedicatedServer.Messaging.Registries { diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/PacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/PacketRegistry.cs index 110e878a..af6f3ef7 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/PacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/PacketRegistry.cs @@ -1,6 +1,6 @@ using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets; -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Abstractions; namespace BeatTogether.DedicatedServer.Messaging.Registries { diff --git a/BeatTogether.DedicatedServer.Messaging/Structs/AvatarSystemIdentifier.cs b/BeatTogether.DedicatedServer.Messaging/Structs/AvatarSystemIdentifier.cs index f8c48cad..8ae8643a 100644 --- a/BeatTogether.DedicatedServer.Messaging/Structs/AvatarSystemIdentifier.cs +++ b/BeatTogether.DedicatedServer.Messaging/Structs/AvatarSystemIdentifier.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - + namespace BeatTogether.DedicatedServer.Messaging.Structs { public struct AvatarSystemIdentifier diff --git a/BeatTogether.DedicatedServer.Messaging/Structs/MultiplayerAvatarData.cs b/BeatTogether.DedicatedServer.Messaging/Structs/MultiplayerAvatarData.cs index 49fc3a2c..c29a7329 100644 --- a/BeatTogether.DedicatedServer.Messaging/Structs/MultiplayerAvatarData.cs +++ b/BeatTogether.DedicatedServer.Messaging/Structs/MultiplayerAvatarData.cs @@ -1,10 +1,4 @@ -using BeatTogether.DedicatedServer.Messaging.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - + namespace BeatTogether.DedicatedServer.Messaging.Structs { public readonly struct MultiplayerAvatarData diff --git a/BeatTogether.DedicatedServer.Messaging/Util/SpanBuffer.cs b/BeatTogether.DedicatedServer.Messaging/Util/SpanBuffer.cs new file mode 100644 index 00000000..5a2f461d --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Util/SpanBuffer.cs @@ -0,0 +1,488 @@ +using System; +using System.Buffers.Binary; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using Krypton.Buffers; + +namespace BeatTogether.DedicatedServer.Messaging.Util +{ + public ref struct SpanBuffer + { + private readonly bool _resize; + + private Span _buffer; + + private int _offset; + public int Offset => _offset; + public ReadOnlySpan ReadOnlyData => _buffer.Slice(0, _offset); + public Span Data => _buffer.Slice(0, _offset); + public int Size => _offset; + public readonly int RemainingSize => _buffer.Length - _offset; + public ReadOnlySpan RemainingData => _buffer.Slice(_offset); + + public SpanBuffer(Span buffer, bool resize = true) + { + _resize = resize; + _buffer = buffer; + _offset = 0; + } + + public SpanBuffer(int size, bool resize = true) + { + _resize = resize; + _buffer = new byte[size].AsSpan(); + _offset = 0; + } + public void SetOffset(int NewOffset) + { + _offset = NewOffset; + } + + #region Writing To buffer + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void Reserve(int length) + { + int num = _offset + length; + if (num > _buffer.Length) + { + ResizeBuffer(num); + } + } + + private void ResizeBuffer(int neededLength) + { + if (!_resize) + { + throw new OutOfSpaceException(_buffer.Length, _offset, neededLength); + } + + byte[] array = new byte[neededLength * 2]; + _buffer.CopyTo(array.AsSpan()); + _buffer = array.AsSpan(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void WriteBool(bool x) + { + Reserve(1); + _buffer[_offset++] = (byte)(x ? 1 : 0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void WriteInt8(sbyte x) + { + Reserve(1); + _buffer[_offset++] = (byte)x; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void WriteUInt8(byte x) + { + Reserve(1); + _buffer[_offset++] = x; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void WriteInt16(short x) + { + Reserve(2); + BinaryPrimitives.WriteInt16LittleEndian(_buffer.Slice(_offset), x); + _offset += 2; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void WriteUInt16(ushort x) + { + Reserve(2); + BinaryPrimitives.WriteUInt16LittleEndian(_buffer.Slice(_offset), x); + _offset += 2; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void WriteInt32(int x) + { + Reserve(4); + BinaryPrimitives.WriteInt32LittleEndian(_buffer.Slice(_offset), x); + _offset += 4; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void WriteUInt32(uint x) + { + Reserve(4); + BinaryPrimitives.WriteUInt32LittleEndian(_buffer.Slice(_offset), x); + _offset += 4; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void WriteUInt64(ulong x) + { + Reserve(8); + BinaryPrimitives.WriteUInt64LittleEndian(_buffer.Slice(_offset), x); + _offset += 8; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void WriteInt64(long x) + { + Reserve(8); + BinaryPrimitives.WriteInt64LittleEndian(_buffer.Slice(_offset), x); + _offset += 8; + } + + public void WriteFloat32(float x) + { + if (!BitConverter.IsLittleEndian) + { + throw new NotImplementedException(); + } + + Reserve(4); + MemoryMarshal.Write(_buffer.Slice(_offset), ref x); + _offset += 4; + } + + public void WriteFloat64(double x) + { + if (!BitConverter.IsLittleEndian) + { + throw new NotImplementedException(); + } + + Reserve(8); + MemoryMarshal.Write(_buffer.Slice(_offset), ref x); + _offset += 8; + } + + public void WriteGuid(Guid guid) + { + Reserve(16); + guid.TryWriteBytes(_buffer.Slice(_offset)); + _offset += 16; + } + + public void WriteString(string str, Encoding encoding) + { + int byteCount = encoding.GetByteCount(str); + Reserve(byteCount + 2); + BinaryPrimitives.WriteUInt16LittleEndian(_buffer.Slice(_offset), (ushort)byteCount); + _offset += 2; + Span bytes = _buffer.Slice(_offset, byteCount); + encoding.GetBytes(str.AsSpan(), bytes); + _offset += byteCount; + } + + public void WriteUTF8String(string str) + { + WriteString(str, Encoding.UTF8); + } + + public void WriteUTF16String(string str) + { + WriteString(str, Encoding.Unicode); + } + + public void WriteBytes(ReadOnlySpan x) + { + Reserve(x.Length); + x.CopyTo(_buffer.Slice(_offset)); + _offset += x.Length; + } + public void PadBytes(int n) + { + Reserve(n); + _offset += n; + } + + public void Dispose() + { + _buffer = Span.Empty; + _offset = 0; + } + + public static implicit operator ReadOnlySpan(SpanBuffer buffer) + { + return buffer.ReadOnlyData; + } + #endregion + + #region ReadingFromBuffer + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void ThrowIfEndOfBuffer(int neededSize) + { + if (_offset + neededSize > _buffer.Length) + { + throw new EndOfBufferException(_buffer.Length, _offset, neededSize); + } + } + + public Span ReadBytes(int count) + { + ThrowIfEndOfBuffer(count); + Span result = _buffer.Slice(_offset, count); + _offset += count; + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public byte ReadByte() + { + ThrowIfEndOfBuffer(1); + return _buffer[_offset++]; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public byte ReadUInt8() + { + return ReadByte(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public sbyte ReadInt8() + { + return (sbyte)ReadByte(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool ReadBool() + { + if (ReadUInt8() != 1) + { + return false; + } + + return true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ushort ReadUInt16() + { + ThrowIfEndOfBuffer(2); + ushort result = BinaryPrimitives.ReadUInt16LittleEndian(_buffer.Slice(_offset)); + _offset += 2; + return result; + } + + public Span ReadUInt16Slice(int count) + { + ThrowIfEndOfBuffer(2 * count); + Span readOnlySpan = MemoryMarshal.Cast(_buffer.Slice(_offset)); + _offset += 2 * count; + if (BitConverter.IsLittleEndian) + { + return readOnlySpan.Slice(0, count); + } + + ushort[] array = new ushort[count]; + for (int i = 0; i < count; i++) + { + array[i] = BinaryPrimitives.ReverseEndianness(readOnlySpan[i]); + } + + return array; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public short ReadInt16() + { + ThrowIfEndOfBuffer(2); + short result = BinaryPrimitives.ReadInt16LittleEndian(_buffer.Slice(_offset)); + _offset += 2; + return result; + } + + public ReadOnlySpan ReadInt16Slice(int count) + { + ThrowIfEndOfBuffer(2 * count); + ReadOnlySpan readOnlySpan = MemoryMarshal.Cast(_buffer.Slice(_offset)); + _offset += 2 * count; + if (BitConverter.IsLittleEndian) + { + return readOnlySpan.Slice(0, count); + } + + short[] array = new short[count]; + for (int i = 0; i < count; i++) + { + array[i] = BinaryPrimitives.ReverseEndianness(readOnlySpan[i]); + } + + return array; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public uint ReadUInt32() + { + ThrowIfEndOfBuffer(4); + uint result = BinaryPrimitives.ReadUInt32LittleEndian(_buffer.Slice(_offset)); + _offset += 4; + return result; + } + + public ReadOnlySpan ReadUInt32Slice(int count) + { + ThrowIfEndOfBuffer(4 * count); + ReadOnlySpan readOnlySpan = MemoryMarshal.Cast(_buffer.Slice(_offset)); + _offset += 4 * count; + if (BitConverter.IsLittleEndian) + { + return readOnlySpan.Slice(0, count); + } + + uint[] array = new uint[count]; + for (int i = 0; i < count; i++) + { + array[i] = BinaryPrimitives.ReverseEndianness(readOnlySpan[i]); + } + + return array; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ReadInt32() + { + ThrowIfEndOfBuffer(4); + int result = BinaryPrimitives.ReadInt32LittleEndian(_buffer.Slice(_offset)); + _offset += 4; + return result; + } + + public ReadOnlySpan ReadInt32Slice(int count) + { + ThrowIfEndOfBuffer(4 * count); + ReadOnlySpan readOnlySpan = MemoryMarshal.Cast(_buffer.Slice(_offset)); + _offset += 4 * count; + if (BitConverter.IsLittleEndian) + { + return readOnlySpan.Slice(0, count); + } + + int[] array = new int[count]; + for (int i = 0; i < count; i++) + { + array[i] = BinaryPrimitives.ReverseEndianness(readOnlySpan[i]); + } + + return array; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ulong ReadUInt64() + { + ThrowIfEndOfBuffer(8); + ulong result = BinaryPrimitives.ReadUInt64LittleEndian(_buffer.Slice(_offset)); + _offset += 8; + return result; + } + + public ReadOnlySpan ReadUInt64Slice(int count) + { + ThrowIfEndOfBuffer(8 * count); + ReadOnlySpan readOnlySpan = MemoryMarshal.Cast(_buffer.Slice(_offset)); + _offset += 8 * count; + if (BitConverter.IsLittleEndian) + { + return readOnlySpan.Slice(0, count); + } + + ulong[] array = new ulong[count]; + for (int i = 0; i < count; i++) + { + array[i] = BinaryPrimitives.ReverseEndianness(readOnlySpan[i]); + } + + return array; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public long ReadInt64() + { + ThrowIfEndOfBuffer(8); + long result = BinaryPrimitives.ReadInt64LittleEndian(_buffer.Slice(_offset)); + _offset += 8; + return result; + } + + public ReadOnlySpan ReadInt64Slice(int count) + { + ThrowIfEndOfBuffer(8 * count); + ReadOnlySpan readOnlySpan = MemoryMarshal.Cast(_buffer.Slice(_offset)); + _offset += 8 * count; + if (BitConverter.IsLittleEndian) + { + return readOnlySpan.Slice(0, count); + } + + long[] array = new long[count]; + for (int i = 0; i < count; i++) + { + array[i] = BinaryPrimitives.ReverseEndianness(readOnlySpan[i]); + } + + return array; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float ReadFloat32() + { + if (!BitConverter.IsLittleEndian) + { + throw new NotImplementedException(); + } + + ThrowIfEndOfBuffer(4); + float result = MemoryMarshal.Read(_buffer.Slice(_offset)); + _offset += 4; + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public double ReadFloat64() + { + if (!BitConverter.IsLittleEndian) + { + throw new NotImplementedException(); + } + + ThrowIfEndOfBuffer(8); + double result = MemoryMarshal.Read(_buffer.Slice(_offset)); + _offset += 8; + return result; + } + + public Guid ReadGuid() + { + ThrowIfEndOfBuffer(16); + Guid result = new Guid(_buffer.Slice(_offset, 16)); + _offset += 16; + return result; + } + + public string ReadString(Encoding encoding) + { + ushort count = ReadUInt16(); + ReadOnlySpan bytes = ReadBytes(count); + return encoding.GetString(bytes); + } + + public string ReadUTF8String() + { + return ReadString(Encoding.UTF8); + } + + public string ReadUTF16String() + { + return ReadString(Encoding.Unicode); + } + + public void SkipBytes(int count) + { + ThrowIfEndOfBuffer(count); + _offset += count; + } + #endregion + } +} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs index 82ca1287..eafd2838 100644 --- a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs +++ b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs @@ -1,9 +1,11 @@ -namespace BeatTogether.DedicatedServer.Node.Configuration +using System; + +namespace BeatTogether.DedicatedServer.Node.Configuration { public sealed class NodeConfiguration { public string HostName { get; set; } = "127.0.0.1"; - public string NodeVersion { get; } = "1.6.0"; + public Version NodeVersion { get; } = new Version(1,6,0); public int BasePort { get; set; } = 30000; public int MaximumSlots { get; set; } = 10000; } diff --git a/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs b/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs index 42e40b80..2416f226 100644 --- a/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs +++ b/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs @@ -9,7 +9,7 @@ using BeatTogether.DedicatedServer.Node.Abstractions; using BeatTogether.DedicatedServer.Node.Configuration; using BeatTogether.Extensions; -using BeatTogether.LiteNetLib.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Abstractions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; diff --git a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs index 3b9feb65..298fbf76 100644 --- a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs +++ b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs @@ -42,8 +42,8 @@ public Task StartAsync(CancellationToken cancellationToken) _autobus.Subscribe(HandleCheckNode); _autobus.Subscribe(HandleDisconnectPlayer); _autobus.Subscribe(HandleCloseServer); - _autobus.Publish(new NodeStartedEvent(_configuration.HostName, _configuration.NodeVersion)); - _logger.Information("Dedicated node version: " + _configuration.NodeVersion + " starting: " + _configuration.HostName); + _autobus.Publish(new NodeStartedEvent(_configuration.HostName, _configuration.NodeVersion.ToString())); + _logger.Information("Dedicated node version: " + _configuration.NodeVersion.ToString() + " starting: " + _configuration.HostName); return Task.CompletedTask; } @@ -108,7 +108,7 @@ private Task HandlePlayerConnectedToMatchmaking(PlayerConnectedToMatchmakingServ private Task HandleCheckNode(CheckNodesEvent checkNodesEvent) { - _autobus.Publish(new NodeOnlineEvent(_configuration.HostName, _configuration.NodeVersion)); + _autobus.Publish(new NodeOnlineEvent(_configuration.HostName, _configuration.NodeVersion.ToString())); return Task.CompletedTask; } From cc72d7c1f9669e72ed72f5f0d25e34e5f038f43c Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 1 Apr 2024 02:01:29 +0100 Subject: [PATCH 083/120] Remove un-needed latency updating code --- .../DedicatedInstance.cs | 39 ------------------- .../ENet/ENetServer.cs | 5 --- 2 files changed, 44 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 7a93aa9d..c4ce3b6d 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -17,17 +17,7 @@ using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; using BeatTogether.DedicatedServer.Messaging.Abstractions; - -//using BeatTogether.LiteNetLib.Sources; using BeatTogether.DedicatedServer.Messaging.Util; - -//using BeatTogether.LiteNetLib; -//using BeatTogether.LiteNetLib.Abstractions; -//using BeatTogether.LiteNetLib.Configuration; -//using BeatTogether.LiteNetLib.Enums; -//using BeatTogether.LiteNetLib.Util; -//using BeatTogether.LiteNetLib.Sources; -//using Microsoft.Extensions.DependencyInjection; using Serilog; using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; @@ -42,7 +32,6 @@ public sealed class DedicatedInstance : ENetServer, IDedicatedInstance public const int SyncTimeDelay = 5000; public InstanceConfiguration _configuration { get; private set; } - //public int LiteNetPort => _configuration.LiteNetPort; public int Port => _configuration.Port; public bool IsRunning => IsAlive; public long RunTime => (DateTime.UtcNow.Ticks - _startTime) / 10000L; @@ -56,14 +45,12 @@ public sealed class DedicatedInstance : ENetServer, IDedicatedInstance public event Action GameIsInLobby = null!; public event Action UpdateInstanceEvent = null!; - //private readonly IHandshakeSessionRegistry _handshakeSessionRegistry; private readonly IPlayerRegistry _playerRegistry; private readonly IServiceProvider _serviceProvider; private readonly PacketEncryptionLayer _packetEncryptionLayer; private readonly IPacketDispatcher PacketDispatcher; private readonly PacketSource ConnectedMessageSource; - //public SemaphoreSlim ConnectDisconnectSemaphore { get; } = new(1); //Stops lobby loop from running during player connection/disconnection, and stops disconnects and connects happening simultaneously private byte _connectionIdCount = 0; private int _lastSortIndex = -1; @@ -74,21 +61,14 @@ public sealed class DedicatedInstance : ENetServer, IDedicatedInstance private long _startTime; private CancellationTokenSource? _waitForPlayerCts = null; private CancellationTokenSource? _stopServerCts; - - - //public readonly ENetServer ENetServer; public DedicatedInstance( InstanceConfiguration configuration, - //IHandshakeSessionRegistry handshakeSessionRegistry, IPlayerRegistry playerRegistry, - //LiteNetConfiguration liteNetConfiguration, - //LiteNetPacketRegistry registry, IPacketDispatcher packetDispatcher, PacketSource connectedMessageSource, IServiceProvider serviceProvider, - //IPacketLayer packetLayer, PacketEncryptionLayer packetEncryptionLayer) : base (configuration.Port) { @@ -343,21 +323,6 @@ public void SetState(MultiplayerGameState state) if (_waitForPlayerCts != null) _waitForPlayerCts.Cancel(); - // Retrieve encryption params and platform data from handshake process by player session token, if provided - //if (!string.IsNullOrEmpty(connectionRequestData.PlayerSessionId)) - //{ - //var handshakeSession = - // _handshakeSessionRegistry.TryGetByPlayerSessionId(connectionRequestData.PlayerSessionId); - //GetPlayerRegistry().RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out var ClientVer, out var Platform, out var PlayerPlatformUserId); - //player.ClientVersion = ClientVer; - //player.Platform = (Enums.Platform)Platform; - //player.PlatformUserId = PlayerPlatformUserId; - //if (handshakeSession != null && handshakeSession.EncryptionParameters != null) - //{ - // _packetEncryptionLayer.AddEncryptedEndPoint((IPEndPoint)endPoint, - // handshakeSession.EncryptionParameters, true); - //} - //} if (GetPlayerRegistry().RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out var ClientVer, out var Platform, out var PlayerPlatformUserId)) { player.ClientVersion = ClientVer; @@ -406,10 +371,6 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, I #endregion - - public override void OnLatencyUpdate(EndPoint endPoint, int latency) - => _logger.Verbose($"Latency updated (RemoteEndPoint='{endPoint}', Latency={0.001f * latency})."); - public override void OnConnect(EndPoint endPoint) { _logger.Information($"Endpoint connected (RemoteEndPoint='{endPoint}')"); diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs index d948d1df..3280ff48 100644 --- a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs @@ -2,7 +2,6 @@ using System.Buffers; using System.Collections.Generic; using System.Net; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using BeatTogether.DedicatedServer.Ignorance.ENet; @@ -327,10 +326,6 @@ public virtual void OnDisconnect(EndPoint endPoint) { } - public virtual void OnLatencyUpdate(EndPoint endPoint, int latency) - { - } - public virtual void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, IgnoranceChannelTypes method) { } From 5dd6876a305a0072e31ff883e716e04e1dfc5e10 Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 1 Apr 2024 02:20:45 +0100 Subject: [PATCH 084/120] Added per player difficulties and per player modifier packets --- .../SetPerPlayerDiffHandler.cs | 6 +++ .../CommandHandlers/SetPerPlayerModHandler.cs | 7 +++ .../DediPacketSetNewManagerHandler.cs | 6 +-- .../MultiplayerCore/GetPerPlayerHandler.cs | 37 ++++++++++++++++ .../MultiplayerCore/PerPlayerHandler.cs | 43 +++++++++++++++++++ .../MpCorePackets/GetPerPlayer.cs | 16 +++++++ .../MpCorePackets/PerPlayer.cs | 23 ++++++++++ 7 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetPerPlayerHandler.cs create mode 100644 BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/PerPlayerHandler.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetPerPlayer.cs create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/PerPlayer.cs diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs index ff743992..771255ce 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs @@ -3,6 +3,7 @@ using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers { @@ -24,6 +25,11 @@ public override void Handle(IPlayer player, SetPerPlayerDifficulties command) { Text = "Per player difficulties: " + command.Enabled }, IgnoranceChannelTypes.Reliable); + _packetDisapatcher.SendToNearbyPlayers(new PerPlayer() + { + PPDEnabled = _Configuration.AllowPerPlayerDifficulties, + PPMEnabled = _Configuration.AllowPerPlayerModifiers, + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs index bec00152..56f8fb67 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs @@ -3,6 +3,8 @@ using BeatTogether.DedicatedServer.Kernel.CommandHandlers; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MPChatPackets; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; +using Microsoft.Extensions.Configuration; namespace BeatTogether.DedicatedServer.Kernel.Commands.CommandHandlers { @@ -24,6 +26,11 @@ public override void Handle(IPlayer player, SetPerPlayerModifiers command) { Text = "Per player modifiers: " + command.Enabled }, IgnoranceChannelTypes.Reliable); + _packetDisapatcher.SendToNearbyPlayers(new PerPlayer() + { + PPDEnabled = _Configuration.AllowPerPlayerDifficulties, + PPMEnabled = _Configuration.AllowPerPlayerModifiers, + }, IgnoranceChannelTypes.Reliable); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs index b415076d..6effb847 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs @@ -11,9 +11,9 @@ namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession. { class DediPacketSetNewManagerPacketHandler : BasePacketHandler { - public InstanceConfiguration _configuration; - public readonly IPacketDispatcher _packetDispatcher; - public readonly IPlayerRegistry _playerRegistry; + private InstanceConfiguration _configuration; + private readonly IPacketDispatcher _packetDispatcher; + private readonly IPlayerRegistry _playerRegistry; private readonly ILogger _logger = Log.ForContext(); public DediPacketSetNewManagerPacketHandler( diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetPerPlayerHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetPerPlayerHandler.cs new file mode 100644 index 00000000..e99a4d4b --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetPerPlayerHandler.cs @@ -0,0 +1,37 @@ +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; +using Serilog; + +namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc +{ + class GetPerPlayerHandler : BasePacketHandler + { + private InstanceConfiguration _configuration; + private readonly IPacketDispatcher _PacketDispatcher; + private readonly ILogger _logger = Log.ForContext(); + + public GetPerPlayerHandler( + IPacketDispatcher PacketDispatcher, + InstanceConfiguration configuration) + { + _PacketDispatcher = PacketDispatcher; + _configuration = configuration; + } + + public override void Handle(IPlayer sender, GetPerPlayer packet) + { + + _logger.Debug( + $"Handling packet of type '{nameof(GetPerPlayer)}' " + + $"(SenderId={sender.ConnectionId})." + ); + _PacketDispatcher.SendToPlayer(sender, new PerPlayer() + { + PPDEnabled = _configuration.AllowPerPlayerDifficulties, + PPMEnabled = _configuration.AllowPerPlayerModifiers, + }, IgnoranceChannelTypes.Reliable); + } + } +} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/PerPlayerHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/PerPlayerHandler.cs new file mode 100644 index 00000000..516ced50 --- /dev/null +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/PerPlayerHandler.cs @@ -0,0 +1,43 @@ +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets; +using Serilog; + +namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc +{ + class PerPlayerHandler : BasePacketHandler + { + private InstanceConfiguration _configuration; + private readonly IPacketDispatcher _PacketDispatcher; + private readonly ILogger _logger = Log.ForContext(); + + public PerPlayerHandler( + IPacketDispatcher PacketDispatcher, + InstanceConfiguration configuration) + { + _PacketDispatcher = PacketDispatcher; + _configuration = configuration; + } + + public override void Handle(IPlayer sender, PerPlayer packet) + { + + _logger.Debug( + $"Handling packet of type '{nameof(PerPlayer)}' " + + $"(SenderId={sender.ConnectionId})." + ); + if(sender.IsServerOwner) + { + _configuration.AllowPerPlayerDifficulties = packet.PPDEnabled; + _configuration.AllowPerPlayerModifiers = packet.PPMEnabled; + _PacketDispatcher.SendToNearbyPlayers(new PerPlayer() + { + PPDEnabled = _configuration.AllowPerPlayerDifficulties, + PPMEnabled = _configuration.AllowPerPlayerModifiers, + }, IgnoranceChannelTypes.Reliable); + } + + } + } +} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetPerPlayer.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetPerPlayer.cs new file mode 100644 index 00000000..67e7a923 --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetPerPlayer.cs @@ -0,0 +1,16 @@ +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets +{ + public sealed class GetPerPlayer : INetSerializable + { + public void ReadFrom(ref SpanBuffer bufferReader) + { + } + + public void WriteTo(ref SpanBuffer bufferWriter) + { + } + } +} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/PerPlayer.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/PerPlayer.cs new file mode 100644 index 00000000..0dad8bfb --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/PerPlayer.cs @@ -0,0 +1,23 @@ +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets +{ + public sealed class PerPlayer : INetSerializable + { + public bool PPDEnabled; + public bool PPMEnabled; + + public void ReadFrom(ref SpanBuffer bufferReader) + { + PPDEnabled = bufferReader.ReadBool(); + PPMEnabled = bufferReader.ReadBool(); + } + + public void WriteTo(ref SpanBuffer bufferWriter) + { + bufferWriter.WriteBool(PPDEnabled); + bufferWriter.WriteBool(PPMEnabled); + } + } +} \ No newline at end of file From fa8cfdf0cc5931a1a707f4123e4a7ce4e6cf0f62 Mon Sep 17 00:00:00 2001 From: cubic Date: Tue, 2 Apr 2024 04:14:02 +0100 Subject: [PATCH 085/120] Removed encryption layers --- .../Abstractions/IPacketDispatcher.cs | 13 - .../DedicatedInstance.cs | 6 +- .../Abstractions/IEncryptedPacketReader.cs | 11 - .../Abstractions/IEncryptedPacketWriter.cs | 11 - .../Encryption/EncryptedPacketReader.cs | 57 --- .../Encryption/EncryptedPacketWriter.cs | 61 --- .../Encryption/EncryptionParameters.cs | 25 -- .../Encryption/PacketEncryptionLayer.cs | 350 ------------------ .../Abstractions/IPacketLayer.cs | 11 - .../Extensions/HostBuilderExtensions.cs | 8 - .../MasterServerEventHandler.cs | 38 +- .../NodeService.cs | 10 +- 12 files changed, 4 insertions(+), 597 deletions(-) delete mode 100644 BeatTogether.DedicatedServer.Kernel/Encryption/Abstractions/IEncryptedPacketReader.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Encryption/Abstractions/IEncryptedPacketWriter.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketReader.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Encryption/EncryptionParameters.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Abstractions/IPacketLayer.cs diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs index 1cefe924..0890c705 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs @@ -15,18 +15,5 @@ public interface IPacketDispatcher void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod); void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, IgnoranceChannelTypes deliveryMethod); void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod); - - /* - Task SendToNearbyPlayersAndAwait(INetSerializable packet, DeliveryMethod deliveryMethod); - Task SendToNearbyPlayersAndAwait(INetSerializable[] packets, DeliveryMethod deliveryMethod); - Task SendExcludingPlayerAndAwait(IPlayer excludedPlayer, INetSerializable packet, DeliveryMethod deliveryMethod); - Task SendExcludingPlayerAndAwait(IPlayer excludedPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); - Task SendFromPlayerAndAwait(IPlayer fromPlayer, INetSerializable packet, DeliveryMethod deliveryMethod); - Task SendFromPlayerAndAwait(IPlayer fromPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); - Task SendFromPlayerToPlayerAndAwait(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable packet, DeliveryMethod deliveryMethod); - Task SendFromPlayerToPlayerAndAwait(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, DeliveryMethod deliveryMethod); - Task SendToPlayerAndAwait(IPlayer player, INetSerializable packet, DeliveryMethod deliveryMethod); - Task SendToPlayerAndAwait(IPlayer player, INetSerializable[] packets, DeliveryMethod deliveryMethod); - */ } } diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index c4ce3b6d..7d30761a 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; -using BeatTogether.DedicatedServer.Kernel.Encryption; using BeatTogether.DedicatedServer.Kernel.ENet; using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Extensions; @@ -47,7 +46,6 @@ public sealed class DedicatedInstance : ENetServer, IDedicatedInstance private readonly IPlayerRegistry _playerRegistry; private readonly IServiceProvider _serviceProvider; - private readonly PacketEncryptionLayer _packetEncryptionLayer; private readonly IPacketDispatcher PacketDispatcher; private readonly PacketSource ConnectedMessageSource; @@ -68,14 +66,12 @@ public DedicatedInstance( IPlayerRegistry playerRegistry, IPacketDispatcher packetDispatcher, PacketSource connectedMessageSource, - IServiceProvider serviceProvider, - PacketEncryptionLayer packetEncryptionLayer) + IServiceProvider serviceProvider) : base (configuration.Port) { _configuration = configuration; _playerRegistry = playerRegistry; _serviceProvider = serviceProvider; - _packetEncryptionLayer = packetEncryptionLayer; PacketDispatcher = packetDispatcher; ConnectedMessageSource = connectedMessageSource; } diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/Abstractions/IEncryptedPacketReader.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/Abstractions/IEncryptedPacketReader.cs deleted file mode 100644 index b245f797..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/Abstractions/IEncryptedPacketReader.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Krypton.Buffers; -using System; -using System.Security.Cryptography; - -namespace BeatTogether.DedicatedServer.Kernel.Encryption.Abstractions -{ - public interface IEncryptedPacketReader - { - ReadOnlyMemory ReadFrom(ref SpanBufferReader bufferReader, byte[] key, HMAC hmac); - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/Abstractions/IEncryptedPacketWriter.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/Abstractions/IEncryptedPacketWriter.cs deleted file mode 100644 index ac0b9208..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/Abstractions/IEncryptedPacketWriter.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Security.Cryptography; -using Krypton.Buffers; - -namespace BeatTogether.DedicatedServer.Kernel.Encryption.Abstractions -{ - public interface IEncryptedPacketWriter - { - void WriteTo(ref SpanBufferWriter bufferWriter, ReadOnlySpan data, uint sequenceId, byte[] key, HMAC hmac); - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketReader.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketReader.cs deleted file mode 100644 index 5c1a9978..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketReader.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Linq; -using System.Security.Cryptography; -using BeatTogether.DedicatedServer.Kernel.Encryption.Abstractions; -using Krypton.Buffers; -using Serilog; - -namespace BeatTogether.DedicatedServer.Kernel.Encryption -{ - public sealed class EncryptedPacketReader : IEncryptedPacketReader - { - private readonly ILogger _logger = Log.ForContext(); - - /// - public ReadOnlyMemory ReadFrom(ref SpanBufferReader bufferReader, byte[] key, HMAC hmac) - { - var sequenceId = bufferReader.ReadUInt32(); - var iv = bufferReader.ReadBytes(16).ToArray(); - var decryptedBuffer = bufferReader.RemainingData.ToArray(); - using (var aes = Aes.Create()) - { - aes.Padding = PaddingMode.None; - using (var cryptoTransform = aes.CreateDecryptor(key, iv)) - { - var bytesWritten = 0; - var offset = 0; - for (var i = decryptedBuffer.Length; i >= cryptoTransform.InputBlockSize; i -= bytesWritten) - { - var inputCount = cryptoTransform.CanTransformMultipleBlocks - ? (i / cryptoTransform.InputBlockSize * cryptoTransform.InputBlockSize) - : cryptoTransform.InputBlockSize; - bytesWritten = cryptoTransform.TransformBlock( - decryptedBuffer, offset, inputCount, - decryptedBuffer, offset - ); - offset += bytesWritten; - } - } - } - - var paddingByteCount = decryptedBuffer[decryptedBuffer.Length - 1] + 1; - var hmacStart = decryptedBuffer.Length - paddingByteCount - 10; - var decryptedBufferSpan = decryptedBuffer.AsSpan(); - var hash = decryptedBufferSpan.Slice(hmacStart, 10); - var hashBufferWriter = new SpanBufferWriter(stackalloc byte[decryptedBuffer.Length + 4]); - hashBufferWriter.WriteBytes(decryptedBufferSpan.Slice(0, hmacStart)); - hashBufferWriter.WriteUInt32(sequenceId); - Span computedHash = stackalloc byte[32]; - if (!hmac.TryComputeHash(hashBufferWriter.Data, computedHash, out _)) - throw new Exception("Failed to compute message hash."); - if (!hash.SequenceEqual(computedHash.Slice(0, 10))) - throw new Exception("Message hash does not match the computed hash."); - - return decryptedBufferSpan.Slice(0, hmacStart).ToArray(); - } - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs deleted file mode 100644 index dffec1bd..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptedPacketWriter.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Security.Cryptography; -using BeatTogether.DedicatedServer.Kernel.Encryption.Abstractions; -using BeatTogether.DedicatedServer.Messaging.Util; -using Krypton.Buffers; - -namespace BeatTogether.DedicatedServer.Kernel.Encryption -{ - public sealed class EncryptedPacketWriter : IEncryptedPacketWriter - { - private readonly RandomNumberGenerator _rngCryptoServiceProvider; - - public EncryptedPacketWriter( - RandomNumberGenerator rngCryptoServiceProvider) - { - _rngCryptoServiceProvider = rngCryptoServiceProvider; - } - public void WriteTo(ref SpanBufferWriter bufferWriter, ReadOnlySpan data, uint sequenceId, byte[] key, HMAC hmac) - { - var unencryptedBufferWriter = new SpanBuffer(stackalloc byte[data.Length + 128 + 10], false); - unencryptedBufferWriter.WriteBytes(data); - unencryptedBufferWriter.WriteUInt32(sequenceId); - Span hash = stackalloc byte[32]; - if (!hmac.TryComputeHash(unencryptedBufferWriter.Data, hash, out _)) - throw new Exception("Failed to compute message hash."); - unencryptedBufferWriter.SetOffset(data.Length); - unencryptedBufferWriter.WriteBytes(hash.Slice(0, 10)); - - var iv = new byte[16]; - _rngCryptoServiceProvider.GetBytes(iv); - - var paddingByteCount = (byte)((16 - ((unencryptedBufferWriter.Size + 1) & 15)) & 15); - for (var i = 0; i < paddingByteCount + 1; i++) - unencryptedBufferWriter.WriteUInt8(paddingByteCount); - - var encryptedBuffer = unencryptedBufferWriter.Data.ToArray(); - using (var aes = Aes.Create()) - { - aes.Padding = PaddingMode.None; - using (var cryptoTransform = aes.CreateEncryptor(key, iv)) - { - var bytesWritten = 0; - for (var i = encryptedBuffer.Length; i >= cryptoTransform.InputBlockSize; i -= bytesWritten) - { - var inputCount = cryptoTransform.CanTransformMultipleBlocks - ? (i / cryptoTransform.InputBlockSize * cryptoTransform.InputBlockSize) - : cryptoTransform.InputBlockSize; - bytesWritten = cryptoTransform.TransformBlock( - encryptedBuffer, bytesWritten, inputCount, - encryptedBuffer, bytesWritten - ); - } - } - } - - bufferWriter.WriteUInt32(sequenceId); - bufferWriter.WriteBytes(iv); - bufferWriter.WriteBytes(encryptedBuffer); - } - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptionParameters.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptionParameters.cs deleted file mode 100644 index 8e725f73..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/EncryptionParameters.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Threading; - -namespace BeatTogether.DedicatedServer.Kernel.Encryption -{ - public sealed class EncryptionParameters - { - public byte[] ReceiveKey { get; } - public byte[] SendKey { get; } - public byte[] ReceiveMac { get; } - public byte[] SendMac { get; } - - private uint _lastSequenceId = 0U; - - public EncryptionParameters(byte[] receiveKey, byte[] sendKey, byte[] receiveMac, byte[] sendMac) - { - ReceiveKey = receiveKey; - SendKey = sendKey; - ReceiveMac = receiveMac; - SendMac = sendMac; - } - - public uint GetNextSequenceId() => - unchecked(Interlocked.Increment(ref _lastSequenceId)); - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs b/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs deleted file mode 100644 index a014f519..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Encryption/PacketEncryptionLayer.cs +++ /dev/null @@ -1,350 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Diagnostics.CodeAnalysis; -using System.Net; -using System.Security.Cryptography; -using System.Text; -using BeatTogether.Core.Security.Abstractions; -using BeatTogether.Core.Security.Models; -using BeatTogether.DedicatedServer.Kernel.Encryption.Abstractions; -using BeatTogether.DedicatedServer.Messaging.Abstractions; -using Krypton.Buffers; -using Serilog; - -namespace BeatTogether.DedicatedServer.Kernel.Encryption -{ - public sealed class PacketEncryptionLayer : IPacketLayer - { - public byte[] Random { get; } = new byte[32]; - public ECKeyPair KeyPair { get; } - - private readonly IEncryptedPacketReader _encryptedPacketReader; - private readonly IEncryptedPacketWriter _encryptedPacketWriter; - private readonly IDiffieHellmanService _diffieHellmanService; - private readonly ILogger _logger = Log.ForContext(); - - private readonly ConcurrentDictionary _potentialEncryptionParameters = new(); - private readonly ConcurrentDictionary _encryptionParameters = new(); - - private static readonly byte[] _masterSecretSeed = Encoding.UTF8.GetBytes("master secret"); - private static readonly byte[] _keyExpansionSeed = Encoding.UTF8.GetBytes("key expansion"); - - public PacketEncryptionLayer( - IEncryptedPacketReader encryptedPacketReader, - IEncryptedPacketWriter encryptedPacketWriter, - IDiffieHellmanService diffieHellmanService, - RandomNumberGenerator rngCryptoServiceProvider) - { - _encryptedPacketReader = encryptedPacketReader; - _encryptedPacketWriter = encryptedPacketWriter; - _diffieHellmanService = diffieHellmanService; - - rngCryptoServiceProvider.GetBytes(Random); - KeyPair = _diffieHellmanService.GetECKeyPair(); - } - - #region Public Methods - - public void AddEncryptedEndPoint(IPEndPoint endPoint, EncryptionParameters encryptionParameters, - bool definitive = false) - { - if (definitive) - { - _encryptionParameters[endPoint] = encryptionParameters; - } - else - { - _potentialEncryptionParameters[endPoint.Address] = encryptionParameters; - _encryptionParameters.TryRemove(endPoint, out _); - } - } - - public void AddEncryptedEndPoint(IPEndPoint endPoint, - BeatTogether.Core.Messaging.Models.EncryptionParameters encryptionParameters, - bool definitive = false) - { - AddEncryptedEndPoint(endPoint, new EncryptionParameters(encryptionParameters.ReceiveKey, - encryptionParameters.SendKey, encryptionParameters.ReceiveMac.Key, encryptionParameters.SendMac.Key), - definitive); - } - - public void AddEncryptedEndPoint( - IPEndPoint endPoint, - byte[] clientRandom, - byte[] clientPublicKey, - bool definitive = false) - { - var clientPublicKeyParameters = _diffieHellmanService.DeserializeECPublicKey(clientPublicKey); - var preMasterSecret = - _diffieHellmanService.GetPreMasterSecret(clientPublicKeyParameters, KeyPair.PrivateKeyParameters); - var sendKey = new byte[32]; - var receiveKey = new byte[32]; - var sendMacSourceArray = new byte[64]; - var receiveMacSourceArray = new byte[64]; - var masterSecretSeed = MakeSeed(_masterSecretSeed, Random, clientRandom); - var keyExpansionSeed = MakeSeed(_keyExpansionSeed, Random, clientRandom); - var sourceArray = PRF( - PRF(preMasterSecret, masterSecretSeed, 48), - keyExpansionSeed, - 192 - ); - Array.Copy(sourceArray, 0, sendKey, 0, 32); - Array.Copy(sourceArray, 32, receiveKey, 0, 32); - Array.Copy(sourceArray, 64, sendMacSourceArray, 0, 64); - Array.Copy(sourceArray, 128, receiveMacSourceArray, 0, 64); - var encryptionParameters = new EncryptionParameters( - receiveKey, - sendKey, - receiveMacSourceArray, - sendMacSourceArray - ); - - AddEncryptedEndPoint(endPoint, encryptionParameters, definitive); - } - - public void RemoveEncryptedEndPoint(IPEndPoint endPoint) - { - _potentialEncryptionParameters.TryRemove(endPoint.Address, out _); - _encryptionParameters.TryRemove(endPoint, out _); - } - - public void ProcessInboundPacket(EndPoint endPoint, ref Span data) - { - var address = ((IPEndPoint) endPoint).Address; - - if (data.Length == 0) - return; - - var bufferReader = new SpanBufferReader(data); - - if (!bufferReader.ReadBool()) // NotEncrypted - { - // Received an unencrypted packet - this is valid if the client is still negotiating - // Slice out the encryption flag and continue - data = data[1..]; - // TODO Reject unencrypted inbound packets for regular clients past the negotiation stage? - return; - } - byte[]? decryptedData; - - if (_encryptionParameters.TryGetValue(endPoint, out var encryptionParameters)) - { - if (TryDecrypt(ref bufferReader, encryptionParameters, out decryptedData)) - data = decryptedData; - else - data = Array.Empty(); - - return; - } - - if (_potentialEncryptionParameters.TryGetValue(address, out encryptionParameters)) - { - if (TryDecrypt(ref bufferReader, encryptionParameters, out decryptedData)) - { - _encryptionParameters[endPoint] = encryptionParameters; - _potentialEncryptionParameters.TryRemove(address, out _); - data = decryptedData; - } - else - data = Array.Empty(); - return; - } - - // Cannot decrypt incoming packet - // This can happen briefly when the handshake process switches to encrypted mode - _logger.Information( - "Failed to retrieve decryption parameters " + - $"(RemoteEndPoint='{endPoint}')." - ); - data = Array.Empty(); - } - - public void ProcessOutBoundPacket(EndPoint endPoint, ref Span data) //Not used - { - if (!_encryptionParameters.TryGetValue(endPoint, out var encryptionParameters)) - { - if (_potentialEncryptionParameters.TryGetValue(((IPEndPoint) endPoint).Address, - out var encryptionParametersOld)) - { - _logger.Warning( - $"Re-assigning encryption parameters as old parameters (RemoteEndPoint='{endPoint}')."); - encryptionParameters = _encryptionParameters.GetOrAdd(endPoint, encryptionParametersOld); - } - } - - var bufferWriter = new SpanBufferWriter(stackalloc byte[412]); - - if (encryptionParameters != null) - { - bufferWriter.WriteBool(true); // isEncrypted - - using (var hmac = new HMACSHA256(encryptionParameters.SendMac)) - { - _encryptedPacketWriter.WriteTo( - ref bufferWriter, data, - encryptionParameters.GetNextSequenceId(), - encryptionParameters.SendKey, hmac); - } - } - else - { - // Failed to retrieve encryption parameters for send - // During early handshake, this is legitimate - - bufferWriter.WriteBool(false); // NotEncrypted - bufferWriter.WriteBytes(data); - } - data = bufferWriter.Data.ToArray(); - - } - - public void ProcessInboundPacket(EndPoint endPoint, ref Memory data) // Not used - { - var address = ((IPEndPoint)endPoint).Address; - - if (data.Length == 0) - return; - - var bufferReader = new SpanBufferReader(data.Span); - - if (!bufferReader.ReadBool()) // NotEncrypted - { - // Received an unencrypted packet - this is valid if the client is still negotiating - // Slice out the encryption flag and continue - data = data[1..]; - // TODO Reject unencrypted inbound packets for regular clients past the negotiation stage? - return; - } - - byte[]? decryptedData; - - if (_encryptionParameters.TryGetValue(endPoint, out var encryptionParameters)) - { - if (TryDecrypt(ref bufferReader, encryptionParameters, out decryptedData)) - data = decryptedData; - else - data = Array.Empty(); - return; - } - - if (_potentialEncryptionParameters.TryGetValue(address, out encryptionParameters)) - { - if (TryDecrypt(ref bufferReader, encryptionParameters, out decryptedData)) - { - _encryptionParameters[endPoint] = encryptionParameters; - _potentialEncryptionParameters.TryRemove(address, out _); - data = decryptedData; - } - else - data = Array.Empty(); - return; - } - - // Cannot decrypt incoming packet - // This can happen briefly when the handshake process switches to encrypted mode - _logger.Information( - "Failed to retrieve decryption parameters " + - $"(RemoteEndPoint='{endPoint}')." - ); - data = Array.Empty(); - } - - public void ProcessOutBoundPacket(EndPoint endPoint, ref Memory data) - { - if (!_encryptionParameters.TryGetValue(endPoint, out var encryptionParameters)) - { - if (_potentialEncryptionParameters.TryGetValue(((IPEndPoint)endPoint).Address, - out var encryptionParametersOld)) - { - _logger.Warning( - $"Re-assigning encryption parameters as old parameters (RemoteEndPoint='{endPoint}')."); - encryptionParameters = _encryptionParameters.GetOrAdd(endPoint, encryptionParametersOld); - } - } - - var bufferWriter = new SpanBufferWriter(stackalloc byte[data.Length + 256], false); - - if (encryptionParameters != null) - { - bufferWriter.WriteBool(true); // isEncrypted - - using var hmac = new HMACSHA256(encryptionParameters.SendMac); - _encryptedPacketWriter.WriteTo( - ref bufferWriter, data.Span, - encryptionParameters.GetNextSequenceId(), - encryptionParameters.SendKey, hmac); - } - else - { - // Failed to retrieve encryption parameters for send - // During early handshake, this is legitimate - - bufferWriter.WriteBool(false); // NotEncrypted - bufferWriter.WriteBytes(data.Span); - } - data = bufferWriter.Data.ToArray(); - } - #endregion - - #region Private Methods - - private static byte[] MakeSeed(byte[] baseSeed, byte[] serverSeed, byte[] clientSeed) - { - var seed = new byte[baseSeed.Length + serverSeed.Length + clientSeed.Length]; - Array.Copy(baseSeed, 0, seed, 0, baseSeed.Length); - Array.Copy(serverSeed, 0, seed, baseSeed.Length, serverSeed.Length); - Array.Copy(clientSeed, 0, seed, baseSeed.Length + serverSeed.Length, clientSeed.Length); - return seed; - } - - private static byte[] PRF(byte[] key, byte[] seed, int length) - { - var i = 0; - var array = new byte[length + seed.Length]; - while (i < length) - { - Array.Copy(seed, 0, array, i, seed.Length); - PRFHash(key, array, ref i); - } - - var array2 = new byte[length]; - Array.Copy(array, 0, array2, 0, length); - return array2; - } - - private static void PRFHash(byte[] key, byte[] seed, ref int length) - { - using var hmacsha256 = new HMACSHA256(key); - var array = hmacsha256.ComputeHash(seed, 0, length); - var num = Math.Min(length + array.Length, seed.Length); - Array.Copy(array, 0, seed, length, num - length); - length = num; - } - - private bool TryDecrypt( - ref SpanBufferReader bufferReader, - EncryptionParameters encryptionParameters, - [MaybeNullWhen(false)] out byte[] data) - { - try - { - using (var hmac = new HMACSHA256(encryptionParameters.ReceiveMac)) - { - data = _encryptedPacketReader - .ReadFrom(ref bufferReader, encryptionParameters.ReceiveKey, hmac) - .ToArray(); - } - - return true; - } - catch (Exception e) - { - _logger.Warning($"Failed to decrypt packet: {e.Message}"); - data = null; - return false; - } - } - - #endregion - } -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Messaging/Abstractions/IPacketLayer.cs b/BeatTogether.DedicatedServer.Messaging/Abstractions/IPacketLayer.cs deleted file mode 100644 index 716432e0..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Abstractions/IPacketLayer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Net; - -namespace BeatTogether.DedicatedServer.Messaging.Abstractions -{ - public interface IPacketLayer - { - public void ProcessInboundPacket(EndPoint endPoint, ref Span data); - public void ProcessOutBoundPacket(EndPoint endPoint, ref Span data); - } -} diff --git a/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs b/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs index 2416f226..3c2137ee 100644 --- a/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs +++ b/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs @@ -2,14 +2,11 @@ using Autobus; using BeatTogether.DedicatedServer.Interface; using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Encryption; -using BeatTogether.DedicatedServer.Kernel.Encryption.Abstractions; using BeatTogether.DedicatedServer.Kernel.Extensions; using BeatTogether.DedicatedServer.Kernel.Providers; using BeatTogether.DedicatedServer.Node.Abstractions; using BeatTogether.DedicatedServer.Node.Configuration; using BeatTogether.Extensions; -using BeatTogether.DedicatedServer.Messaging.Abstractions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -30,11 +27,6 @@ public static IHostBuilder UseDedicatedServerNode(this IHostBuilder hostBuilder) .AddSingleton(RandomNumberGenerator.Create()) .AddSingleton() .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton(services => - services.GetRequiredService()) .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs index 298fbf76..84ed16a4 100644 --- a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs +++ b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs @@ -5,7 +5,6 @@ using Autobus; using BeatTogether.DedicatedServer.Interface.Events; using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Encryption; using BeatTogether.DedicatedServer.Node.Abstractions; using BeatTogether.DedicatedServer.Node.Configuration; using BeatTogether.MasterServer.Interface.Events; @@ -17,19 +16,16 @@ namespace BeatTogether.DedicatedServer.Node public sealed class MasterServerEventHandler : IHostedService { private readonly IAutobus _autobus; - private readonly PacketEncryptionLayer _packetEncryptionLayer; private readonly ILogger _logger = Log.ForContext(); private readonly NodeConfiguration _configuration; private readonly IInstanceRegistry _instanceRegistry; public MasterServerEventHandler( IAutobus autobus, - PacketEncryptionLayer packetEncryptionLayer, NodeConfiguration nodeConfiguration, IInstanceRegistry instanceRegistry) { _autobus = autobus; - _packetEncryptionLayer = packetEncryptionLayer; _configuration = nodeConfiguration; _instanceRegistry = instanceRegistry; } @@ -65,41 +61,14 @@ private Task HandlePlayerConnectedToMatchmaking(PlayerConnectedToMatchmakingServ if (@event.NodeEndpoint != _configuration.HostName) return Task.CompletedTask; - var remoteEndPoint = IPEndPoint.Parse(@event.RemoteEndPoint); - var random = @event.Random; - var publicKey = @event.PublicKey; + //var remoteEndPoint = IPEndPoint.Parse(@event.RemoteEndPoint); var playerSessionId = @event.PlayerSessionId; var serverSecret = @event.Secret; var PlayerClientVersion = @event.ClientVersion; var PlayerPlatform = @event.Platform; var PlayerPlatformUserId = @event.PlatformUserId; - // Clients connecting via Graph API will connect directly to us to negotiate encryption parameters - var hasEncryptionParams = random != null && publicKey != null && random.Length > 0 && publicKey.Length > 0; - - if (hasEncryptionParams) - { - _logger.Verbose( - "Adding encrypted end point " + - $"(RemoteEndPoint='{remoteEndPoint}', " + - $"Random='{BitConverter.ToString(random!)}', " + - $"PublicKey='{BitConverter.ToString(publicKey!)}')." - ); - _packetEncryptionLayer.AddEncryptedEndPoint(remoteEndPoint, random!, publicKey!); - } - else - { - //_logger.Verbose( - // "Master server notified us of connecting graph client " + - // $"(RemoteEndPoint='{remoteEndPoint}', " + - // $"PlayerSessionId='{playerSessionId}')." - //); - - //var HandshakeRegistry = TryGetDedicatedInstance(serverSecret)? - // .GetHandshakeSessionRegistry(); - //HandshakeRegistry?.AddPendingPlayerSessionId(playerSessionId); - //HandshakeRegistry?.AddExtraPlayerSessionData(playerSessionId, PlayerClientVersion, PlayerPlatform, PlayerPlatformUserId); - } + TryGetDedicatedInstance(serverSecret)?.GetPlayerRegistry().AddExtraPlayerSessionData(playerSessionId, PlayerClientVersion, PlayerPlatform, PlayerPlatformUserId); _autobus.Publish(new NodeReceivedPlayerEncryptionEvent(_configuration.HostName, @event.RemoteEndPoint)); @@ -116,9 +85,6 @@ private Task HandleDisconnectPlayer(DisconnectPlayerFromMatchmakingServerEvent d { TryGetDedicatedInstance(disconnectEvent.Secret)?.DisconnectPlayer(disconnectEvent.UserId); - if (!string.IsNullOrEmpty(disconnectEvent.UserEndPoint)) - _packetEncryptionLayer.RemoveEncryptedEndPoint(IPEndPoint.Parse(disconnectEvent.UserEndPoint)); - return Task.CompletedTask; } diff --git a/BeatTogether.DedicatedServer.Node/NodeService.cs b/BeatTogether.DedicatedServer.Node/NodeService.cs index 14f2b04d..6851e957 100644 --- a/BeatTogether.DedicatedServer.Node/NodeService.cs +++ b/BeatTogether.DedicatedServer.Node/NodeService.cs @@ -7,7 +7,6 @@ using BeatTogether.DedicatedServer.Interface.Requests; using BeatTogether.DedicatedServer.Interface.Responses; using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Encryption; using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Node.Abstractions; using BeatTogether.DedicatedServer.Node.Configuration; @@ -19,19 +18,16 @@ public sealed class NodeService : IMatchmakingService { private readonly NodeConfiguration _configuration; private readonly IInstanceFactory _instanceFactory; - private readonly PacketEncryptionLayer _packetEncryptionLayer; private readonly IAutobus _autobus; private readonly ILogger _logger = Log.ForContext(); public NodeService( NodeConfiguration configuration, IInstanceFactory instanceFactory, - PacketEncryptionLayer packetEncryptionLayer, IAutobus autobus) { _configuration = configuration; _instanceFactory = instanceFactory; - _packetEncryptionLayer = packetEncryptionLayer; _autobus = autobus; } @@ -76,9 +72,7 @@ public async Task CreateMatchmakingServer(Creat await matchmakingServer.Start(); return new CreateMatchmakingServerResponse( CreateMatchmakingServerError.None, - $"{_configuration.HostName}:{matchmakingServer.Port}", - _packetEncryptionLayer.Random, - _packetEncryptionLayer.KeyPair.PublicKey + $"{_configuration.HostName}:{matchmakingServer.Port}" ); } @@ -124,12 +118,10 @@ private void HandleUpdatePlayerEvent(IPlayer player) } private void HandlePlayerDisconnectEvent(IPlayer player) { - _packetEncryptionLayer.RemoveEncryptedEndPoint((IPEndPoint)player.Endpoint); _autobus.Publish(new PlayerLeaveServerEvent(player.Instance._configuration.Secret, player.UserId, ((IPEndPoint)player.Endpoint).ToString())); } private void HandlePlayerLeaveBeforeJoining(string Secret, EndPoint endPoint, string[] Players) { - _packetEncryptionLayer.RemoveEncryptedEndPoint((IPEndPoint)endPoint); _autobus.Publish(new UpdatePlayersEvent(Secret, Players)); } #endregion From 6e2d6c785386044c3e4580ed765514c87b765258 Mon Sep 17 00:00:00 2001 From: cubic Date: Fri, 5 Apr 2024 21:37:55 +0100 Subject: [PATCH 086/120] Bump dedi interface version --- ...tTogether.DedicatedServer.Interface.csproj | 2 +- .../PortAllocator.cs | 37 ++++++++++++------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj b/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj index 2b41c9b3..ec558582 100644 --- a/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj +++ b/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj @@ -7,7 +7,7 @@ BeatTogether Team BeatTogether https://github.com/beattogether/BeatTogether.DedicatedServer - 1.7.1 + 1.7.2 enable diff --git a/BeatTogether.DedicatedServer.Node/PortAllocator.cs b/BeatTogether.DedicatedServer.Node/PortAllocator.cs index f3abc82d..67bb84b6 100644 --- a/BeatTogether.DedicatedServer.Node/PortAllocator.cs +++ b/BeatTogether.DedicatedServer.Node/PortAllocator.cs @@ -9,6 +9,8 @@ public sealed class PortAllocator : IPortAllocator { private readonly NodeConfiguration _configuration; + private readonly object _lock = new object(); + private readonly HashSet _acquiredPorts = new(); private readonly HashSet _releasedPorts = new(); @@ -24,27 +26,34 @@ public PortAllocator( public int? AcquirePort() { - if (_acquiredPorts.Count >= _configuration.MaximumSlots) - return null; - int port; - if (_releasedPorts.Any()) + lock (_lock) { - port = _releasedPorts.First(); - _releasedPorts.Remove(port); + if (_acquiredPorts.Count >= _configuration.MaximumSlots) + return null; + int port; + if (_releasedPorts.Any()) + { + port = _releasedPorts.First(); + _releasedPorts.Remove(port); + } + else + port = ++_lastPort; + _acquiredPorts.Add(port); + return port; } - else - port = ++_lastPort; - _acquiredPorts.Add(port); - return port; + } public bool ReleasePort(int port) { + lock (_lock) + { + if (!_acquiredPorts.Remove(port)) + return false; + _releasedPorts.Add(port); + return true; + } - if (!_acquiredPorts.Remove(port)) - return false; - _releasedPorts.Add(port); - return true; } } } From 450fc986e901a0668b5a57cc6233b1d9dd18e0ec Mon Sep 17 00:00:00 2001 From: cubic Date: Fri, 5 Apr 2024 22:21:57 +0100 Subject: [PATCH 087/120] Cleanup code and bump interface version --- ...tTogether.DedicatedServer.Interface.csproj | 2 +- .../Enums/GameplayState.cs | 6 ++--- .../Events/NodeOnlineEvent.cs | 2 +- .../NodeReceivedPlayerEncryptionEvent.cs | 2 +- .../Events/NodeStartedEvent.cs | 2 +- .../Events/PlayerLeaveServerEvent.cs | 2 +- .../CreateMatchmakingServerRequest.cs | 2 +- .../SetWelcomeMessageHandler.cs | 4 +-- .../GamePlatformToMpCorePlatform.cs | 24 ++++++----------- .../Managers/Abstractions/IGameplayManager.cs | 1 - .../Managers/GameplayManager.cs | 27 +++++++++---------- .../GameplayRpc/LevelFinishedPacketHandler.cs | 4 +-- .../MPChat/MpcCapabilitiesPacketHandler.cs | 2 +- .../MPChat/MpcTextChatPacketHandler.cs | 2 +- .../DediPacketSetNewManagerHandler.cs | 2 +- .../MultiplayerCore/GetPerPlayerHandler.cs | 2 +- .../MultiplayerCore/PerPlayerHandler.cs | 2 +- .../TextCommandRepository.cs | 3 +-- .../NodeService.cs | 2 +- .../PortAllocator.cs | 2 +- 20 files changed, 40 insertions(+), 55 deletions(-) diff --git a/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj b/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj index ec558582..d4e8eb39 100644 --- a/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj +++ b/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj @@ -7,7 +7,7 @@ BeatTogether Team BeatTogether https://github.com/beattogether/BeatTogether.DedicatedServer - 1.7.2 + 1.7.3 enable diff --git a/BeatTogether.DedicatedServer.Interface/Enums/GameplayState.cs b/BeatTogether.DedicatedServer.Interface/Enums/GameplayState.cs index 9b22858e..275d7ff3 100644 --- a/BeatTogether.DedicatedServer.Interface/Enums/GameplayState.cs +++ b/BeatTogether.DedicatedServer.Interface/Enums/GameplayState.cs @@ -4,8 +4,8 @@ public enum GameplayState : byte { None = 0, SceneLoad = 1, - SongLoad = 1, - Gameplay = 2, - Results = 3 + SongLoad = 2, + Gameplay = 3, + Results = 4 } } diff --git a/BeatTogether.DedicatedServer.Interface/Events/NodeOnlineEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/NodeOnlineEvent.cs index 284550dc..d65d06a1 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/NodeOnlineEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/NodeOnlineEvent.cs @@ -2,5 +2,5 @@ namespace BeatTogether.DedicatedServer.Interface.Events { - public sealed record NodeOnlineEvent(string endPoint, string NodeVersion); + public sealed record NodeOnlineEvent(string EndPoint, string NodeVersion); } \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Interface/Events/NodeReceivedPlayerEncryptionEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/NodeReceivedPlayerEncryptionEvent.cs index afdffbf7..09f2b5e8 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/NodeReceivedPlayerEncryptionEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/NodeReceivedPlayerEncryptionEvent.cs @@ -1,4 +1,4 @@ namespace BeatTogether.DedicatedServer.Interface.Events { - public sealed record NodeReceivedPlayerEncryptionEvent(string endPoint, string PlayerEndPoint); + public sealed record NodeReceivedPlayerEncryptionEvent(string EndPoint, string PlayerEndPoint); } \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Interface/Events/NodeStartedEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/NodeStartedEvent.cs index 5ddee634..58a41439 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/NodeStartedEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/NodeStartedEvent.cs @@ -2,5 +2,5 @@ namespace BeatTogether.DedicatedServer.Interface.Events { - public sealed record NodeStartedEvent(string endPoint, string NodeVersion); + public sealed record NodeStartedEvent(string EndPoint, string NodeVersion); } \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Interface/Events/PlayerLeaveServerEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/PlayerLeaveServerEvent.cs index d60b78a2..b6d98e21 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/PlayerLeaveServerEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/PlayerLeaveServerEvent.cs @@ -2,5 +2,5 @@ namespace BeatTogether.DedicatedServer.Interface.Events { - public sealed record PlayerLeaveServerEvent(string Secret, string UserId, string endPoint); + public sealed record PlayerLeaveServerEvent(string Secret, string UserId, string EndPoint); } diff --git a/BeatTogether.DedicatedServer.Interface/Requests/CreateMatchmakingServerRequest.cs b/BeatTogether.DedicatedServer.Interface/Requests/CreateMatchmakingServerRequest.cs index ab7fd119..95cd444e 100644 --- a/BeatTogether.DedicatedServer.Interface/Requests/CreateMatchmakingServerRequest.cs +++ b/BeatTogether.DedicatedServer.Interface/Requests/CreateMatchmakingServerRequest.cs @@ -9,7 +9,7 @@ public record CreateMatchmakingServerRequest( bool PermanentManager = true, float Timeout = 10f, string ServerName = "", - float resultScreenTime = 20.0f, + float ResultScreenTime = 20.0f, float BeatmapStartTime = 5.0f, float PlayersReadyCountdownTime = 0f, bool AllowPerPlayerModifiers = false, diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetWelcomeMessageHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetWelcomeMessageHandler.cs index a5a591af..b690df65 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetWelcomeMessageHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetWelcomeMessageHandler.cs @@ -10,13 +10,11 @@ class SetWelcomeMessageHandler : BaseCommandHandler { private readonly IPacketDispatcher _packetDisapatcher; private readonly InstanceConfiguration _Configuration; - private readonly IDedicatedInstance _instance; - public SetWelcomeMessageHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration, IDedicatedInstance instance) + public SetWelcomeMessageHandler(IPacketDispatcher packetDisapatcher, InstanceConfiguration instanceConfiguration) { _packetDisapatcher = packetDisapatcher; _Configuration = instanceConfiguration; - _instance = instance; } public override void Handle(IPlayer player, SetWelcomeMessage command) diff --git a/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs b/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs index 7836f1da..b1022423 100644 --- a/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs +++ b/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs @@ -6,23 +6,15 @@ public static class GamePlatformToMpCorePlatform { public static Platform Convert(this Enums.Platform gamePlatform) { - switch (gamePlatform) + return gamePlatform switch { - case Enums.Platform.Test: - return Platform.Unknown; - case Enums.Platform.OculusRift: - return Platform.OculusPC; - case Enums.Platform.OculusQuest: - return Platform.OculusQuest; - case Enums.Platform.Steam: - return Platform.Steam; - case Enums.Platform.PS4: - case Enums.Platform.PS4Dev: - case Enums.Platform.PS4Cert: - return Platform.PS4; - default: - return 0; - } + Enums.Platform.Test => Platform.Unknown, + Enums.Platform.OculusRift => Platform.OculusPC, + Enums.Platform.OculusQuest => Platform.OculusQuest, + Enums.Platform.Steam => Platform.Steam, + Enums.Platform.PS4 or Enums.Platform.PS4Dev or Enums.Platform.PS4Cert => Platform.PS4, + _ => 0, + }; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/IGameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/IGameplayManager.cs index 9b0bb734..5987a8e3 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/IGameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/IGameplayManager.cs @@ -12,7 +12,6 @@ public interface IGameplayManager GameplayManagerState State { get; } BeatmapIdentifier? CurrentBeatmap { get; } GameplayModifiers CurrentModifiers { get; } - public long _songStartTime { get; } void HandlePlayerLeaveGameplay(IPlayer player); void HandleGameSceneLoaded(IPlayer player, SetGameplaySceneReadyPacket packet); diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs index 020ad1b6..eee1d0b5 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs @@ -34,8 +34,9 @@ public sealed class GameplayManager : IGameplayManager, IDisposable private const float SceneLoadTimeLimit = 15.0f; private const float SongLoadTimeLimit = 15.0f; - public long _songStartTime { get; private set; } - List PlayersAtStart = new(); + private long SongStartTime { get; set; } + + private readonly List PlayersAtStart = new(); private CancellationTokenSource? _requestReturnToMenuCts; @@ -166,14 +167,14 @@ public async void StartSong(CancellationToken cancellationToken) } // Start song and wait for finish - _songStartTime = (_instance.RunTime + SongStartDelay + (StartDelay * 2)); - _logger.Verbose($"SongStartTime: {_songStartTime} RunTime: {_instance.RunTime}"); + SongStartTime = (_instance.RunTime + SongStartDelay + (StartDelay * 2)); + _logger.Verbose($"SongStartTime: {SongStartTime} RunTime: {_instance.RunTime}"); State = GameplayManagerState.Gameplay; _packetDispatcher.SendToNearbyPlayers(new SetSongStartTimePacket { - StartTime = _songStartTime + StartTime = SongStartTime }, IgnoranceChannelTypes.Reliable); //Initiates the song start process for forced late joiners @@ -185,7 +186,7 @@ public async void StartSong(CancellationToken cancellationToken) { Beatmap = CurrentBeatmap, Modifiers = CurrentModifiers, - StartTime = _songStartTime + StartTime = SongStartTime }, IgnoranceChannelTypes.Reliable); } } @@ -210,7 +211,7 @@ private void ResetValues() _levelFinishedTcs.Clear(); _sceneReadyTcs.Clear(); _songReadyTcs.Clear(); - _songStartTime = 0; + SongStartTime = 0; _playerSpecificSettings.Clear(); _levelCompletionResults.Clear(); PlayersAtStart.Clear(); @@ -262,10 +263,10 @@ public void HandleGameSongLoaded(IPlayer player) return; } if (State != GameplayManagerState.SceneLoad) //Late joiners get sent start time - if(_songStartTime != 0) + if(SongStartTime != 0) _packetDispatcher.SendToPlayer(player, new SetSongStartTimePacket { - StartTime = _songStartTime + StartTime = SongStartTime }, IgnoranceChannelTypes.Reliable); } @@ -277,14 +278,10 @@ public void HandleLevelFinished(IPlayer player, LevelFinishedPacket packet) PlayerFinishLevel(player.UserId); } - object RequestReturnLock = new(); public void SignalRequestReturnToMenu() { - lock (RequestReturnLock) - { - if (_requestReturnToMenuCts != null && !_requestReturnToMenuCts.IsCancellationRequested) - _requestReturnToMenuCts.Cancel(); - } + if (_requestReturnToMenuCts != null && !_requestReturnToMenuCts.IsCancellationRequested) + _requestReturnToMenuCts.Cancel(); } //will set players tasks as done if they leave gameplay due to disconnect or returning to the menu diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/LevelFinishedPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/LevelFinishedPacketHandler.cs index 7a8e294a..3fb5b5b5 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/LevelFinishedPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/LevelFinishedPacketHandler.cs @@ -7,8 +7,8 @@ namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession. { public sealed class LevelFinishedPacketHandler : BasePacketHandler { - private IGameplayManager _gameplayManager; - private ILogger _logger = Log.ForContext(); + private readonly IGameplayManager _gameplayManager; + private readonly ILogger _logger = Log.ForContext(); public LevelFinishedPacketHandler( IGameplayManager gameplayManager) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs index f7614884..c18d46ad 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcCapabilitiesPacketHandler.cs @@ -10,7 +10,7 @@ public class MpcCapabilitiesPacketHandler : BasePacketHandler(); + //private readonly ILogger _logger = Log.ForContext(); public MpcCapabilitiesPacketHandler(IPacketDispatcher packetDispatcher, InstanceConfiguration instanceConfiguration) { diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs index 094636a1..e4a19708 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MPChat/MpcTextChatPacketHandler.cs @@ -14,7 +14,7 @@ public class MpcTextChatPacketHandler : BasePacketHandler private readonly InstanceConfiguration _instanceConfiguration; private readonly ITextCommandRepository _CommandRepository; private readonly IServiceProvider _serviceProvider; - private readonly ILogger _logger = Log.ForContext(); + //private readonly ILogger _logger = Log.ForContext(); public MpcTextChatPacketHandler(IPacketDispatcher packetDispatcher, diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs index 6effb847..721568a2 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs @@ -11,7 +11,7 @@ namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession. { class DediPacketSetNewManagerPacketHandler : BasePacketHandler { - private InstanceConfiguration _configuration; + private readonly InstanceConfiguration _configuration; private readonly IPacketDispatcher _packetDispatcher; private readonly IPlayerRegistry _playerRegistry; private readonly ILogger _logger = Log.ForContext(); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetPerPlayerHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetPerPlayerHandler.cs index e99a4d4b..225272f4 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetPerPlayerHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetPerPlayerHandler.cs @@ -8,7 +8,7 @@ namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession. { class GetPerPlayerHandler : BasePacketHandler { - private InstanceConfiguration _configuration; + private readonly InstanceConfiguration _configuration; private readonly IPacketDispatcher _PacketDispatcher; private readonly ILogger _logger = Log.ForContext(); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/PerPlayerHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/PerPlayerHandler.cs index 516ced50..533d36ff 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/PerPlayerHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/PerPlayerHandler.cs @@ -8,7 +8,7 @@ namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession. { class PerPlayerHandler : BasePacketHandler { - private InstanceConfiguration _configuration; + private readonly InstanceConfiguration _configuration; private readonly IPacketDispatcher _PacketDispatcher; private readonly ILogger _logger = Log.ForContext(); diff --git a/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs b/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs index 71092fd3..bce72e1a 100644 --- a/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs +++ b/BeatTogether.DedicatedServer.Kernel/TextCommandRepository.cs @@ -1,7 +1,6 @@ using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Commands; using BeatTogether.DedicatedServer.Kernel.Enums; -using BeatTogether.DedicatedServer.Kernel.Managers; using Serilog; using System; using System.Collections.Concurrent; @@ -15,7 +14,7 @@ public class TextCommandRepository : ITextCommandRepository private readonly ConcurrentDictionary> _Commands = new(); private readonly ConcurrentDictionary> _SHCommands = new(); - private readonly ILogger _logger = Log.ForContext(); + //private readonly ILogger _logger = Log.ForContext(); public TextCommandRepository() { RegisterCommands(); diff --git a/BeatTogether.DedicatedServer.Node/NodeService.cs b/BeatTogether.DedicatedServer.Node/NodeService.cs index 6851e957..7c3cefe7 100644 --- a/BeatTogether.DedicatedServer.Node/NodeService.cs +++ b/BeatTogether.DedicatedServer.Node/NodeService.cs @@ -50,7 +50,7 @@ public async Task CreateMatchmakingServer(Creat request.PermanentManager, request.Timeout, request.ServerName, - (long)request.resultScreenTime, + (long)request.ResultScreenTime, ((long)request.BeatmapStartTime) * 1000, ((long)request.PlayersReadyCountdownTime) * 1000, request.AllowPerPlayerModifiers, diff --git a/BeatTogether.DedicatedServer.Node/PortAllocator.cs b/BeatTogether.DedicatedServer.Node/PortAllocator.cs index 67bb84b6..169577a7 100644 --- a/BeatTogether.DedicatedServer.Node/PortAllocator.cs +++ b/BeatTogether.DedicatedServer.Node/PortAllocator.cs @@ -9,7 +9,7 @@ public sealed class PortAllocator : IPortAllocator { private readonly NodeConfiguration _configuration; - private readonly object _lock = new object(); + private readonly object _lock = new(); private readonly HashSet _acquiredPorts = new(); private readonly HashSet _releasedPorts = new(); From bee141e8edb38e20411426549b4c07b63f7d3f85 Mon Sep 17 00:00:00 2001 From: cubic <79692655+cubicgraphics@users.noreply.github.com> Date: Fri, 5 Apr 2024 22:23:43 +0100 Subject: [PATCH 088/120] Update nuget.yml --- .github/workflows/nuget.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index 9e0393ac..7e6cec86 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -4,11 +4,7 @@ on: branches: - master - dev - - dev-1.29 - - dev-1.29-Net6.0 - - dev-1.29-Net6.0-Faster - - dev-1.31.0 - - dev-1.31.0-Merge-faster-changes + - dev-1.35 jobs: nuget-1: From 677be190e3a75fcdd16cc9cac0ec6486faae9712 Mon Sep 17 00:00:00 2001 From: cubic <79692655+cubicgraphics@users.noreply.github.com> Date: Fri, 5 Apr 2024 22:24:30 +0100 Subject: [PATCH 089/120] Update nuget.yml --- .github/workflows/nuget.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index 7e6cec86..08e0e638 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -4,7 +4,7 @@ on: branches: - master - dev - - dev-1.35 + - dev-1.35.0 jobs: nuget-1: From 2f1f3ae1ee091b32b7c353b7076c347a82855b5a Mon Sep 17 00:00:00 2001 From: cubic Date: Fri, 5 Apr 2024 23:11:58 +0100 Subject: [PATCH 090/120] Bumped required master server interface ver --- .../BeatTogether.DedicatedServer.Node.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj b/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj index baac3102..7da5c8c4 100644 --- a/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj +++ b/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj @@ -13,7 +13,7 @@ - + From 2b6ce65b6e37648515d1ea212b3b8ac63bbe1cbc Mon Sep 17 00:00:00 2001 From: cubic Date: Fri, 5 Apr 2024 23:19:40 +0100 Subject: [PATCH 091/120] Comment out packet flag i added --- BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs index 3280ff48..91eecfd5 100644 --- a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs @@ -272,7 +272,7 @@ public void Send(ENetConnection connection, ReadOnlySpan message, Ignoranc return; var eNetPacket = default(Packet); - eNetPacket.Create(message.ToArray(), message.Length, (PacketFlags)deliveryMethod); + eNetPacket.Create(message.ToArray(), message.Length/*, (PacketFlags)deliveryMethod*/); _ignorance.Outgoing.Enqueue(new IgnoranceOutgoingPacket() { From 17c37609ed44cc12925c920123700e8c0bf561c0 Mon Sep 17 00:00:00 2001 From: cubic Date: Sat, 6 Apr 2024 00:54:19 +0100 Subject: [PATCH 092/120] Removed IsEnetConnectionBool --- BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs | 1 - BeatTogether.DedicatedServer.Kernel/Player.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index dcc4c0d7..dd6299c3 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -23,7 +23,6 @@ public interface IPlayer string PlatformUserId { get; set; } uint? ENetPeerId { get; set; } - bool IsENetConnection { get;} RollingAverage Latency { get; } long SyncTime { get; } diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index 0482dd86..b5e89b46 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -20,7 +20,7 @@ public sealed class Player : IPlayer public string PlayerSessionId { get; } public uint? ENetPeerId { get; set; } - public bool IsENetConnection => true; //ENetPeerId.HasValue; + public RollingAverage Latency { get; } = new(30); public long SyncTime => Math.Min(Instance.RunTime - Latency.CurrentAverage - _syncTimeOffset, From ca4ac436aa668051e97a36b40c2f275ee9730bab Mon Sep 17 00:00:00 2001 From: cubic Date: Sat, 6 Apr 2024 15:07:17 +0100 Subject: [PATCH 093/120] Fix dependency loop, Fix dedi-master message serialisation --- .../Responses/CreateMatchmakingServerResponse.cs | 6 +++--- .../BeatTogether.DedicatedServer.Kernel.csproj | 1 - .../DedicatedInstance.cs | 13 +++++-------- .../ENet/ENetServer.cs | 2 +- .../Extensions/HostBuilderExtensions.cs | 2 +- .../BeatTogether.DedicatedServer.Messaging.csproj | 4 ++++ .../InstanceFactory.cs | 1 - BeatTogether.DedicatedServer.Node/NodeService.cs | 4 +++- 8 files changed, 17 insertions(+), 16 deletions(-) diff --git a/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs b/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs index 3a122e1f..84c7e0cc 100644 --- a/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs +++ b/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs @@ -9,9 +9,9 @@ public enum CreateMatchmakingServerError public record CreateMatchmakingServerResponse( CreateMatchmakingServerError Error, - string? RemoteEndPoint = null, - byte[]? Random = null, - byte[]? PublicKey = null) + string RemoteEndPoint, + byte[] Random, + byte[] PublicKey) { public bool Success => Error == default; } diff --git a/BeatTogether.DedicatedServer.Kernel/BeatTogether.DedicatedServer.Kernel.csproj b/BeatTogether.DedicatedServer.Kernel/BeatTogether.DedicatedServer.Kernel.csproj index b5a15957..a7f9ea63 100644 --- a/BeatTogether.DedicatedServer.Kernel/BeatTogether.DedicatedServer.Kernel.csproj +++ b/BeatTogether.DedicatedServer.Kernel/BeatTogether.DedicatedServer.Kernel.csproj @@ -21,7 +21,6 @@ - diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 7d30761a..529d9400 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -19,6 +19,7 @@ using BeatTogether.DedicatedServer.Messaging.Util; using Serilog; using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using Microsoft.Extensions.DependencyInjection; namespace BeatTogether.DedicatedServer.Kernel { @@ -46,8 +47,8 @@ public sealed class DedicatedInstance : ENetServer, IDedicatedInstance private readonly IPlayerRegistry _playerRegistry; private readonly IServiceProvider _serviceProvider; - private readonly IPacketDispatcher PacketDispatcher; - private readonly PacketSource ConnectedMessageSource; + private IPacketDispatcher PacketDispatcher; + private PacketSource ConnectedMessageSource; private byte _connectionIdCount = 0; @@ -64,16 +65,12 @@ public sealed class DedicatedInstance : ENetServer, IDedicatedInstance public DedicatedInstance( InstanceConfiguration configuration, IPlayerRegistry playerRegistry, - IPacketDispatcher packetDispatcher, - PacketSource connectedMessageSource, IServiceProvider serviceProvider) : base (configuration.Port) { _configuration = configuration; _playerRegistry = playerRegistry; _serviceProvider = serviceProvider; - PacketDispatcher = packetDispatcher; - ConnectedMessageSource = connectedMessageSource; } #region Public Methods @@ -93,8 +90,8 @@ public async Task Start(CancellationToken cancellationToken = default) if (IsRunning) return; - //PacketDispatcher = _serviceProvider.GetRequiredService(); - //ConnectedMessageSource = _serviceProvider.GetRequiredService(); + PacketDispatcher = _serviceProvider.GetRequiredService(); + ConnectedMessageSource = _serviceProvider.GetRequiredService(); _startTime = DateTime.UtcNow.Ticks; diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs index 91eecfd5..4d7762f9 100644 --- a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs @@ -16,7 +16,7 @@ namespace BeatTogether.DedicatedServer.Kernel.ENet { /// - /// Temporary secondary server/socket for ENet (1.31+) connectivity. + /// Server/socket for ENet (1.31+) connectivity. /// public class ENetServer : IDisposable { diff --git a/BeatTogether.DedicatedServer.Kernel/Extensions/HostBuilderExtensions.cs b/BeatTogether.DedicatedServer.Kernel/Extensions/HostBuilderExtensions.cs index bd28ed0c..b81bee35 100644 --- a/BeatTogether.DedicatedServer.Kernel/Extensions/HostBuilderExtensions.cs +++ b/BeatTogether.DedicatedServer.Kernel/Extensions/HostBuilderExtensions.cs @@ -35,7 +35,7 @@ public static IHostBuilder UseDedicatedInstances(this IHostBuilder hostBuilder) .AddDedicatedServerMessaging() .AddScoped() .AddExisting() - .AddExisting() + .AddExisting() //Used to be like this for lnl //.AddScoped() .AddScoped() //.AddScoped() diff --git a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj index 05ac0b57..29409fe6 100644 --- a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj +++ b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj @@ -12,4 +12,8 @@
+ + + + diff --git a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs index 97dea86a..53d86abc 100644 --- a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs +++ b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs @@ -49,7 +49,6 @@ bool AllowNE var scope = _serviceProvider.CreateScope(); var instanceConfig = scope.ServiceProvider.GetRequiredService(); - //instanceConfig.LiteNetPort = (int)liteNetPort!; instanceConfig.Port = (int)Port!; instanceConfig.Secret = secret; instanceConfig.ServerOwnerId = managerId; diff --git a/BeatTogether.DedicatedServer.Node/NodeService.cs b/BeatTogether.DedicatedServer.Node/NodeService.cs index 7c3cefe7..4f9c3b27 100644 --- a/BeatTogether.DedicatedServer.Node/NodeService.cs +++ b/BeatTogether.DedicatedServer.Node/NodeService.cs @@ -72,7 +72,9 @@ public async Task CreateMatchmakingServer(Creat await matchmakingServer.Start(); return new CreateMatchmakingServerResponse( CreateMatchmakingServerError.None, - $"{_configuration.HostName}:{matchmakingServer.Port}" + $"{_configuration.HostName}:{matchmakingServer.Port}", + Array.Empty(), + Array.Empty() ); } From 7c740a622c0f2ef486c7a42c3dc88e050608153f Mon Sep 17 00:00:00 2001 From: cubic Date: Sat, 6 Apr 2024 17:38:29 +0100 Subject: [PATCH 094/120] Remove some logs and fix some possible entitlement issues --- .../Managers/LobbyManager.cs | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 281fd3cd..1b0007c2 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -10,6 +10,7 @@ using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; +using BeatTogether.DedicatedServer.Messaging.Packets; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using Serilog; @@ -109,7 +110,7 @@ public void ForceStartBeatmapUpdate() } if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin)) { - foreach (IPlayer p in _playerRegistry.Players) +/* foreach (IPlayer p in _playerRegistry.Players) { if (p.GetEntitlement(SelectedBeatmap.LevelId) is not EntitlementStatus.Ok || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin) { @@ -119,7 +120,7 @@ public void ForceStartBeatmapUpdate() Entitlement = EntitlementStatus.Ok }, IgnoranceChannelTypes.Reliable); } - } + }*/ //The clients need to be sent that all the payers have OK entitlement //starts beatmap _gameplayManager.SetBeatmap(SelectedBeatmap!, SelectedModifiers); @@ -145,10 +146,10 @@ public void ForceStartBeatmapUpdate() { if (p.GetEntitlement(SelectedBeatmap.LevelId) is not EntitlementStatus.Ok) { - _packetDispatcher.SendFromPlayer(p, new SetIsEntitledToLevelPacket() + //TODO This needs changing? we just kick the player for now, but really we want to send them to spectator + _packetDispatcher.SendToPlayer(p, new KickPlayerPacket { - LevelId = SelectedBeatmap.LevelId, - Entitlement = EntitlementStatus.Ok + DisconnectedReason = DisconnectedReason.Kicked }, IgnoranceChannelTypes.Reliable); p.ForceLateJoin = true; } @@ -193,7 +194,7 @@ public void Update() .Where(p => (p.GetEntitlement(player.BeatmapIdentifier.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) && !p.IsSpectating && p.WantsToPlayNextLevel) .Select(p => p.UserId).ToArray() }, IgnoranceChannelTypes.Reliable); - _logger.Debug("Sent missing entitlement packet"); + //_logger.Debug("Sent missing entitlement packet"); } } } @@ -243,7 +244,7 @@ public void Update() private void CountingDown(bool isReady, bool NotStartable) { - _logger.Debug($"CountdownEndTime '{CountdownEndTime}' RunTime '{_instance.RunTime}' BeatMapStartCountdownTime '{_configuration.CountdownConfig.BeatMapStartCountdownTime}' CountdownTimePlayersReady '{_configuration.CountdownConfig.CountdownTimePlayersReady}'"); + //_logger.Debug($"CountdownEndTime '{CountdownEndTime}' RunTime '{_instance.RunTime}' BeatMapStartCountdownTime '{_configuration.CountdownConfig.BeatMapStartCountdownTime}' CountdownTimePlayersReady '{_configuration.CountdownConfig.CountdownTimePlayersReady}'"); // If not already counting down if (CountDownState == CountdownState.NotCountingDown) { @@ -257,7 +258,7 @@ private void CountingDown(bool isReady, bool NotStartable) // If counting down if (CountDownState != CountdownState.NotCountingDown) { - _logger.Debug($"CountdownEndTime '{CountdownEndTime}' RunTime '{_instance.RunTime}'"); + //_logger.Debug($"CountdownEndTime '{CountdownEndTime}' RunTime '{_instance.RunTime}'"); if(CountdownEndTime <= _instance.RunTime) { _logger.Debug($"Countdown finished, sending map"); @@ -268,17 +269,19 @@ private void CountingDown(bool isReady, bool NotStartable) } if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin)) { - foreach(IPlayer p in _playerRegistry.Players) + //Dont do this as we dont want clients to store incorrect info on players entitlements +/* foreach(IPlayer p in _playerRegistry.Players) { if (p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin) { + //Force send to everyone that those players have the map. _packetDispatcher.SendFromPlayer(p, new SetIsEntitledToLevelPacket() { LevelId = SelectedBeatmap!.LevelId, Entitlement = EntitlementStatus.Ok }, IgnoranceChannelTypes.Reliable); } - } + }*/ _logger.Debug($"All players have entitlement, starting map"); //starts beatmap _gameplayManager.SetBeatmap(SelectedBeatmap!, SelectedModifiers); @@ -355,8 +358,8 @@ public BeatmapDifficulty[] GetSelectedBeatmapDifficulties() // If you want to cancel the countdown use CancelCountdown(), Not SetCountdown as CancelCountdown() ALSO informs the clients it has been canceled, whereas SetCountdown will not private void SetCountdown(CountdownState countdownState, long countdown = 0) { - _logger.Error($"CountdownEndTime currently is '{CountdownEndTime}' countdown is set to '{countdown}' state will be set to '{countdownState}' BeatmapStartTime is '{_configuration.CountdownConfig.BeatMapStartCountdownTime}'"); - _logger.Error($"Check should start Beatmap {(CountdownEndTime - _instance.RunTime) < _configuration.CountdownConfig.BeatMapStartCountdownTime} EndTime '{CountdownEndTime - _instance.RunTime}' RunTime '{_instance.RunTime}'"); + //_logger.Error($"CountdownEndTime currently is '{CountdownEndTime}' countdown is set to '{countdown}' state will be set to '{countdownState}' BeatmapStartTime is '{_configuration.CountdownConfig.BeatMapStartCountdownTime}'"); + //_logger.Error($"Check should start Beatmap {(CountdownEndTime - _instance.RunTime) < _configuration.CountdownConfig.BeatMapStartCountdownTime} EndTime '{CountdownEndTime - _instance.RunTime}' RunTime '{_instance.RunTime}'"); CountDownState = countdownState; switch (CountDownState) { @@ -384,7 +387,7 @@ private void SetCountdown(CountdownState countdownState, long countdown = 0) StartBeatmapPacket(); break; } - _logger.Error($"CountdownEndTime final set to '{CountdownEndTime}' CountdownState '{CountDownState}' countdown is '{countdown}' RunTime is '{_instance.RunTime}' BeatmapStartTime is '{_configuration.CountdownConfig.BeatMapStartCountdownTime}'"); + //_logger.Error($"CountdownEndTime final set to '{CountdownEndTime}' CountdownState '{CountDownState}' countdown is '{countdown}' RunTime is '{_instance.RunTime}' BeatmapStartTime is '{_configuration.CountdownConfig.BeatMapStartCountdownTime}'"); } //Checks the lobby settings and sends the player the correct beatmap From 30453c5b60a01b63b0e4609c184705a9a1d4bd03 Mon Sep 17 00:00:00 2001 From: cubic Date: Sat, 6 Apr 2024 18:09:41 +0100 Subject: [PATCH 095/120] Change lobby logic to allow backgrounded players to pass into gameplay as how spectators would --- BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs | 2 +- BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs index eee1d0b5..e0a6081c 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs @@ -102,7 +102,7 @@ public async void StartSong(CancellationToken cancellationToken) State = GameplayManagerState.SceneLoad; foreach (var player in _playerRegistry.Players)//Array of players that are playing at the start { - if (!player.IsSpectating && !player.ForceLateJoin) + if (!player.IsSpectating && !player.ForceLateJoin && !player.IsBackgrounded) PlayersAtStart.Add(player.UserId); } diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 1b0007c2..9f81a019 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -108,7 +108,7 @@ public void ForceStartBeatmapUpdate() { SetCountdown(CountdownState.WaitingForEntitlement); } - if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin)) + if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsBackgrounded || !p.WantsToPlayNextLevel || p.ForceLateJoin)) { /* foreach (IPlayer p in _playerRegistry.Players) { From cd94865cc65925d70bc72e2751178b7c863361f1 Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 8 Apr 2024 01:39:09 +0100 Subject: [PATCH 096/120] Added dedicated server states, cleaned up dedicated instance code and a few comments --- .../DedicatedInstance.cs | 313 +++++++++--------- .../Managers/GameplayManager.cs | 1 - .../Managers/LobbyManager.cs | 2 +- .../PlayerRegistry.cs | 16 +- .../Models/BitMask128.cs | 12 +- 5 files changed, 178 insertions(+), 166 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 529d9400..11adc210 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -50,6 +50,7 @@ public sealed class DedicatedInstance : ENetServer, IDedicatedInstance private IPacketDispatcher PacketDispatcher; private PacketSource ConnectedMessageSource; + private readonly PlayerStateHash ServerStateHash = new(); private byte _connectionIdCount = 0; private int _lastSortIndex = -1; @@ -75,6 +76,10 @@ public DedicatedInstance( #region Public Methods + public void InstanceConfigUpdated() + { + UpdateInstanceEvent?.Invoke(this); + } public IPlayerRegistry GetPlayerRegistry() { @@ -131,7 +136,7 @@ public async Task Start(CancellationToken cancellationToken = default) } }, cancellationToken); } - + ServerStateHash.WriteToBitMask("dedicated_server"); await base.Start(); _ = Task.Run(() => SendSyncTime(_stopServerCts.Token), cancellationToken); @@ -155,10 +160,16 @@ public async Task Stop(CancellationToken cancellationToken = default) $"SongSelectionMode={_configuration.SongSelectionMode}, " + $"GameplayServerControlSettings={_configuration.GameplayServerControlSettings})." ); - - PacketDispatcher.SendToNearbyPlayers(new KickPlayerPacket - { - DisconnectedReason = DisconnectedReason.ServerTerminated + ServerStateHash.WriteToBitMask("terminating"); + PacketDispatcher.SendToNearbyPlayers(new INetSerializable[]{ + new PlayerStatePacket + { + PlayerState = ServerStateHash + }, + new KickPlayerPacket + { + DisconnectedReason = DisconnectedReason.ServerTerminated + } }, IgnoranceChannelTypes.Reliable); KickAllPeers(); @@ -218,10 +229,6 @@ public void SetState(MultiplayerGameState state) GameIsInLobby?.Invoke(_configuration.Secret, state == MultiplayerGameState.Lobby); } - #endregion - - #region EnetCompat - public override IPlayer? TryAcceptConnection(IPEndPoint endPoint, ref SpanBuffer Data) { bool PlayerNoJoin = false; @@ -323,27 +330,6 @@ public void SetState(MultiplayerGameState state) player.PlatformUserId = PlayerPlatformUserId; } - - PacketDispatcher.SendExcludingPlayer(player, new INetSerializable[]{ - new PlayerConnectedPacket - { - RemoteConnectionId = player.ConnectionId, - UserId = player.UserId, - UserName = player.UserName, - IsConnectionOwner = false - }, - new PlayerSortOrderPacket - { - UserId = player.UserId, - SortIndex = player.SortIndex - }, - new MpNodePoseSyncStatePacket - { - fullStateUpdateFrequency = 100L, - deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() - }, - }, IgnoranceChannelTypes.Reliable); - return player; EndOfTryAccept: @@ -362,8 +348,6 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, I ConnectedMessageSource.OnReceive(remoteEndPoint, ref reader, method); } - #endregion - public override void OnConnect(EndPoint endPoint) { _logger.Information($"Endpoint connected (RemoteEndPoint='{endPoint}')"); @@ -379,12 +363,29 @@ public override void OnConnect(EndPoint endPoint) return; } PlayerConnectedEvent?.Invoke(player); - //The player has already been sent to every other player in the should connect function. - //Start of sending other players to player - //Now send all players already in the game to the new player - IPlayer[] PlayersAtJoin = _playerRegistry.Players; + //Send to other players that there is a new player + PacketDispatcher.SendExcludingPlayer(player, new INetSerializable[]{ + new PlayerConnectedPacket + { + RemoteConnectionId = player.ConnectionId, + UserId = player.UserId, + UserName = player.UserName, + IsConnectionOwner = false + }, + new PlayerSortOrderPacket + { + UserId = player.UserId, + SortIndex = player.SortIndex + }, + new MpNodePoseSyncStatePacket + { + fullStateUpdateFrequency = 100L, + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() + }, + }, IgnoranceChannelTypes.Reliable); + //Send server infomation to player var Player_ConnectPacket = new INetSerializable[] { new SyncTimePacket @@ -403,6 +404,10 @@ public override void OnConnect(EndPoint endPoint) UserName = _configuration.ServerName, IsConnectionOwner = true }, + new PlayerStatePacket + { + PlayerState = ServerStateHash + }, new SetIsStartButtonEnabledPacket// Disables start button if they are server owner without selected song { Reason = player.UserId == _configuration.ServerOwnerId ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None @@ -416,8 +421,9 @@ public override void OnConnect(EndPoint endPoint) PacketDispatcher.SendToPlayer(player, Player_ConnectPacket, IgnoranceChannelTypes.Reliable); + //Send other connected players to new player List MakeBigPacketToSendToPlayer = new(); - foreach (IPlayer p in PlayersAtJoin) + foreach (IPlayer p in _playerRegistry.Players) { if(p.ConnectionId != player.ConnectionId) { @@ -439,33 +445,34 @@ public override void OnConnect(EndPoint endPoint) { PacketDispatcher.SendToPlayer(player, SubPacket.ToArray(), IgnoranceChannelTypes.Reliable); } - //End of sending other players to player + //send player avatars and states of other players in server to new player + INetSerializable[] SendToPlayerFromPlayers = new INetSerializable[2]; + SendToPlayerFromPlayers[0] = new PlayerIdentityPacket(); + SendToPlayerFromPlayers[1] = new MpPlayerData(); - // Update permissions - constant manager possibly does not work - if ((_configuration.SetConstantManagerFromUserId == player.UserId || _playerRegistry.GetPlayerCount() == 1) && _configuration.GameplayServerMode == GameplayServerMode.Managed) + foreach (IPlayer p in _playerRegistry.Players) { - _configuration.ServerOwnerId = player.UserId; - PacketDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket //Sends updated value to all players.//TODO Make a function for updating players permissions as there will be commands for it soon + if (p.ConnectionId != player.ConnectionId) { - PermissionConfiguration = new PlayersPermissionConfiguration - { - PlayersPermission = new PlayerPermissionConfiguration[] - { - new PlayerPermissionConfiguration() - { - UserId = player.UserId, - IsServerOwner = player.IsServerOwner, - HasRecommendBeatmapsPermission = player.CanRecommendBeatmaps, - HasRecommendGameplayModifiersPermission = player.CanRecommendModifiers, - HasKickVotePermission = player.CanKickVote, - HasInvitePermission = player.CanInvite - } - } - } - }, IgnoranceChannelTypes.Reliable); + // Send player to player data to new player + ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PlayerState = p.State; + ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PlayerAvatar = p.Avatar; + ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).Random = new ByteArray { Data = p.Random }; + ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PublicEncryptionKey = new ByteArray { Data = p.PublicEncryptionKey }; + ((MpPlayerData)SendToPlayerFromPlayers[1]).PlatformID = p.PlatformUserId; + ((MpPlayerData)SendToPlayerFromPlayers[1]).Platform = p.Platform.Convert(); + ((MpPlayerData)SendToPlayerFromPlayers[1]).ClientVersion = p.ClientVersion; + + // Send all player avatars and states to just joined player + PacketDispatcher.SendFromPlayerToPlayer(p, player, SendToPlayerFromPlayers, IgnoranceChannelTypes.Reliable); + } } + // Update permissions + if ((_configuration.SetConstantManagerFromUserId == player.UserId || _playerRegistry.GetPlayerCount() == 1) && _configuration.GameplayServerMode == GameplayServerMode.Managed) + SetNewServerOwner(player); + if (player.Platform == Enums.Platform.Test) //If the player is a bot, send permissions. Normal players request this in a packet when they join { bool HasManager = (_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var ServerOwner) && !player.IsServerOwner); @@ -498,34 +505,8 @@ public override void OnConnect(EndPoint endPoint) }, IgnoranceChannelTypes.Reliable); } - //Start of sending player avatars and states of other players to new player - INetSerializable[] SendToPlayerFromPlayers = new INetSerializable[2]; - SendToPlayerFromPlayers[0] = new PlayerIdentityPacket(); - SendToPlayerFromPlayers[1] = new MpPlayerData(); - - foreach (IPlayer p in PlayersAtJoin) - { - if (p.ConnectionId != player.ConnectionId) - { - // Send player to player data to new player - - ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PlayerState = p.State; - ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PlayerAvatar = p.Avatar; - ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).Random = new ByteArray { Data = p.Random }; - ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PublicEncryptionKey = new ByteArray { Data = p.PublicEncryptionKey }; - ((MpPlayerData)SendToPlayerFromPlayers[1]).PlatformID = p.PlatformUserId; - ((MpPlayerData)SendToPlayerFromPlayers[1]).Platform = p.Platform.Convert(); - ((MpPlayerData)SendToPlayerFromPlayers[1]).ClientVersion = p.ClientVersion; - - - // Send all player avatars and states to just joined player - PacketDispatcher.SendFromPlayerToPlayer(p, player, SendToPlayerFromPlayers, IgnoranceChannelTypes.Reliable); - //Sends them one by one to avoid server lag - } - } - //End of sending avatars and states to new player - - foreach (IPlayer p in PlayersAtJoin) + //Send joining players mpcore data to everyone else + foreach (IPlayer p in _playerRegistry.Players) { if (p.ConnectionId != player.ConnectionId) { @@ -538,14 +519,11 @@ public override void OnConnect(EndPoint endPoint) } } - var packet = new MpcTextChatPacket { Text = player.UserName + " Joined, Platform: " + player.Platform.ToString() + " Version: " + player.ClientVersion }; - foreach (var p in PlayersAtJoin) - { - if (p.CanTextChat) - { - PacketDispatcher.SendToPlayer(p, packet, IgnoranceChannelTypes.Reliable); - } - } + PacketDispatcher.SendToNearbyPlayers(new MpcTextChatPacket + { + Text = player.UserName + " Joined, Platform: " + player.Platform.ToString() + " Version: " + player.ClientVersion + }, IgnoranceChannelTypes.Reliable); + } public void DisconnectPlayer(string UserId) //Used by master servers kick player event @@ -566,66 +544,37 @@ public override void OnDisconnect(EndPoint endPoint) ); - if (_playerRegistry.TryGetPlayer(endPoint, out var player)) + if (!_playerRegistry.TryGetPlayer(endPoint, out var player)) { - //Sends to all players that they have disconnected - - PacketDispatcher.SendFromPlayer(player, new PlayerDisconnectedPacket - { - DisconnectedReason = DisconnectedReason.ClientConnectionClosed - }, IgnoranceChannelTypes.Reliable); + return; + } + //Sends to all players that they have disconnected - if (_configuration.ServerOwnerId == player.UserId) - _configuration.ServerOwnerId = ""; + PacketDispatcher.SendFromPlayer(player, new PlayerDisconnectedPacket + { + DisconnectedReason = DisconnectedReason.ClientConnectionClosed + }, IgnoranceChannelTypes.Reliable); - _playerRegistry.RemovePlayer(player); - ReleaseSortIndex(player.SortIndex); - ReleaseConnectionId(player.ConnectionId); + _playerRegistry.RemovePlayer(player); + ReleaseSortIndex(player.SortIndex); + ReleaseConnectionId(player.ConnectionId); - PlayerDisconnectedEvent?.Invoke(player); - } + PlayerDisconnectedEvent?.Invoke(player); - if (_playerRegistry.GetPlayerCount() != 0 && string.IsNullOrEmpty(_configuration.ServerOwnerId) && _configuration.GameplayServerMode == GameplayServerMode.Managed) + if(_playerRegistry.GetPlayerCount() != 0) { - var serverOwner = _playerRegistry.Players[0]; - _configuration.ServerOwnerId = serverOwner.UserId; - - // Update permissions - PacketDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket + if (player.IsServerOwner && _configuration.GameplayServerMode == GameplayServerMode.Managed) { - PermissionConfiguration = new PlayersPermissionConfiguration - { - PlayersPermission = new PlayerPermissionConfiguration[] - { - new PlayerPermissionConfiguration() - { - UserId = serverOwner!.UserId, - IsServerOwner = serverOwner.IsServerOwner, - HasRecommendBeatmapsPermission = serverOwner.CanRecommendBeatmaps, - HasRecommendGameplayModifiersPermission = serverOwner.CanRecommendModifiers, - HasKickVotePermission = serverOwner.CanKickVote, - HasInvitePermission = serverOwner.CanInvite - } - } - } + // Update permissions + SetNewServerOwner(_playerRegistry.Players[0]); + } + PacketDispatcher.SendToNearbyPlayers(new MpNodePoseSyncStatePacket + { + fullStateUpdateFrequency = 100L, + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() }, IgnoranceChannelTypes.Reliable); - - // Disable start button if they are server owner without selected song - if (serverOwner.BeatmapIdentifier == null) - PacketDispatcher.SendToPlayer(serverOwner, new SetIsStartButtonEnabledPacket - { - Reason = CannotStartGameReason.NoSongSelected - }, IgnoranceChannelTypes.Reliable); } - - - PacketDispatcher.SendToNearbyPlayers(new MpNodePoseSyncStatePacket - { - fullStateUpdateFrequency = 100L, - deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() - }, IgnoranceChannelTypes.Reliable); - - if (_playerRegistry.GetPlayerCount() == 0) + else { NoPlayersTime = RunTime; if (_configuration.DestroyInstanceTimeout != -1) @@ -647,8 +596,77 @@ public override void OnDisconnect(EndPoint endPoint) } } + #endregion + #region Private Methods + private void SetNewServerOwner(IPlayer NewOwner) + { + if (_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var OldOwner)) + { + _configuration.ServerOwnerId = NewOwner.UserId; + PacketDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket + { + PermissionConfiguration = new PlayersPermissionConfiguration + { + PlayersPermission = new PlayerPermissionConfiguration[] + { + new PlayerPermissionConfiguration() + { + UserId = OldOwner.UserId, + IsServerOwner = OldOwner.IsServerOwner, + HasRecommendBeatmapsPermission = OldOwner.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = OldOwner.CanRecommendModifiers, + HasKickVotePermission = OldOwner.CanKickVote, + HasInvitePermission = OldOwner.CanInvite + }, + new PlayerPermissionConfiguration() + { + UserId = NewOwner.UserId, + IsServerOwner = NewOwner.IsServerOwner, + HasRecommendBeatmapsPermission = NewOwner.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = NewOwner.CanRecommendModifiers, + HasKickVotePermission = NewOwner.CanKickVote, + HasInvitePermission = NewOwner.CanInvite + } + } + } + }, IgnoranceChannelTypes.Reliable); + PacketDispatcher.SendToPlayer(OldOwner, new SetIsStartButtonEnabledPacket + { + Reason = CannotStartGameReason.None + }, IgnoranceChannelTypes.Reliable); + } + else + { + _configuration.ServerOwnerId = NewOwner.UserId; + PacketDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket + { + PermissionConfiguration = new PlayersPermissionConfiguration + { + PlayersPermission = new PlayerPermissionConfiguration[] + { + new PlayerPermissionConfiguration() + { + UserId = NewOwner.UserId, + IsServerOwner = NewOwner.IsServerOwner, + HasRecommendBeatmapsPermission = NewOwner.CanRecommendBeatmaps, + HasRecommendGameplayModifiersPermission = NewOwner.CanRecommendModifiers, + HasKickVotePermission = NewOwner.CanKickVote, + HasInvitePermission = NewOwner.CanInvite + } + } + } + }, IgnoranceChannelTypes.Reliable); + } + //Disable start button if no map is selected + if (NewOwner.BeatmapIdentifier == null) + PacketDispatcher.SendToPlayer(NewOwner, new SetIsStartButtonEnabledPacket + { + Reason = CannotStartGameReason.NoSongSelected + }, IgnoranceChannelTypes.Reliable); + } + private async void SendSyncTime(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) @@ -671,11 +689,6 @@ private async void SendSyncTime(CancellationToken cancellationToken) } } - public void InstanceConfigUpdated() - { - UpdateInstanceEvent?.Invoke(this); - } - #endregion } } diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs index e0a6081c..15448b7d 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs @@ -5,7 +5,6 @@ using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.GameplayRpc; -//using BeatTogether.LiteNetLib.Enums; using Serilog; using System; using System.Collections.Concurrent; diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 9f81a019..4f6fb984 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -34,7 +34,7 @@ public sealed class LobbyManager : ILobbyManager, IDisposable public bool AllPlayersAreInLobby => _playerRegistry.Players.All(p => p.InMenu);//if all are going to be spectating public bool DoesEveryoneOwnBeatmap => SelectedBeatmap != null && !_playerRegistry.Players.Any(p => (p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) && !p.IsSpectating && p.WantsToPlayNextLevel); public bool SpectatingPlayersUpdated { get; set; } = false; - public bool ForceStartSelectedBeatmap { get; set; } = false; + public bool ForceStartSelectedBeatmap { get; set; } = false; //For future server-side things public BeatmapIdentifier? SelectedBeatmap { get; private set; } = null; public GameplayModifiers SelectedModifiers { get; private set; } = new(); diff --git a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs index 5cfcef4d..12acbe03 100644 --- a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs @@ -78,10 +78,7 @@ public bool AddPlayer(IPlayer player) _playersByRemoteEndPoint.TryAdd(player.Endpoint, player); _playersByConnectionId.TryAdd(player.ConnectionId, player); _PlayerCount++; - lock (MillisBetweenSyncStatePackets_Lock) - { - MillisBetweenSyncStatePackets = (int)(0.84 * _PlayerCount + 15.789); - } + MillisBetweenSyncStatePackets = (int)(0.84 * _PlayerCount + 15.789); return true; } } @@ -97,10 +94,7 @@ public void RemovePlayer(IPlayer player) _playersByRemoteEndPoint.Remove(player.Endpoint, out _); _playersByConnectionId.Remove(player.ConnectionId, out _); _PlayerCount--; - lock (MillisBetweenSyncStatePackets_Lock) - { - MillisBetweenSyncStatePackets = (int)(0.84 * _PlayerCount + 15.789); - } + MillisBetweenSyncStatePackets = (int)(0.84 * _PlayerCount + 15.789); } } } @@ -127,14 +121,10 @@ public bool TryGetPlayer(string userId, [MaybeNullWhen(false)] out IPlayer playe } } - private readonly object MillisBetweenSyncStatePackets_Lock = new(); private int MillisBetweenSyncStatePackets = 0; public int GetMillisBetweenSyncStatePackets() { - lock (MillisBetweenSyncStatePackets_Lock) - { - return MillisBetweenSyncStatePackets; - } + return MillisBetweenSyncStatePackets; } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs index 1454b9ec..0cf66c08 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/BitMask128.cs @@ -23,7 +23,7 @@ public bool Contains(string value, int hashCount = 3, int hashBits = 8) uint hash = MurmurHash2(value); for (int i = 0; i < hashCount; i++) { - if (GetBits((int)((ulong)hash % (ulong)((long)BitCount)), 1) == 0UL) + if (GetBits((int)(hash % (ulong)((long)BitCount)), 1) == 0UL) { return false; } @@ -32,6 +32,16 @@ public bool Contains(string value, int hashCount = 3, int hashBits = 8) return true; } + public void WriteToBitMask(string value, int hashCount = 3, int hashBits = 8) + { + ulong hash = MurmurHash2(value); + for(int i = 0; i < hashCount; i++) + { + SetBits((int)(hash % (ulong)((long)BitCount)), 1UL); + hash >>= hashBits; + } + } + public ulong GetBits(int offset, int count) { ulong num = (1UL << count) - 1UL; From 6ea9913d8cc331252ba8bcdf933395d952d95877 Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 8 Apr 2024 06:10:51 +0100 Subject: [PATCH 097/120] Cleanup lobby manager and gamplay code in regards to player states and making code more readable --- .../Managers/Abstractions/ILobbyManager.cs | 6 +- .../Managers/GameplayManager.cs | 10 +- .../Managers/LobbyManager.cs | 206 ++++++++---------- .../MenuRpc/SetIsInLobbyPacketHandler.cs | 2 +- .../PlayerStatePacketHandler.cs | 4 +- BeatTogether.DedicatedServer.Kernel/Player.cs | 18 +- 6 files changed, 110 insertions(+), 136 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs index 2db9c9fa..aa1b886b 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs @@ -8,16 +8,16 @@ namespace BeatTogether.DedicatedServer.Kernel.Managers.Abstractions public interface ILobbyManager { bool AllPlayersReady { get; } - bool SomePlayersReady { get; } + bool AnyPlayersReady { get; } bool NoPlayersReady { get; } bool AllPlayersNotWantToPlayNextLevel { get; } - bool DoesEveryoneOwnBeatmap { get; } + bool CanEveryonePlayBeatmap { get; } BeatmapIdentifier? SelectedBeatmap { get; } GameplayModifiers SelectedModifiers { get; } CountdownState CountDownState { get; } long CountdownEndTime { get; } GameplayModifiers EmptyModifiers {get; } - public bool SpectatingPlayersUpdated { get; set; } + public bool UpdateSpectatingPlayers { get; set; } public bool ForceStartSelectedBeatmap { get; set; } void Update(); diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs index 15448b7d..028bde36 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs @@ -101,8 +101,12 @@ public async void StartSong(CancellationToken cancellationToken) State = GameplayManagerState.SceneLoad; foreach (var player in _playerRegistry.Players)//Array of players that are playing at the start { - if (!player.IsSpectating && !player.ForceLateJoin && !player.IsBackgrounded) + if (player.WantsToPlayNextLevel && !player.IsSpectating && !player.IsBackgrounded && !player.ForceLateJoin) + { PlayersAtStart.Add(player.UserId); + } + //if (!player.IsSpectating && !player.ForceLateJoin && !player.IsBackgrounded) + // PlayersAtStart.Add(player.UserId); } // Create level finished tasks (players may send these at any time during gameplay) @@ -159,7 +163,7 @@ public async void StartSong(CancellationToken cancellationToken) { if (_playerRegistry.TryGetPlayer(UserId, out var p)) { - if (!p.InGameplay || p.InLobby) + if (!p.InGameplay || !p.IsActive) HandlePlayerLeaveGameplay(p); StartDelay = Math.Max(StartDelay, p.Latency.CurrentAverage); } @@ -176,7 +180,7 @@ public async void StartSong(CancellationToken cancellationToken) StartTime = SongStartTime }, IgnoranceChannelTypes.Reliable); - //Initiates the song start process for forced late joiners + //Initiates the song start process for forced late joiners - try force them to spectate if they were causing issues in countdown foreach(IPlayer p in _playerRegistry.Players) { if (p.ForceLateJoin) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 4f6fb984..ac953a16 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -27,13 +27,13 @@ namespace BeatTogether.DedicatedServer.Kernel.Managers { public sealed class LobbyManager : ILobbyManager, IDisposable { - public bool AllPlayersReady => _playerRegistry.Players.All(p => p.IsReady || !p.WantsToPlayNextLevel); //If all are ready or not playing - public bool SomePlayersReady => _playerRegistry.Players.Any(p => p.IsReady); //If anyone is readied - public bool NoPlayersReady => _playerRegistry.Players.All(p => !p.IsReady || !p.WantsToPlayNextLevel); //players not ready or are going to spectate + public bool AllPlayersReady => _playerRegistry.Players.All(p => p.IsReady || !p.WantsToPlayNextLevel || p.IsBackgrounded || p.IsSpectating); //If all are ready or spectating or backgrounded or a spectator type + public bool AnyPlayersReady => _playerRegistry.Players.Any(p => p.IsReady && p.WantsToPlayNextLevel && !p.IsBackgrounded && !p.IsSpectating); //If anyone who is active wants to play + public bool NoPlayersReady => !AnyPlayersReady;//no players want to play right now public bool AllPlayersNotWantToPlayNextLevel => _playerRegistry.Players.All(p => !p.WantsToPlayNextLevel);//if all are going to be spectating - public bool AllPlayersAreInLobby => _playerRegistry.Players.All(p => p.InMenu);//if all are going to be spectating - public bool DoesEveryoneOwnBeatmap => SelectedBeatmap != null && !_playerRegistry.Players.Any(p => (p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) && !p.IsSpectating && p.WantsToPlayNextLevel); - public bool SpectatingPlayersUpdated { get; set; } = false; + public bool AllPlayersAreInLobby => _playerRegistry.Players.All(p => p.InMenu); + public bool CanEveryonePlayBeatmap => SelectedBeatmap != null && !_playerRegistry.Players.Any(p => (p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned) && !p.IsSpectating && !p.IsBackgrounded && p.WantsToPlayNextLevel); + public bool UpdateSpectatingPlayers { get; set; } = false; public bool ForceStartSelectedBeatmap { get; set; } = false; //For future server-side things public BeatmapIdentifier? SelectedBeatmap { get; private set; } = null; @@ -43,7 +43,7 @@ public sealed class LobbyManager : ILobbyManager, IDisposable private BeatmapIdentifier? _lastBeatmap = null; private bool _lastSpectatorState; - private bool _AllOwnMap; + private bool _LastCanEveryonePlayBeatmap; private string _lastManagerId = null!; private readonly CancellationTokenSource _stopCts = new(); private const int LoopTime = 100; @@ -96,6 +96,10 @@ private async void UpdateLoop(CancellationToken cancellationToken) } } + /// + /// Force starts the beatmap without waiting for players to download the map. If they dont download the map in time then they should end up spectating + /// Currently not used, probably needs fixing + /// public void ForceStartBeatmapUpdate() { if(SelectedBeatmap != null) @@ -108,20 +112,8 @@ public void ForceStartBeatmapUpdate() { SetCountdown(CountdownState.WaitingForEntitlement); } - if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsBackgrounded || !p.WantsToPlayNextLevel || p.ForceLateJoin)) + if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || !p.WantsToPlayNextLevel || p.IsBackgrounded || p.ForceLateJoin)) { -/* foreach (IPlayer p in _playerRegistry.Players) - { - if (p.GetEntitlement(SelectedBeatmap.LevelId) is not EntitlementStatus.Ok || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin) - { - _packetDispatcher.SendFromPlayer(p, new SetIsEntitledToLevelPacket() - { - LevelId = SelectedBeatmap.LevelId, - Entitlement = EntitlementStatus.Ok - }, IgnoranceChannelTypes.Reliable); - } - }*/ - //The clients need to be sent that all the payers have OK entitlement //starts beatmap _gameplayManager.SetBeatmap(SelectedBeatmap!, SelectedModifiers); Task.Run(() => _gameplayManager.StartSong(CancellationToken.None)); @@ -142,17 +134,13 @@ public void ForceStartBeatmapUpdate() } if(CountdownEndTime + _configuration.SendPlayersWithoutEntitlementToSpectateTimeout <= _instance.RunTime) { - foreach (IPlayer p in _playerRegistry.Players) + IPlayer[] MissingEntitlement = _playerRegistry.Players.Where(p => p.GetEntitlement(SelectedBeatmap!.LevelId) is not EntitlementStatus.Ok).ToArray(); + foreach (IPlayer p in MissingEntitlement) { - if (p.GetEntitlement(SelectedBeatmap.LevelId) is not EntitlementStatus.Ok) - { - //TODO This needs changing? we just kick the player for now, but really we want to send them to spectator - _packetDispatcher.SendToPlayer(p, new KickPlayerPacket - { - DisconnectedReason = DisconnectedReason.Kicked - }, IgnoranceChannelTypes.Reliable); - p.ForceLateJoin = true; - } + //Force the player to join late + p.ForceLateJoin = true; + _packetDispatcher.SendToPlayer(p, new CancelLevelStartPacket(), IgnoranceChannelTypes.Reliable); + _packetDispatcher.SendToPlayer(p, new SetIsReadyPacket() { IsReady = false }, IgnoranceChannelTypes.Reliable); } } } @@ -169,74 +157,36 @@ public void Update() UpdateBeatmap(GetSelectedBeatmap(), GetSelectedModifiers()); - if (_lastManagerId != null && _lastManagerId != _configuration.ServerOwnerId && _playerRegistry.TryGetPlayer(_lastManagerId, out var OldManager)) - _packetDispatcher.SendToPlayer(OldManager, new SetIsStartButtonEnabledPacket - { - Reason = CannotStartGameReason.None - }, IgnoranceChannelTypes.Reliable); - - if (ForceStartSelectedBeatmap) - { - ForceStartBeatmapUpdate(); - return; - } - - foreach (IPlayer player in _playerRegistry.Players) - { - if (player.UpdateEntitlement || SpectatingPlayersUpdated) - { - player.UpdateEntitlement = false; - if (player.BeatmapIdentifier != null) - { - _packetDispatcher.SendToPlayer(player, new SetPlayersMissingEntitlementsToLevelPacket - { - PlayersWithoutEntitlements = _playerRegistry.Players - .Where(p => (p.GetEntitlement(player.BeatmapIdentifier.LevelId) is EntitlementStatus.NotOwned or EntitlementStatus.Unknown) && !p.IsSpectating && p.WantsToPlayNextLevel) - .Select(p => p.UserId).ToArray() - }, IgnoranceChannelTypes.Reliable); - //_logger.Debug("Sent missing entitlement packet"); - } - } - } - SpectatingPlayersUpdated = false; - bool allPlayersOwnBeatmap = DoesEveryoneOwnBeatmap; + UpdatePlayersMissingEntitlementsMessages(); if (_configuration.SongSelectionMode == SongSelectionMode.ServerOwnerPicks) { - if (_lastBeatmap != SelectedBeatmap || _AllOwnMap != allPlayersOwnBeatmap || _lastSpectatorState != AllPlayersNotWantToPlayNextLevel) + if (_lastBeatmap != SelectedBeatmap || _LastCanEveryonePlayBeatmap != CanEveryonePlayBeatmap || _lastSpectatorState != AllPlayersNotWantToPlayNextLevel) { _packetDispatcher.SendToPlayer(serverOwner!, new SetIsStartButtonEnabledPacket { - Reason = GetCannotStartGameReason(serverOwner!, allPlayersOwnBeatmap) + Reason = GetCannotStartGameReason(serverOwner!, CanEveryonePlayBeatmap) }, IgnoranceChannelTypes.Reliable); } } - _AllOwnMap = allPlayersOwnBeatmap; - if (SelectedBeatmap != null) - { - switch (_configuration.SongSelectionMode) //server modes - { - case SongSelectionMode.ServerOwnerPicks: - CountingDown(serverOwner!.IsReady, !serverOwner.IsReady); - break; - case SongSelectionMode.Vote: - CountingDown(SomePlayersReady, NoPlayersReady); - break; - case SongSelectionMode.RandomPlayerPicks: - CountingDown(SomePlayersReady, NoPlayersReady); - break; - case SongSelectionMode.ServerPicks: - CountingDown(true, false); - break; - } - } - else + + switch (_configuration.SongSelectionMode) //server modes { - //Send stop countdown packet if the beatmap is somehow set to null (serrver owner may disconnect, or if tournament server setting the beatmap to null should stop the countdown) - if (CountDownState != CountdownState.NotCountingDown) - CancelCountdown(); + case SongSelectionMode.ServerOwnerPicks: + CountingDown(serverOwner!.IsReady, !serverOwner.IsReady || AllPlayersNotWantToPlayNextLevel || !CanEveryonePlayBeatmap); + break; + case SongSelectionMode.Vote: + CountingDown(AnyPlayersReady, NoPlayersReady || AllPlayersNotWantToPlayNextLevel || !CanEveryonePlayBeatmap); + break; + case SongSelectionMode.RandomPlayerPicks: + CountingDown(AnyPlayersReady, NoPlayersReady || AllPlayersNotWantToPlayNextLevel || !CanEveryonePlayBeatmap); + break; + case SongSelectionMode.ServerPicks: + CountingDown(true, false); + break; } + _LastCanEveryonePlayBeatmap = CanEveryonePlayBeatmap; _lastManagerId = _configuration.ServerOwnerId; _lastSpectatorState = AllPlayersNotWantToPlayNextLevel; _lastBeatmap = SelectedBeatmap; @@ -250,50 +200,43 @@ private void CountingDown(bool isReady, bool NotStartable) { if (CountdownEndTime != 0 && CountdownEndTime <= _instance.RunTime) CancelCountdown(); - if ((AllPlayersReady && !AllPlayersNotWantToPlayNextLevel && _AllOwnMap)) - SetCountdown(CountdownState.StartBeatmapCountdown, _configuration.CountdownConfig.BeatMapStartCountdownTime); - else if (isReady && _AllOwnMap) - SetCountdown(CountdownState.CountingDown, _configuration.CountdownConfig.CountdownTimePlayersReady); + if (isReady && !NotStartable) + SetCountdown(CountdownState.CountingDown, _configuration.CountdownConfig.CountdownTimePlayersReady); //Begin normal countdown + else if (AllPlayersReady && !NotStartable) + SetCountdown(CountdownState.StartBeatmapCountdown, _configuration.CountdownConfig.BeatMapStartCountdownTime); //Lock in beatmap and being starting countdown } // If counting down if (CountDownState != CountdownState.NotCountingDown) { //_logger.Debug($"CountdownEndTime '{CountdownEndTime}' RunTime '{_instance.RunTime}'"); - if(CountdownEndTime <= _instance.RunTime) + //If the beatmap is not playable or the game is not startable + if ( NotStartable ) { - _logger.Debug($"Countdown finished, sending map"); + _logger.Debug("Canceling countdown"); + CancelCountdown(); + return; + } + if (CountdownEndTime <= _instance.RunTime) + { + _logger.Debug($"Countdown finished, sending map again and waiting for entitlement check"); // If countdown just finished, send map then pause lobby untill all players have map downloaded if (CountDownState != CountdownState.WaitingForEntitlement) { SetCountdown(CountdownState.WaitingForEntitlement); } - if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin)) + if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || !p.WantsToPlayNextLevel || p.IsBackgrounded || p.ForceLateJoin)) { - //Dont do this as we dont want clients to store incorrect info on players entitlements -/* foreach(IPlayer p in _playerRegistry.Players) - { - if (p.IsSpectating || !p.WantsToPlayNextLevel || p.ForceLateJoin) - { - //Force send to everyone that those players have the map. - _packetDispatcher.SendFromPlayer(p, new SetIsEntitledToLevelPacket() - { - LevelId = SelectedBeatmap!.LevelId, - Entitlement = EntitlementStatus.Ok - }, IgnoranceChannelTypes.Reliable); - } - }*/ - _logger.Debug($"All players have entitlement, starting map"); + _logger.Debug($"All players have entitlement or are not playing, starting map"); //starts beatmap _gameplayManager.SetBeatmap(SelectedBeatmap!, SelectedModifiers); - Task.Run(() => _gameplayManager.StartSong(CancellationToken.None)); - //stops countdown SetCountdown(CountdownState.NotCountingDown); + Task.Run(() => _gameplayManager.StartSong(CancellationToken.None)); return; } if (CountdownEndTime + _configuration.SendPlayersWithoutEntitlementToSpectateTimeout <= _instance.RunTime) //If takes too long to start then players are sent to spectate by telling them the beatmap already started { - _logger.Debug($"Took too long to start, sending players to spectate"); - IPlayer[] MissingEntitlement = _playerRegistry.Players.Where(p => p.GetEntitlement(SelectedBeatmap!.LevelId) is not EntitlementStatus.Ok).ToArray(); + _logger.Debug($"Took too long to start, sending problem players to spectate"); + IPlayer[] MissingEntitlement = _playerRegistry.Players.Where(p => p.GetEntitlement(SelectedBeatmap!.LevelId) is not EntitlementStatus.Ok && !p.IsSpectating && p.WantsToPlayNextLevel && !p.IsBackgrounded).ToArray(); foreach (IPlayer p in MissingEntitlement) { //Force the player to join late @@ -303,11 +246,10 @@ private void CountingDown(bool isReady, bool NotStartable) } } } - // If server owner/all players are no longer ready or not all players own beatmap or beatmap is null - if (NotStartable || !_AllOwnMap || AllPlayersNotWantToPlayNextLevel || ((CountdownEndTime - _instance.RunTime) < _configuration.CountdownConfig.BeatMapStartCountdownTime && SelectedBeatmap == null)) - CancelCountdown(); - else if (CountDownState == CountdownState.CountingDown && (AllPlayersReady || (CountdownEndTime - _instance.RunTime) < _configuration.CountdownConfig.BeatMapStartCountdownTime)) + if (CountDownState == CountdownState.CountingDown && (AllPlayersReady || (CountdownEndTime - _instance.RunTime) < _configuration.CountdownConfig.BeatMapStartCountdownTime)) + { SetCountdown(CountdownState.StartBeatmapCountdown, _configuration.CountdownConfig.BeatMapStartCountdownTime); + } } } @@ -337,6 +279,35 @@ private void UpdateBeatmap(BeatmapIdentifier? beatmap, GameplayModifiers modifie } } + private void UpdatePlayersMissingEntitlementsMessages() + { + foreach (IPlayer player in _playerRegistry.Players) + { + if (player.UpdateEntitlement || UpdateSpectatingPlayers) + { + player.UpdateEntitlement = false; + if (player.BeatmapIdentifier != null) + { + _packetDispatcher.SendToPlayer(player, new SetPlayersMissingEntitlementsToLevelPacket + { + PlayersWithoutEntitlements = _playerRegistry.Players + .Where(p => (p.GetEntitlement(player.BeatmapIdentifier.LevelId) is EntitlementStatus.NotOwned) && !p.IsSpectating && p.WantsToPlayNextLevel && !p.IsBackgrounded) + .Select(p => p.UserId).ToArray() + }, IgnoranceChannelTypes.Reliable); + //_logger.Debug("Sent missing entitlement packet"); + } + else + { //Send empty if no map is selected + _packetDispatcher.SendToPlayer(player, new SetPlayersMissingEntitlementsToLevelPacket + { + PlayersWithoutEntitlements = { } + }, IgnoranceChannelTypes.Reliable); + } + } + } + UpdateSpectatingPlayers = false; + } + public BeatmapDifficulty[] GetSelectedBeatmapDifficulties() { if (!SelectedBeatmap!.LevelId.StartsWith("custom_level_")) @@ -358,8 +329,6 @@ public BeatmapDifficulty[] GetSelectedBeatmapDifficulties() // If you want to cancel the countdown use CancelCountdown(), Not SetCountdown as CancelCountdown() ALSO informs the clients it has been canceled, whereas SetCountdown will not private void SetCountdown(CountdownState countdownState, long countdown = 0) { - //_logger.Error($"CountdownEndTime currently is '{CountdownEndTime}' countdown is set to '{countdown}' state will be set to '{countdownState}' BeatmapStartTime is '{_configuration.CountdownConfig.BeatMapStartCountdownTime}'"); - //_logger.Error($"Check should start Beatmap {(CountdownEndTime - _instance.RunTime) < _configuration.CountdownConfig.BeatMapStartCountdownTime} EndTime '{CountdownEndTime - _instance.RunTime}' RunTime '{_instance.RunTime}'"); CountDownState = countdownState; switch (CountDownState) { @@ -387,12 +356,13 @@ private void SetCountdown(CountdownState countdownState, long countdown = 0) StartBeatmapPacket(); break; } - //_logger.Error($"CountdownEndTime final set to '{CountdownEndTime}' CountdownState '{CountDownState}' countdown is '{countdown}' RunTime is '{_instance.RunTime}' BeatmapStartTime is '{_configuration.CountdownConfig.BeatMapStartCountdownTime}'"); + _logger.Debug($"CountdownEndTime final set to '{CountdownEndTime}' CountdownState '{CountDownState}' countdown is '{countdown}' RunTime is '{_instance.RunTime}'"); } //Checks the lobby settings and sends the player the correct beatmap private void StartBeatmapPacket() { + _logger.Debug("Sending start level packet"); if (!_configuration.AllowPerPlayerModifiers && !_configuration.AllowPerPlayerDifficulties) { _packetDispatcher.SendToNearbyPlayers(new StartLevelPacket diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs index 18af1124..abacfb37 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsInLobbyPacketHandler.cs @@ -41,7 +41,7 @@ public override void Handle(IPlayer sender, SetIsInLobbyPacket packet) { _packetDispatcher.SendToPlayer(sender, new SetIsStartButtonEnabledPacket { - Reason = sender.IsServerOwner ? _lobbyManager.GetCannotStartGameReason(sender, _lobbyManager.DoesEveryoneOwnBeatmap) : CannotStartGameReason.None + Reason = sender.IsServerOwner ? _lobbyManager.GetCannotStartGameReason(sender, _lobbyManager.CanEveryonePlayBeatmap) : CannotStartGameReason.None }, IgnoranceChannelTypes.Reliable); if (_lobbyManager.SelectedBeatmap is null) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs index 4efd833a..d6621d66 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs @@ -27,8 +27,8 @@ public override void Handle(IPlayer sender, PlayerStatePacket packet) ); sender.State = packet.PlayerState; - if (packet.PlayerState.Contains("spectating") != sender.State.Contains("spectating") || packet.PlayerState.Contains("wants_to_play_next_level") != sender.State.Contains("wants_to_play_next_level")) - _lobbyManager.SpectatingPlayersUpdated = true; + if ( packet.PlayerState.Contains("wants_to_play_next_level") != sender.State.Contains("wants_to_play_next_level") || packet.PlayerState.Contains("backgrounded") != sender.State.Contains("backgrounded")) + _lobbyManager.UpdateSpectatingPlayers = true; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index b5e89b46..de3c97fe 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -45,15 +45,15 @@ public sealed class Player : IPlayer public bool CanKickVote => UserId == Instance._configuration.ServerOwnerId; public bool CanInvite => Instance._configuration.DiscoveryPolicy is DiscoveryPolicy.WithCode or DiscoveryPolicy.Public; - public bool ForceLateJoin { get; set; } = false; - - public bool IsPlayer => State.Contains("player"); - public bool IsSpectating => State.Contains("spectating"); //True if spectating players in gameplay - public bool WantsToPlayNextLevel => State.Contains("wants_to_play_next_level"); //True if spectating is toggled in menu - public bool IsBackgrounded => State.Contains("backgrounded"); //No idea - public bool InGameplay => State.Contains("in_gameplay"); //True while in gameplay - public bool WasActiveAtLevelStart => State.Contains("was_active_at_level_start"); //True if the player was active at the level start - need to check if it means they are a spectator or not - public bool IsActive => State.Contains("is_active"); //No idea, i suppose its the opposite of IsBackgrounded + public bool ForceLateJoin { get; set; } = false; //Used to force trouble players to late join a mp game/tell them to spectate + + public bool IsPlayer => State.Contains("player"); //If the user is a player + public bool IsSpectating => State.Contains("spectating"); //True if player is spectating (special case that is not applicable to normal game clients) + public bool WantsToPlayNextLevel => State.Contains("wants_to_play_next_level"); //True if player wants to spectate + public bool IsBackgrounded => State.Contains("backgrounded"); //If user has gone AFK + public bool InGameplay => State.Contains("in_gameplay"); //True while user in gameplay + public bool WasActiveAtLevelStart => State.Contains("was_active_at_level_start"); //True if the player was active at the beatmap level start - playing the level + public bool IsActive => State.Contains("is_active"); //If player is activly playing the beatmap public bool FinishedLevel => State.Contains("finished_level"); //If the player has finished the level public bool InMenu => State.Contains("in_menu"); //Should be true while in lobby From 1d05c2b793c836dcd5b5643206af6c2820a65cb8 Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 8 Apr 2024 06:56:12 +0100 Subject: [PATCH 098/120] Kick problem players that are not informing the server of there entitlement after 30 seconds/have not downloaded the beatmap within 30 seconds --- .../Abstractions/IDedicatedInstance.cs | 3 +-- .../Abstractions/IPlayer.cs | 2 +- .../DedicatedInstance.cs | 15 ++++++--------- .../ENet/ENetServer.cs | 6 +----- .../Managers/LobbyManager.cs | 7 ++++--- BeatTogether.DedicatedServer.Kernel/Player.cs | 2 +- .../InstanceFactory.cs | 1 - .../InstanceRegistry.cs | 1 - .../MasterServerEventHandler.cs | 6 +++++- 9 files changed, 19 insertions(+), 24 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs index c1dbcbae..dd16f30d 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs @@ -21,7 +21,6 @@ public interface IDedicatedInstance InstanceConfiguration _configuration { get; } bool IsRunning { get; } long RunTime { get; } - //public int LiteNetPort { get; } public int Port { get; } MultiplayerGameState State { get; } @@ -35,7 +34,7 @@ public interface IDedicatedInstance Task Stop(CancellationToken cancellationToken = default); - void DisconnectPlayer(string UserId); + void DisconnectPlayer(IPlayer player); int GetNextSortIndex(); void ReleaseSortIndex(int sortIndex); byte GetNextConnectionId(); diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index dd6299c3..367737c8 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -22,7 +22,7 @@ public interface IPlayer Platform Platform { get; set; } string PlatformUserId { get; set; } - uint? ENetPeerId { get; set; } + uint ENetPeerId { get; set; } RollingAverage Latency { get; } long SyncTime { get; } diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 11adc210..34de97c3 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -358,8 +358,6 @@ public override void OnConnect(EndPoint endPoint) "Failed to retrieve player " + $"(RemoteEndPoint='{endPoint}')." ); - //Disconnect(endPoint); - //TODO impliment for enet, enet peers cannot be located at this point as a peer ID is required to kick them return; } PlayerConnectedEvent?.Invoke(player); @@ -526,14 +524,13 @@ public override void OnConnect(EndPoint endPoint) } - public void DisconnectPlayer(string UserId) //Used by master servers kick player event + public void DisconnectPlayer(IPlayer player) { - - if(_playerRegistry.TryGetPlayer(UserId, out var player)) - PacketDispatcher.SendToPlayer(player, new KickPlayerPacket - { - DisconnectedReason = DisconnectedReason.Kicked - }, IgnoranceChannelTypes.Reliable); + PacketDispatcher.SendToPlayer(player, new KickPlayerPacket + { + DisconnectedReason = DisconnectedReason.Kicked + }, IgnoranceChannelTypes.Reliable); + KickPeer(player.ENetPeerId); } public override void OnDisconnect(EndPoint endPoint) diff --git a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs index 4d7762f9..784e4d29 100644 --- a/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs +++ b/BeatTogether.DedicatedServer.Kernel/ENet/ENetServer.cs @@ -246,11 +246,7 @@ public void KickAllPeers() public void Send(IPlayer player, ReadOnlySpan message, IgnoranceChannelTypes deliveryMethod) { - if (!player.ENetPeerId.HasValue) - // Not an ENet peer - return; - - Send(player.ENetPeerId.Value, message, deliveryMethod); + Send(player.ENetPeerId, message, deliveryMethod); } public void Send(uint peerId, ReadOnlySpan message, IgnoranceChannelTypes deliveryMethod) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index ac953a16..a4b1fc7e 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -235,14 +235,15 @@ private void CountingDown(bool isReady, bool NotStartable) } if (CountdownEndTime + _configuration.SendPlayersWithoutEntitlementToSpectateTimeout <= _instance.RunTime) //If takes too long to start then players are sent to spectate by telling them the beatmap already started { - _logger.Debug($"Took too long to start, sending problem players to spectate"); + _logger.Debug($"Took too long to start, kicking problem players"); IPlayer[] MissingEntitlement = _playerRegistry.Players.Where(p => p.GetEntitlement(SelectedBeatmap!.LevelId) is not EntitlementStatus.Ok && !p.IsSpectating && p.WantsToPlayNextLevel && !p.IsBackgrounded).ToArray(); foreach (IPlayer p in MissingEntitlement) { - //Force the player to join late + /* //Force the player to join late p.ForceLateJoin = true; _packetDispatcher.SendToPlayer(p, new CancelLevelStartPacket(), IgnoranceChannelTypes.Reliable); - _packetDispatcher.SendToPlayer(p, new SetIsReadyPacket() { IsReady = false }, IgnoranceChannelTypes.Reliable); + _packetDispatcher.SendToPlayer(p, new SetIsReadyPacket() { IsReady = false }, IgnoranceChannelTypes.Reliable);*/ + _instance.DisconnectPlayer(p); } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index de3c97fe..595766e7 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -19,7 +19,7 @@ public sealed class Player : IPlayer public string UserName { get; } public string PlayerSessionId { get; } - public uint? ENetPeerId { get; set; } + public uint ENetPeerId { get; set; } public RollingAverage Latency { get; } = new(30); public long SyncTime => diff --git a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs index 53d86abc..a7bb7f78 100644 --- a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs +++ b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs @@ -82,7 +82,6 @@ bool AllowNE private void HandleStopEvent(IDedicatedInstance Instance) { _instanceRegistry.RemoveInstance(Instance); - //_portAllocator.ReleasePort(Instance.LiteNetPort); _portAllocator.ReleasePort(Instance.Port); } } diff --git a/BeatTogether.DedicatedServer.Node/InstanceRegistry.cs b/BeatTogether.DedicatedServer.Node/InstanceRegistry.cs index a405f177..5929bfa9 100644 --- a/BeatTogether.DedicatedServer.Node/InstanceRegistry.cs +++ b/BeatTogether.DedicatedServer.Node/InstanceRegistry.cs @@ -1,7 +1,6 @@ using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Node.Abstractions; using System.Collections.Concurrent; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace BeatTogether.DedicatedServer.Node diff --git a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs index 84ed16a4..cfd91018 100644 --- a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs +++ b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs @@ -83,7 +83,11 @@ private Task HandleCheckNode(CheckNodesEvent checkNodesEvent) private Task HandleDisconnectPlayer(DisconnectPlayerFromMatchmakingServerEvent disconnectEvent) { - TryGetDedicatedInstance(disconnectEvent.Secret)?.DisconnectPlayer(disconnectEvent.UserId); + var instance = TryGetDedicatedInstance(disconnectEvent.Secret); + if (instance != null && instance.GetPlayerRegistry().TryGetPlayer(disconnectEvent.UserId, out var player)) + { + instance.DisconnectPlayer(player); + } return Task.CompletedTask; } From 3e95730c89e9bee11de62394115352e76db437f2 Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 8 Apr 2024 07:02:03 +0100 Subject: [PATCH 099/120] Improve player kicking --- .../MenuRpc/RequestKickPlayerPacketHandler.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs index 9d96db99..a037bdb6 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/RequestKickPlayerPacketHandler.cs @@ -1,7 +1,4 @@ -using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Messaging.Enums; -using BeatTogether.DedicatedServer.Messaging.Packets; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using Serilog; @@ -11,14 +8,17 @@ public sealed class RequestKickPlayerPacketHandler : BasePacketHandler(); public RequestKickPlayerPacketHandler( IPlayerRegistry playerRegistry, - IPacketDispatcher packetDispatcher) + IPacketDispatcher packetDispatcher, + IDedicatedInstance dedicatedInstance) { _playerRegistry = playerRegistry; _packetDispatcher = packetDispatcher; + _instance = dedicatedInstance; } public override void Handle(IPlayer sender, RequestKickPlayerPacket packet) @@ -29,10 +29,7 @@ public override void Handle(IPlayer sender, RequestKickPlayerPacket packet) ); if (sender.CanKickVote) if (_playerRegistry.TryGetPlayer(packet.KickedPlayerId, out var kickedPlayer)) - _packetDispatcher.SendToPlayer(kickedPlayer, new KickPlayerPacket - { - DisconnectedReason = DisconnectedReason.Kicked - }, IgnoranceChannelTypes.Reliable); + _instance.DisconnectPlayer(kickedPlayer); } } From 3b12e57ac6e91ce1c08d144dadd0d22ed8f810d7 Mon Sep 17 00:00:00 2001 From: cubic Date: Tue, 9 Apr 2024 11:10:47 +0100 Subject: [PATCH 100/120] Added send to specific players options --- .../Abstractions/IPacketDispatcher.cs | 4 ++- .../PacketDispatcher.cs | 29 +++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs index 0890c705..aea0eddf 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPacketDispatcher.cs @@ -11,7 +11,9 @@ public interface IPacketDispatcher void SendFromPlayerToPlayer(IPlayer fromPlayer, IPlayer toPlayer, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod); void SendToNearbyPlayers(INetSerializable packet, IgnoranceChannelTypes deliveryMethod); void SendToNearbyPlayers(INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod); - void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, IgnoranceChannelTypes deliveryMethod); + void SendToPlayers(IPlayer[] Players, INetSerializable packet, IgnoranceChannelTypes deliveryMethod); + void SendToPlayers(IPlayer[] Players, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod); + void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, IgnoranceChannelTypes deliveryMethod); void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod); void SendFromPlayer(IPlayer fromPlayer, INetSerializable packet, IgnoranceChannelTypes deliveryMethod); void SendFromPlayer(IPlayer fromPlayer, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index 5e5f0aab..3c69f147 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -46,7 +46,6 @@ public void SendToNearbyPlayers(INetSerializable packet, IgnoranceChannelTypes d var writer = new SpanBuffer(stackalloc byte[412]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteOne(ref writer, packet); - _logger.Verbose("Packet: " + packet.GetType().Name + " Was entered into the spanbuffer correctly, now sending once to each player"); foreach (var player in _playerRegistry.Players) SendInternal(player, ref writer, deliveryMethod); @@ -61,10 +60,36 @@ public void SendToNearbyPlayers(INetSerializable[] packets, IgnoranceChannelType var writer = new SpanBuffer(stackalloc byte[1024]); writer.WriteRoutingHeader(ServerId, LocalConnectionId); WriteMany(ref writer, packets); - _logger.Verbose("Packets were entered into the spanbuffer correctly, now sending once to each player"); foreach (var player in _playerRegistry.Players) SendInternal(player, ref writer, deliveryMethod); } + public void SendToPlayers(IPlayer[] players, INetSerializable packet, IgnoranceChannelTypes deliveryMethod) + { + _logger.Debug( + $"Sending packet of type '{packet.GetType().Name}' to specific players" + + $"(SenderId={ServerId})" + ); + + var writer = new SpanBuffer(stackalloc byte[412]); + writer.WriteRoutingHeader(ServerId, LocalConnectionId); + WriteOne(ref writer, packet); + foreach (var player in players) + SendInternal(player, ref writer, deliveryMethod); + + } + public void SendToPlayers(IPlayer[] players, INetSerializable[] packets, IgnoranceChannelTypes deliveryMethod) + { + _logger.Debug( + $"Sending MultiPacket to specific players" + + $"(SenderId={ServerId})" + ); + + var writer = new SpanBuffer(stackalloc byte[1024]); + writer.WriteRoutingHeader(ServerId, LocalConnectionId); + WriteMany(ref writer, packets); + foreach (var player in players) + SendInternal(player, ref writer, deliveryMethod); + } public void SendExcludingPlayer(IPlayer excludedPlayer, INetSerializable packet, IgnoranceChannelTypes deliveryMethod) { From 5ced0a637b8eb2c2ce0d6b428df7404b89a3a8ed Mon Sep 17 00:00:00 2001 From: cubic Date: Tue, 9 Apr 2024 11:18:05 +0100 Subject: [PATCH 101/120] Changed how beatmap requirements and difficulties are stored --- .../Abstractions/IPlayer.cs | 12 +++--- .../Managers/Abstractions/ILobbyManager.cs | 3 +- .../Managers/LobbyManager.cs | 40 +++++++++++-------- .../ClearRecommendedBeatmapPacketHandler.cs | 3 +- .../MenuRpc/GetStartedLevelPacketHandler.cs | 4 +- .../SetRecommendedBeatmapPacketHandler.cs | 11 +++-- .../MultiplayerCore/MPBeatmapPacketHandler.cs | 18 +++++---- BeatTogether.DedicatedServer.Kernel/Player.cs | 15 +------ .../MpCorePackets/MpBeatmapPacket.cs | 4 +- 9 files changed, 57 insertions(+), 53 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index 367737c8..6e09c0c9 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -3,6 +3,7 @@ using BeatTogether.DedicatedServer.Kernel.Types; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; +using System.Collections.Generic; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { @@ -15,13 +16,13 @@ public interface IPlayer string UserId { get; } string UserName { get; } string PlayerSessionId { get; } - + byte[]? Random { get; set; } byte[]? PublicEncryptionKey { get; set; } string ClientVersion { get; set; } Platform Platform { get; set; } string PlatformUserId { get; set; } - + uint ENetPeerId { get; set; } RollingAverage Latency { get; } @@ -59,12 +60,9 @@ public interface IPlayer EntitlementStatus GetEntitlement(string levelId); void SetEntitlement(string levelId, EntitlementStatus entitlement); bool UpdateEntitlement { get; set; } + public string MapHash { get; set; } - public bool Chroma { get; set; } - public bool NoodleExtensions { get; set; } - public bool MappingExtensions { get; set; } - public BeatmapDifficulty[] BeatmapDifficulties { get; set; } - void ResetRecommendedMapRequirements(); + public Dictionary BeatmapDifficultiesRequirements{ get; set; } long TicksAtLastSyncStateDelta { get; set; } long TicksAtLastSyncState { get; set; } } diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs index aa1b886b..14b9105e 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs @@ -2,6 +2,7 @@ using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; +using System.Collections.Generic; namespace BeatTogether.DedicatedServer.Kernel.Managers.Abstractions { @@ -21,7 +22,7 @@ public interface ILobbyManager public bool ForceStartSelectedBeatmap { get; set; } void Update(); - BeatmapDifficulty[] GetSelectedBeatmapDifficulties(); + Dictionary? GetSelectedBeatmapDifficultiesRequirements(); CannotStartGameReason GetCannotStartGameReason(IPlayer player, bool DoesEveryoneOwnBeatmap); } } diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index a4b1fc7e..9d4e3d1f 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -10,7 +10,6 @@ using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.DedicatedServer.Messaging.Packets; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using Serilog; @@ -309,20 +308,21 @@ private void UpdatePlayersMissingEntitlementsMessages() UpdateSpectatingPlayers = false; } - public BeatmapDifficulty[] GetSelectedBeatmapDifficulties() + //TODO do something better than iterating, probs gonna be storing this server side anyway at some point soon + public Dictionary? GetSelectedBeatmapDifficultiesRequirements() { if (!SelectedBeatmap!.LevelId.StartsWith("custom_level_")) { - return Array.Empty(); + return null; } foreach (var player in _playerRegistry.Players) { if(SelectedBeatmap!.LevelId == player.MapHash) { - return player.BeatmapDifficulties; + return player.BeatmapDifficultiesRequirements; } } - return Array.Empty(); + return null; } @@ -374,11 +374,11 @@ private void StartBeatmapPacket() }, IgnoranceChannelTypes.Reliable); return; } - BeatmapDifficulty[] diff = GetSelectedBeatmapDifficulties(); + var diff = GetSelectedBeatmapDifficultiesRequirements(); BeatmapIdentifier bm = SelectedBeatmap!; foreach (var player in _playerRegistry.Players) { - if (_configuration.AllowPerPlayerDifficulties && player.BeatmapIdentifier != null && diff.Contains(player.BeatmapIdentifier.Difficulty)) + if (_configuration.AllowPerPlayerDifficulties && player.BeatmapIdentifier != null && diff != null && diff.ContainsKey((uint)player.BeatmapIdentifier.Difficulty)) bm.Difficulty = player.BeatmapIdentifier.Difficulty; _packetDispatcher.SendToPlayer(player, new StartLevelPacket { @@ -411,24 +411,32 @@ private void CancelCountdown() SetCountdown(CountdownState.NotCountingDown); } + private bool PlayerMapCheck(IPlayer p) + { + //If no map hash then treat as base game map for compat reasons and while waiting for a packet + var Passed = string.IsNullOrEmpty(p.MapHash); + //If not passed, then we have difficulties, and if we have the diff we are looking for, then we can check it for requirements. + if (!Passed && p.BeatmapDifficultiesRequirements.TryGetValue((uint)p.BeatmapIdentifier!.Difficulty, out string[]? Requirements)) + Passed = !(!_configuration.AllowChroma && Requirements.Contains("Chroma")) || !(!_configuration.AllowMappingExtensions && Requirements.Contains("Mapping Extensions")) || !(!_configuration.AllowNoodleExtensions && Requirements.Contains("Noodle Extensions")); + return Passed; + } + private BeatmapIdentifier? GetSelectedBeatmap() { switch(_configuration.SongSelectionMode) { case SongSelectionMode.ServerOwnerPicks: { - if(_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var p)) - if(p.BeatmapIdentifier != null) - { - bool passed = ((!(p.Chroma && !_configuration.AllowChroma) || !(p.MappingExtensions && !_configuration.AllowMappingExtensions) || !(p.NoodleExtensions && !_configuration.AllowNoodleExtensions)) && p.MapHash == p.BeatmapIdentifier!.LevelId) || p.MapHash != p.BeatmapIdentifier!.LevelId; - if (passed) - return p.BeatmapIdentifier; - } + if (_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var p) && p.BeatmapIdentifier != null) + { + if (PlayerMapCheck(p)) + return p.BeatmapIdentifier; + } return null; } case SongSelectionMode.Vote: Dictionary voteDictionary = new(); - foreach (IPlayer player in _playerRegistry.Players.Where(p => p.BeatmapIdentifier != null&& (((!(p.Chroma && !_configuration.AllowChroma) || !(p.MappingExtensions && !_configuration.AllowMappingExtensions) || !(p.NoodleExtensions && !_configuration.AllowNoodleExtensions)) && p.MapHash == p.BeatmapIdentifier!.LevelId) || p.MapHash != p.BeatmapIdentifier!.LevelId))) + foreach (IPlayer player in _playerRegistry.Players.Where(p => PlayerMapCheck(p))) { if (voteDictionary.ContainsKey(player.BeatmapIdentifier!)) voteDictionary[player.BeatmapIdentifier!]++; @@ -456,7 +464,7 @@ private void CancelCountdown() Random rand = new(); int selectedPlayer = rand.Next(_playerRegistry.GetPlayerCount() - 1); RandomlyPickedPlayer = _playerRegistry.Players[selectedPlayer].UserId; - return _playerRegistry.Players[selectedPlayer].BeatmapIdentifier; + return PlayerMapCheck(_playerRegistry.Players[selectedPlayer]) ? _playerRegistry.Players[selectedPlayer].BeatmapIdentifier : null; } return SelectedBeatmap; diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs index c287e186..1c65d73c 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/ClearRecommendedBeatmapPacketHandler.cs @@ -28,7 +28,8 @@ public override void Handle(IPlayer sender, ClearRecommendedBeatmapPacket packet $"(SenderId={sender.ConnectionId})." ); sender.BeatmapIdentifier = null; - sender.ResetRecommendedMapRequirements(); + sender.MapHash = string.Empty; + sender.BeatmapDifficultiesRequirements.Clear(); _packetDispatcher.SendToPlayer(sender, new SetIsStartButtonEnabledPacket { Reason = sender.IsServerOwner ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs index 1d154d49..d26f228d 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs @@ -67,8 +67,8 @@ public override void Handle(IPlayer sender, GetStartedLevelPacket packet) Modifiers = sender.Modifiers; if (_configuration.AllowPerPlayerDifficulties) { - BeatmapDifficulty[] diff = _lobbyManager.GetSelectedBeatmapDifficulties(); - if (sender.BeatmapIdentifier != null && diff.Contains(sender.BeatmapIdentifier.Difficulty)) + var diff = _lobbyManager.GetSelectedBeatmapDifficultiesRequirements(); + if (sender.BeatmapIdentifier != null && diff != null && diff.ContainsKey((uint)sender.BeatmapIdentifier.Difficulty)) Beatmap.Difficulty = sender.BeatmapIdentifier.Difficulty; } _packetDispatcher.SendToPlayer(sender, new StartLevelPacket diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs index 7d45c29d..7115e2a4 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs @@ -3,6 +3,7 @@ using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using Serilog; +using System.Linq; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { @@ -32,11 +33,15 @@ public override void Handle(IPlayer sender, SetRecommendedBeatmapPacket packet) if (sender.CanRecommendBeatmaps) { + if(sender.BeatmapIdentifier != null && sender.BeatmapIdentifier.LevelId != packet.BeatmapIdentifier.LevelId) + { + sender.BeatmapDifficultiesRequirements.Clear(); + sender.MapHash = string.Empty; + } sender.BeatmapIdentifier = packet.BeatmapIdentifier; - if (sender.BeatmapIdentifier.LevelId != sender.MapHash) - sender.ResetRecommendedMapRequirements(); sender.UpdateEntitlement = true; - _packetDispatcher.SendToNearbyPlayers(new GetIsEntitledToLevelPacket + //TODO apply this logic to all entitlement checks, and check it works well. Might need to send everyones entitlements to a player when they select a map + _packetDispatcher.SendToPlayers(_playerRegistry.Players.Where(p => p.GetEntitlement(sender.BeatmapIdentifier.LevelId) == Messaging.Enums.EntitlementStatus.Unknown).ToArray(), new GetIsEntitledToLevelPacket { LevelId = packet.BeatmapIdentifier.LevelId }, IgnoranceChannelTypes.Reliable); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MPBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MPBeatmapPacketHandler.cs index fb916041..597f9572 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MPBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MPBeatmapPacketHandler.cs @@ -26,14 +26,16 @@ public override void Handle(IPlayer sender, MpBeatmapPacket packet) $"Handling packet of type '{nameof(MpBeatmapPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - sender.MapHash = "custom_level_" + packet.levelHash; - if(packet.requirements.TryGetValue(packet.difficulty, out string[]? Requirements)) - { - sender.Chroma = Requirements.Contains("Chroma"); - sender.NoodleExtensions = Requirements.Contains("Noodle Extensions"); - sender.MappingExtensions = Requirements.Contains("Mapping Extensions"); - } - sender.BeatmapDifficulties = packet.requirements.Keys.Select(b => (BeatmapDifficulty)b).ToArray(); + sender.MapHash = packet.levelHash; + + if(sender.BeatmapIdentifier == null) + sender.BeatmapIdentifier = new BeatmapIdentifier(); + sender.BeatmapIdentifier.LevelId = "custom_level_" + packet.levelHash; + sender.BeatmapIdentifier.Characteristic = packet.characteristic; + sender.BeatmapIdentifier.Difficulty = (BeatmapDifficulty)packet.difficulty; + sender.BeatmapDifficultiesRequirements = packet.requirements; + + sender.UpdateEntitlement = true; } } } diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index 595766e7..8105162b 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Net; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Enums; @@ -102,19 +103,7 @@ public void SetEntitlement(string levelId, EntitlementStatus entitlement) public bool UpdateEntitlement { get; set; } = false; public string MapHash { get; set; } = string.Empty; - public bool Chroma { get; set; } = false; - public bool NoodleExtensions { get; set; } = false; - public bool MappingExtensions { get; set; } = false; - public BeatmapDifficulty[] BeatmapDifficulties { get; set; } = Array.Empty(); - - public void ResetRecommendedMapRequirements() - { - MapHash = string.Empty; - Chroma = false; - NoodleExtensions = false; - MappingExtensions = false; - BeatmapDifficulties = Array.Empty(); - } + public Dictionary BeatmapDifficultiesRequirements { get; set; } public long TicksAtLastSyncStateDelta { get; set; } = 0; //33ms gaps for 30/sec, 66ms gap for 15/sec public long TicksAtLastSyncState { get; set; } = 0; diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs index 726d00dd..dbfbd98f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpBeatmapPacket.cs @@ -47,7 +47,7 @@ public void ReadFrom(ref SpanBuffer bufferReader) reqsForDifficulty[j] = bufferReader.ReadString(); requirements[difficulty] = reqsForDifficulty; } - + //contributors byte count = bufferReader.ReadByte(); for (int i = 0; i < count; i++) { @@ -55,7 +55,7 @@ public void ReadFrom(ref SpanBuffer bufferReader) bufferReader.ReadString(); bufferReader.ReadString(); } - + //difficulty colors byte count2 = bufferReader.ReadByte(); for (int i = 0; i < count2; i++) { From a344bea4d9ba6a86fcca1df1ce45054507054aa7 Mon Sep 17 00:00:00 2001 From: cubic Date: Tue, 16 Apr 2024 01:29:43 +0100 Subject: [PATCH 102/120] Cleanup --- .../Models/AvatarData.cs | 25 --------- .../Models/BeatmapIdentifier.cs | 14 ----- .../Models/GameplayModifiers.cs | 44 ---------------- .../Models/LevelCompletionResults.cs | 52 ------------------- .../Abstractions/IDedicatedInstance.cs | 1 - .../NodeService.cs | 8 --- 6 files changed, 144 deletions(-) delete mode 100644 BeatTogether.DedicatedServer.Interface/Models/AvatarData.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Models/BeatmapIdentifier.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Models/GameplayModifiers.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Models/LevelCompletionResults.cs diff --git a/BeatTogether.DedicatedServer.Interface/Models/AvatarData.cs b/BeatTogether.DedicatedServer.Interface/Models/AvatarData.cs deleted file mode 100644 index 867a3138..00000000 --- a/BeatTogether.DedicatedServer.Interface/Models/AvatarData.cs +++ /dev/null @@ -1,25 +0,0 @@ -using BeatTogether.DedicatedServer.Interface.Enums; -using System; -using System.Drawing; - -namespace BeatTogether.DedicatedServer.Interface.Models -{ - public record AvatarData( - string HeadTopId, - Color HeadTopPrimaryColor, - Color HeadTopSecondaryColor, - string GlassesId, - Color GlassesColor, - string FacialHairId, - Color FacialHairColor, - string HandsId, - Color HandsColor, - string ClothesId, - Color ClothesPrimaryColor, - Color ClothesSecondaryColor, - Color ClothesDetailColor, - string SkinColorId, - string EyesId, - string MouthId - ); -} diff --git a/BeatTogether.DedicatedServer.Interface/Models/BeatmapIdentifier.cs b/BeatTogether.DedicatedServer.Interface/Models/BeatmapIdentifier.cs deleted file mode 100644 index 8cadeb37..00000000 --- a/BeatTogether.DedicatedServer.Interface/Models/BeatmapIdentifier.cs +++ /dev/null @@ -1,14 +0,0 @@ - -namespace BeatTogether.DedicatedServer.Interface.Models -{ - public record BeatmapIdentifier(string LevelId, string Characteristic, BeatmapDifficulty Difficulty); - - public enum BeatmapDifficulty : uint - { - Easy = 0, - Normal = 1, - Hard = 2, - Expert = 3, - ExpertPlus = 4 - } -} diff --git a/BeatTogether.DedicatedServer.Interface/Models/GameplayModifiers.cs b/BeatTogether.DedicatedServer.Interface/Models/GameplayModifiers.cs deleted file mode 100644 index a652f8af..00000000 --- a/BeatTogether.DedicatedServer.Interface/Models/GameplayModifiers.cs +++ /dev/null @@ -1,44 +0,0 @@ - -namespace BeatTogether.DedicatedServer.Interface.Models -{ - public record GameplayModifiers( - EnergyType Energy, - bool NoFailOn0Energy, - bool DemoNoFail, - bool InstaFail, - bool FailOnSaberClash, - EnabledObstacleType EnabledObstacle, - bool DemoNoObstacles, - bool FastNotes, - bool StrictAngles, - bool DisappearingArrows, - bool GhostNotes, - bool NoBombs, - SongSpeed Speed, - bool NoArrows, - bool ProMode, - bool ZenMode, - bool SmallCubes - ); - - public enum EnabledObstacleType - { - All, - FullHeightOnly, - NoObstacles - } - - public enum EnergyType - { - Bar, - Battery - } - - public enum SongSpeed - { - Normal, - Faster, - Slower, - SuperFast - } -} diff --git a/BeatTogether.DedicatedServer.Interface/Models/LevelCompletionResults.cs b/BeatTogether.DedicatedServer.Interface/Models/LevelCompletionResults.cs deleted file mode 100644 index fa917eee..00000000 --- a/BeatTogether.DedicatedServer.Interface/Models/LevelCompletionResults.cs +++ /dev/null @@ -1,52 +0,0 @@ - -namespace BeatTogether.DedicatedServer.Interface.Models -{ - public record LevelCompletionResults(GameplayModifiers GameplayModifiers, - int ModifiedScore, - int MultipliedScore, - Rank Rank, - bool FullCombo, - float LeftSaberMovementDistance, - float RightSaberMovementDistance, - float LeftHandMovementDistance, - float RightHandMovementDistance, - LevelEndStateType LevelEndStateType, - LevelEndAction LevelEndAction, - float Energy, - int GoodCutsCount, - int BadCutsCount, - int MissedCount, - int NotGoodCount, - int OkCount, - int MaxCutScore, - int TotalCutScore, - int GoodCutsCountForNotesWithFullScoreScoringType, - float AverageCenterDistanceCutScoreForNotesWithFullScoreScoringType, - float AverageCutScoreForNotesWithFullScoreScoringType, - int MaxCombo, - float EndSongTime - ); - public enum Rank - { - E, - D, - C, - B, - A, - S, - SS, - SSS - } - public enum LevelEndAction - { - None, - Quit, - Restart - } - public enum LevelEndStateType - { - Incomplete, - Cleared, - Failed - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs index dd16f30d..bf18e1de 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs @@ -26,7 +26,6 @@ public interface IDedicatedInstance float NoPlayersTime { get; } - //IHandshakeSessionRegistry GetHandshakeSessionRegistry(); IPlayerRegistry GetPlayerRegistry(); IServiceProvider GetServiceProvider(); diff --git a/BeatTogether.DedicatedServer.Node/NodeService.cs b/BeatTogether.DedicatedServer.Node/NodeService.cs index 4f9c3b27..90f5f161 100644 --- a/BeatTogether.DedicatedServer.Node/NodeService.cs +++ b/BeatTogether.DedicatedServer.Node/NodeService.cs @@ -85,14 +85,6 @@ private void HandleGameInLobbyEvent(string secret, bool state) { _autobus.Publish(new ServerInGameplayEvent(secret, !state, string.Empty)); } - public static Interface.Models.GameplayModifiers GameplayCast(GameplayModifiers v) - { - return new Interface.Models.GameplayModifiers((Interface.Models.EnergyType)v.Energy, v.NoFailOn0Energy, v.DemoNoFail, v.InstaFail, v.FailOnSaberClash, (Interface.Models.EnabledObstacleType)v.EnabledObstacle, v.DemoNoObstacles, v.FastNotes, v.StrictAngles, v.DisappearingArrows, v.GhostNotes, v.NoBombs, (Interface.Models.SongSpeed)v.Speed, v.NoArrows, v.ProMode, v.ZenMode, v.SmallCubes); - } - public static Interface.Models.LevelCompletionResults LevelCompletionCast(LevelCompletionResults y) - { - return new(GameplayCast(y.GameplayModifiers), y.ModifiedScore, y.MultipliedScore, (Interface.Models.Rank)y.Rank, y.FullCombo, y.LeftSaberMovementDistance, y.RightSaberMovementDistance, y.LeftHandMovementDistance, y.RightHandMovementDistance, (Interface.Models.LevelEndStateType)y.LevelEndStateType, (Interface.Models.LevelEndAction)y.LevelEndAction, y.Energy, y.GoodCutsCount, y.BadCutsCount, y.MissedCount, y.NotGoodCount, y.OkCount, y.MaxCutScore, y.TotalCutScore, y.GoodCutsCountForNotesWithFullScoreScoringType, y.AverageCenterDistanceCutScoreForNotesWithFullScoreScoringType, y.AverageCutScoreForNotesWithFullScoreScoringType, y.MaxCombo, y.EndSongTime); - } private void HandleConfigChangeEvent(IDedicatedInstance inst) { From 44d928bcfc03016b25febf5f439e260f5bee36de Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 6 May 2024 19:46:15 +0100 Subject: [PATCH 103/120] First iteration of new stuff --- .../Abstractions/IInstanceFactory.cs | 11 ++ .../Abstractions/IInstanceRegistry.cs | 15 +++ .../Abstractions/IPortAllocator.cs | 2 +- ...Together.DedicatedServer.Instancing.csproj | 22 +++ .../Configuration/InstancingConfiguration.cs | 11 ++ .../Extensions/HostBuilderExtensions.cs | 27 ++++ .../Implimentations/ServerInstance.cs | 46 +++++++ .../InstanceFactory.cs | 104 +++++++++++++++ .../InstanceRegistry.cs | 60 +++++++++ .../LayerService.cs | 93 +++++++++++++ .../PortAllocator.cs | 10 +- ...tTogether.DedicatedServer.Interface.csproj | 3 +- .../Enums/CountdownState.cs | 10 -- .../Enums/DiscoveryPolicy.cs | 9 -- .../Enums/GameplayServerControlSettings.cs | 13 -- .../Enums/GameplayServerMode.cs | 10 -- .../Enums/GameplayState.cs | 11 -- .../Enums/InvitePolicy.cs | 8 -- .../Enums/MultiplayerGameState.cs | 9 -- .../Enums/SongSelectionMode.cs | 11 -- .../Events/MatchmakingServerStoppedEvent.cs | 3 +- .../Events/NodeOnlineEvent.cs | 7 +- .../NodeReceivedPlayerEncryptionEvent.cs | 4 - .../NodeReceivedPlayerSessionDataEvent.cs | 6 + .../Events/NodeStartedEvent.cs | 7 +- .../Events/PlayerJoinEvent.cs | 7 +- .../Events/PlayerLeaveServerEvent.cs | 7 +- .../Events/ServerInGameplayEvent.cs | 6 +- .../Events/UpdateInstanceConfigEvent.cs | 6 +- .../Events/UpdatePlayersEvent.cs | 4 +- .../IMatchmakingService.cs | 2 +- .../Models/GameplayServerConfiguration.cs | 12 -- .../CreateMatchmakingServerRequest.cs | 18 +-- .../CreateMatchmakingServerResponse.cs | 4 +- .../Abstractions/IDedicatedInstance.cs | 4 +- .../Abstractions/IPlayer.cs | 14 +- .../Abstractions/IPlayerRegistry.cs | 5 +- ...BeatTogether.DedicatedServer.Kernel.csproj | 1 + .../SetCountdownTimeHandler.cs | 2 +- .../CommandHandlers/SetResultsTimeHandler.cs | 2 +- .../StartBeatmapTimeHandler.cs | 2 +- .../Configuration/InstanceConfiguration.cs | 22 +-- .../DedicatedInstance.cs | 112 ++++++++-------- .../Enums/CountdownState.cs | 10 -- .../Enums/DiscoveryPolicy.cs | 9 -- .../Enums/GameplayServerControlSettings.cs | 13 -- .../Enums/GameplayServerMode.cs | 10 -- .../Enums/InvitePolicy.cs | 8 -- .../Enums/Platform.cs | 14 -- .../Enums/SongSelectionMode.cs | 11 -- .../GamePlatformToMpCorePlatform.cs | 12 +- .../Managers/Abstractions/ILobbyManager.cs | 4 +- .../Managers/GameplayManager.cs | 31 ++--- .../Managers/LobbyManager.cs | 29 ++-- .../PacketDispatcher.cs | 2 +- .../GetCountdownEndTimePacketHandler.cs | 5 +- .../MenuRpc/GetIsInLobbyPacketHandler.cs | 4 +- ...ersPermissionConfigurationPacketHandler.cs | 4 +- .../GetRecommendedBeatmapPacketHandler.cs | 4 +- .../MenuRpc/GetSelectedBeatmapHandler.cs | 8 +- .../GetSelectedGameplayModifiersHandler.cs | 7 +- .../MenuRpc/GetStartedLevelPacketHandler.cs | 4 +- .../MenuRpc/SetIsReadyPacketHandler.cs | 4 +- .../SetRecommendedBeatmapPacketHandler.cs | 1 + .../DediPacketSetNewManagerHandler.cs | 7 +- .../GetExtraPlayerDataPacketHandler.cs | 4 +- .../PlayerSortOrderPacketHandler.cs | 2 +- BeatTogether.DedicatedServer.Kernel/Player.cs | 21 +-- .../PlayerRegistry.cs | 42 +++--- ...tTogether.DedicatedServer.Messaging.csproj | 1 + .../Enums/MultiplayerGameState.cs | 9 -- .../MenuRpc/SetMultiplayerGameStatePacket.cs | 2 +- .../Abstractions/IInstanceFactory.cs | 25 ---- .../Abstractions/IInstanceRegistry.cs | 12 -- .../Abstractions/INodeService.cs | 6 - .../BeatTogether.DedicatedServer.Node.csproj | 6 +- .../Configuration/NodeConfiguration.cs | 6 +- .../Extensions/HostBuilderExtensions.cs | 19 +-- .../ForwardServerEventsLayer.cs | 57 ++++++++ .../InstanceFactory.cs | 88 ------------ .../InstanceRegistry.cs | 21 --- .../MasterServerEventHandler.cs | 110 --------------- .../Models/PlayerFromMessage.cs | 24 ++++ .../Models/ServerFromMessage.cs | 81 +++++++++++ .../NodeMessageEventHandler.cs | 100 ++++++++++++++ .../NodeService.cs | 126 ++++-------------- BeatTogether.DedicatedServer.sln | 8 +- .../BeatTogether.DedicatedServer.csproj | 1 + BeatTogether.DedicatedServer/Program.cs | 5 +- 89 files changed, 932 insertions(+), 787 deletions(-) create mode 100644 BeatTogether.DedicatedServer.Instancing/Abstractions/IInstanceFactory.cs create mode 100644 BeatTogether.DedicatedServer.Instancing/Abstractions/IInstanceRegistry.cs rename {BeatTogether.DedicatedServer.Node => BeatTogether.DedicatedServer.Instancing}/Abstractions/IPortAllocator.cs (63%) create mode 100644 BeatTogether.DedicatedServer.Instancing/BeatTogether.DedicatedServer.Instancing.csproj create mode 100644 BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs create mode 100644 BeatTogether.DedicatedServer.Instancing/Extensions/HostBuilderExtensions.cs create mode 100644 BeatTogether.DedicatedServer.Instancing/Implimentations/ServerInstance.cs create mode 100644 BeatTogether.DedicatedServer.Instancing/InstanceFactory.cs create mode 100644 BeatTogether.DedicatedServer.Instancing/InstanceRegistry.cs create mode 100644 BeatTogether.DedicatedServer.Instancing/LayerService.cs rename {BeatTogether.DedicatedServer.Node => BeatTogether.DedicatedServer.Instancing}/PortAllocator.cs (81%) delete mode 100644 BeatTogether.DedicatedServer.Interface/Enums/CountdownState.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Enums/DiscoveryPolicy.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Enums/GameplayServerControlSettings.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Enums/GameplayServerMode.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Enums/GameplayState.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Enums/InvitePolicy.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Enums/MultiplayerGameState.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Enums/SongSelectionMode.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Events/NodeReceivedPlayerEncryptionEvent.cs create mode 100644 BeatTogether.DedicatedServer.Interface/Events/NodeReceivedPlayerSessionDataEvent.cs delete mode 100644 BeatTogether.DedicatedServer.Interface/Models/GameplayServerConfiguration.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Enums/CountdownState.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Enums/DiscoveryPolicy.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Enums/GameplayServerControlSettings.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Enums/GameplayServerMode.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Enums/InvitePolicy.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Enums/Platform.cs delete mode 100644 BeatTogether.DedicatedServer.Kernel/Enums/SongSelectionMode.cs delete mode 100644 BeatTogether.DedicatedServer.Messaging/Enums/MultiplayerGameState.cs delete mode 100644 BeatTogether.DedicatedServer.Node/Abstractions/IInstanceFactory.cs delete mode 100644 BeatTogether.DedicatedServer.Node/Abstractions/IInstanceRegistry.cs delete mode 100644 BeatTogether.DedicatedServer.Node/Abstractions/INodeService.cs create mode 100644 BeatTogether.DedicatedServer.Node/ForwardServerEventsLayer.cs delete mode 100644 BeatTogether.DedicatedServer.Node/InstanceFactory.cs delete mode 100644 BeatTogether.DedicatedServer.Node/InstanceRegistry.cs delete mode 100644 BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs create mode 100644 BeatTogether.DedicatedServer.Node/Models/PlayerFromMessage.cs create mode 100644 BeatTogether.DedicatedServer.Node/Models/ServerFromMessage.cs create mode 100644 BeatTogether.DedicatedServer.Node/NodeMessageEventHandler.cs diff --git a/BeatTogether.DedicatedServer.Instancing/Abstractions/IInstanceFactory.cs b/BeatTogether.DedicatedServer.Instancing/Abstractions/IInstanceFactory.cs new file mode 100644 index 00000000..cf67c6f3 --- /dev/null +++ b/BeatTogether.DedicatedServer.Instancing/Abstractions/IInstanceFactory.cs @@ -0,0 +1,11 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.Core.Abstractions; + +namespace BeatTogether.DedicatedServer.Instancing.Abstractions +{ + public interface IInstanceFactory + { + public IDedicatedInstance? CreateInstance( + IServerInstance serverInstance); + } +} diff --git a/BeatTogether.DedicatedServer.Instancing/Abstractions/IInstanceRegistry.cs b/BeatTogether.DedicatedServer.Instancing/Abstractions/IInstanceRegistry.cs new file mode 100644 index 00000000..05114182 --- /dev/null +++ b/BeatTogether.DedicatedServer.Instancing/Abstractions/IInstanceRegistry.cs @@ -0,0 +1,15 @@ +using BeatTogether.Core.Enums; +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using System.Diagnostics.CodeAnalysis; + +namespace BeatTogether.DedicatedServer.Instancing.Abstractions +{ + public interface IInstanceRegistry + { + public bool AddInstance(IDedicatedInstance instance); + public bool RemoveInstance(IDedicatedInstance instance); + public bool TryGetInstance(string secret, [MaybeNullWhen(false)] out IDedicatedInstance instance); + public bool TryGetInstanceByCode(string code, [MaybeNullWhen(false)] out IDedicatedInstance instance); + public bool TryGetAvailablePublicServer(InvitePolicy invitePolicy, GameplayServerMode serverMode, SongSelectionMode songMode, GameplayServerControlSettings serverControlSettings, BeatmapDifficultyMask difficultyMask, GameplayModifiersMask modifiersMask, string songPackMasks, [MaybeNullWhen(false)] out IDedicatedInstance instance); + } +} diff --git a/BeatTogether.DedicatedServer.Node/Abstractions/IPortAllocator.cs b/BeatTogether.DedicatedServer.Instancing/Abstractions/IPortAllocator.cs similarity index 63% rename from BeatTogether.DedicatedServer.Node/Abstractions/IPortAllocator.cs rename to BeatTogether.DedicatedServer.Instancing/Abstractions/IPortAllocator.cs index ef13698e..39ac81e3 100644 --- a/BeatTogether.DedicatedServer.Node/Abstractions/IPortAllocator.cs +++ b/BeatTogether.DedicatedServer.Instancing/Abstractions/IPortAllocator.cs @@ -1,4 +1,4 @@ -namespace BeatTogether.DedicatedServer.Node.Abstractions +namespace BeatTogether.DedicatedServer.Instancing.Abstractions { public interface IPortAllocator { diff --git a/BeatTogether.DedicatedServer.Instancing/BeatTogether.DedicatedServer.Instancing.csproj b/BeatTogether.DedicatedServer.Instancing/BeatTogether.DedicatedServer.Instancing.csproj new file mode 100644 index 00000000..ebcdd38d --- /dev/null +++ b/BeatTogether.DedicatedServer.Instancing/BeatTogether.DedicatedServer.Instancing.csproj @@ -0,0 +1,22 @@ + + + + net6.0 + 9 + icon.png + BeatTogether Team + BeatTogether + https://github.com/beattogether/BeatTogether.DedicatedServer + 1.0.0 + enable + + + + + + + + + + + diff --git a/BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs b/BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs new file mode 100644 index 00000000..8be3b3b2 --- /dev/null +++ b/BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs @@ -0,0 +1,11 @@ +using System; + +namespace BeatTogether.DedicatedServer.Instancing.Configuration +{ + public sealed class InstancingConfiguration + { + public string HostName { get; set; } = "192.168.0.21"; + public int BasePort { get; set; } = 30000; + public int MaximumSlots { get; set; } = 10000; + } +} diff --git a/BeatTogether.DedicatedServer.Instancing/Extensions/HostBuilderExtensions.cs b/BeatTogether.DedicatedServer.Instancing/Extensions/HostBuilderExtensions.cs new file mode 100644 index 00000000..b918e4fe --- /dev/null +++ b/BeatTogether.DedicatedServer.Instancing/Extensions/HostBuilderExtensions.cs @@ -0,0 +1,27 @@ +using BeatTogether.DedicatedServer.Instancing.Configuration; +using BeatTogether.DedicatedServer.Instancing.Abstractions; +using BeatTogether.Extensions; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using BeatTogether.DedicatedServer.Kernel.Extensions; +using BeatTogether.Core.Abstractions; + +namespace BeatTogether.DedicatedServer.Instancing.Extensions +{ + public static class HostBuilderExtensions + { + public static IHostBuilder UseDedicatedServerInstancing(this IHostBuilder hostBuilder) => + hostBuilder + .ConfigureAppConfiguration() + .UseSerilog() + .UseDedicatedInstances() + .ConfigureServices((hostBuilderContext, services) => + services + .AddConfiguration("Instancing") + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + ); + } +} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Instancing/Implimentations/ServerInstance.cs b/BeatTogether.DedicatedServer.Instancing/Implimentations/ServerInstance.cs new file mode 100644 index 00000000..77e1e24b --- /dev/null +++ b/BeatTogether.DedicatedServer.Instancing/Implimentations/ServerInstance.cs @@ -0,0 +1,46 @@ +using BeatTogether.Core.Abstractions; +using BeatTogether.Core.Enums; +using BeatTogether.Core.Models; +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; + +namespace BeatTogether.DedicatedServer.Instancing.Implimentations +{ + public class ServerInstance : IServerInstance + { + private readonly IDedicatedInstance _ServerInstance; + + public ServerInstance(IDedicatedInstance serverInstance, IPEndPoint instanceEndPoint) + { + _ServerInstance = serverInstance; + InstanceEndPoint = instanceEndPoint; + } + + public string ServerName { get => _ServerInstance._configuration.ServerName; set => throw new NotImplementedException(); } + public IPEndPoint InstanceEndPoint { get; set; } + public string Secret { get => _ServerInstance._configuration.Secret; set => throw new NotImplementedException(); } + public string Code { get => _ServerInstance._configuration.Code; set => throw new NotImplementedException(); } + public MultiplayerGameState GameState { get => (MultiplayerGameState)_ServerInstance.State; set => throw new NotImplementedException(); } + public BeatmapDifficultyMask BeatmapDifficultyMask { get => _ServerInstance._configuration.BeatmapDifficultyMask; set => throw new NotImplementedException(); } + public GameplayModifiersMask GameplayModifiersMask { get => _ServerInstance._configuration.GameplayModifiersMask; set => throw new NotImplementedException(); } + public string SongPackMasks { get => _ServerInstance._configuration.SongPacksMask; set => throw new NotImplementedException(); } + public GameplayServerConfiguration GameplayServerConfiguration { get => _ServerInstance._configuration.GameplayServerConfiguration; set => throw new NotImplementedException(); } + public HashSet PlayerHashes { get => _ServerInstance.GetPlayerRegistry().Players.Select(p => p.HashedUserId).ToHashSet(); set => throw new NotImplementedException(); } + public string InstanceId { get => _ServerInstance._configuration.ServerId; set => throw new NotImplementedException(); } + public string ManagerId { get => _ServerInstance._configuration.ServerOwnerId; set => throw new NotImplementedException(); } + public bool PermanentManager { get => !string.IsNullOrEmpty(_ServerInstance._configuration.SetConstantManagerFromUserId); set => throw new NotImplementedException(); } + public long ServerStartJoinTimeout { get => _ServerInstance._configuration.DestroyInstanceTimeout; set => throw new NotImplementedException(); } + public bool NeverCloseServer { get => _ServerInstance._configuration.DestroyInstanceTimeout == -1; set => throw new NotImplementedException(); } + public long ResultScreenTime { get => _ServerInstance._configuration.CountdownConfig.ResultsScreenTime; set => throw new NotImplementedException(); } + public long BeatmapStartTime { get => _ServerInstance._configuration.CountdownConfig.BeatMapStartCountdownTime; set => throw new NotImplementedException(); } + public long PlayersReadyCountdownTime { get => _ServerInstance._configuration.CountdownConfig.CountdownTimePlayersReady; set => throw new NotImplementedException(); } + public bool AllowPerPlayerModifiers { get => _ServerInstance._configuration.AllowPerPlayerModifiers; set => throw new NotImplementedException(); } + public bool AllowPerPlayerDifficulties { get => _ServerInstance._configuration.AllowPerPlayerDifficulties; set => throw new NotImplementedException(); } + public bool AllowChroma { get => _ServerInstance._configuration.AllowChroma; set => throw new NotImplementedException(); } + public bool AllowME { get => _ServerInstance._configuration.AllowMappingExtensions; set => throw new NotImplementedException(); } + public bool AllowNE { get => _ServerInstance._configuration.AllowNoodleExtensions; set => throw new NotImplementedException(); } + } +} diff --git a/BeatTogether.DedicatedServer.Instancing/InstanceFactory.cs b/BeatTogether.DedicatedServer.Instancing/InstanceFactory.cs new file mode 100644 index 00000000..4d8ece01 --- /dev/null +++ b/BeatTogether.DedicatedServer.Instancing/InstanceFactory.cs @@ -0,0 +1,104 @@ +using System; +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Kernel.Configuration; +using BeatTogether.Core.Enums; +using BeatTogether.DedicatedServer.Instancing.Abstractions; +using Microsoft.Extensions.DependencyInjection; +using BeatTogether.Core.Abstractions; +using System.Net; +using BeatTogether.DedicatedServer.Instancing.Configuration; +using BeatTogether.Core.ServerMessaging; +using BeatTogether.DedicatedServer.Instancing.Implimentations; +using Serilog; + +namespace BeatTogether.DedicatedServer.Instancing +{ + public sealed class InstanceFactory : IInstanceFactory + { + private readonly IInstanceRegistry _instanceRegistry; + private readonly IServiceProvider _serviceProvider; + private readonly IPortAllocator _portAllocator; + private readonly InstancingConfiguration _config; + private readonly ILayer1? _SendEventsLayer; + private readonly ILogger _logger = Log.ForContext(); + + public InstanceFactory( + IInstanceRegistry instanceRegistry, + IServiceProvider serviceProvider, + IPortAllocator portAllocator, + InstancingConfiguration instancingConfiguration) + { + _instanceRegistry = instanceRegistry; + _serviceProvider = serviceProvider; + _portAllocator = portAllocator; + _config = instancingConfiguration; + + _SendEventsLayer = _serviceProvider.GetService(); + } + + public IDedicatedInstance? CreateInstance(IServerInstance serverInstance) + { + var Port = _portAllocator.AcquirePort(); + + if (!Port.HasValue) + return null; + + var scope = _serviceProvider.CreateScope(); + + var instanceConfig = scope.ServiceProvider.GetRequiredService(); + instanceConfig.Port = (int)Port!; + instanceConfig.Secret = serverInstance.Secret; + instanceConfig.Code = serverInstance.Code; + instanceConfig.ServerId = serverInstance.InstanceId; + _logger.Information("Server ID: " + instanceConfig.ServerId); + instanceConfig.ServerOwnerId = serverInstance.ManagerId; + _logger.Information("Server owner ID: " + instanceConfig.ServerOwnerId); + instanceConfig.GameplayServerConfiguration = serverInstance.GameplayServerConfiguration; + instanceConfig.GameplayModifiersMask = serverInstance.GameplayModifiersMask; + instanceConfig.BeatmapDifficultyMask = serverInstance.BeatmapDifficultyMask; + instanceConfig.SongPacksMask = serverInstance.SongPackMasks; + instanceConfig.DestroyInstanceTimeout = serverInstance.ServerStartJoinTimeout; + instanceConfig.ServerName = serverInstance.ServerName; + instanceConfig.CountdownConfig.BeatMapStartCountdownTime = Math.Max(serverInstance.BeatmapStartTime, 0L); + instanceConfig.CountdownConfig.ResultsScreenTime = Math.Max(serverInstance.ResultScreenTime, 0L); //TODO convert the dedi logic to use long instead of float + instanceConfig.AllowChroma = serverInstance.AllowChroma; + instanceConfig.AllowMappingExtensions = serverInstance.AllowME; + instanceConfig.AllowNoodleExtensions = serverInstance.AllowNE; + instanceConfig.AllowPerPlayerDifficulties = serverInstance.AllowPerPlayerDifficulties; + instanceConfig.AllowPerPlayerModifiers = serverInstance.AllowPerPlayerModifiers; + if (serverInstance.PermanentManager) + instanceConfig.SetConstantManagerFromUserId = serverInstance.ManagerId; + instanceConfig.CountdownConfig.CountdownTimePlayersReady = Math.Max(serverInstance.PlayersReadyCountdownTime, 0L); + if (instanceConfig.CountdownConfig.CountdownTimePlayersReady == 0L) + instanceConfig.CountdownConfig.CountdownTimePlayersReady = instanceConfig.GameplayServerConfiguration.GameplayServerMode == GameplayServerMode.Managed ? 15000L : 30000L; + var instance = scope.ServiceProvider.GetRequiredService(); + if (!_instanceRegistry.AddInstance(instance)) + { + return null; + + } + instance.StopEvent += HandleStopEvent; + + serverInstance.InstanceEndPoint = IPEndPoint.Parse($"{_config.HostName}:{instanceConfig.Port}"); + + //Subscribe to server events if the layer above allows this. + if(_SendEventsLayer != null) + { + instance.StopEvent += (dedi) => _SendEventsLayer.InstanceClosed(new ServerInstance(instance, serverInstance.InstanceEndPoint)); + instance.PlayerConnectedEvent += (player) => _SendEventsLayer.PlayerJoined(new ServerInstance(instance, serverInstance.InstanceEndPoint), player); + instance.PlayerDisconnectedEvent += (player) => _SendEventsLayer.PlayerLeft(new ServerInstance(instance, serverInstance.InstanceEndPoint), player); + instance.PlayerDisconnectBeforeJoining += (a, b, c) => _SendEventsLayer.InstancePlayersChanged(new ServerInstance(instance, serverInstance.InstanceEndPoint)); + instance.GameIsInLobby += (a, b) => _SendEventsLayer.InstanceStateChanged(new ServerInstance(instance, serverInstance.InstanceEndPoint)); + instance.UpdateInstanceEvent += (dedi) => _SendEventsLayer.InstanceConfigChanged(new ServerInstance(instance, serverInstance.InstanceEndPoint)); + } + + return instance; + } + + private void HandleStopEvent(IDedicatedInstance Instance) + { + _instanceRegistry.RemoveInstance(Instance); + _portAllocator.ReleasePort(Instance.Port); + } + } +} diff --git a/BeatTogether.DedicatedServer.Instancing/InstanceRegistry.cs b/BeatTogether.DedicatedServer.Instancing/InstanceRegistry.cs new file mode 100644 index 00000000..edf8f689 --- /dev/null +++ b/BeatTogether.DedicatedServer.Instancing/InstanceRegistry.cs @@ -0,0 +1,60 @@ +using BeatTogether.DedicatedServer.Kernel.Abstractions; +using BeatTogether.DedicatedServer.Instancing.Abstractions; +using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; +using BeatTogether.Core.Enums; +using System.Linq; + +namespace BeatTogether.DedicatedServer.Instancing +{ + public sealed class InstanceRegistry : IInstanceRegistry + { + private readonly ConcurrentDictionary _instances = new(); + private readonly ConcurrentDictionary _instancesByCode = new(); + + public bool AddInstance(IDedicatedInstance instance){ + if (_instances.TryAdd(instance._configuration.Secret, instance)) { + if(_instancesByCode.TryAdd(instance._configuration.Code, instance)) + return true; + _instances.TryRemove(instance._configuration.Secret, out _); + } + return false; + } + + public bool RemoveInstance(IDedicatedInstance instance) => _instances.TryRemove(instance._configuration.Secret, out _) && _instancesByCode.TryRemove(instance._configuration.Code, out _); + + public bool TryGetAvailablePublicServer(InvitePolicy invitePolicy, GameplayServerMode serverMode, SongSelectionMode songMode, GameplayServerControlSettings serverControlSettings, BeatmapDifficultyMask difficultyMask, GameplayModifiersMask modifiersMask, string songPackMasks, [MaybeNullWhen(false)] out IDedicatedInstance instance) + { + instance = null; + var AvaliableServers = _instances.Values.Where(s => + s._configuration.GameplayServerConfiguration.InvitePolicy == invitePolicy && + s._configuration.GameplayServerConfiguration.GameplayServerMode == serverMode && + s._configuration.GameplayServerConfiguration.SongSelectionMode == songMode && + s._configuration.GameplayServerConfiguration.GameplayServerControlSettings == serverControlSettings && + s._configuration.BeatmapDifficultyMask == difficultyMask && + s._configuration.GameplayModifiersMask == modifiersMask && + s._configuration.SongPacksMask == songPackMasks + ); + if (!AvaliableServers.Any()) + return false; + var server = AvaliableServers.First(); + foreach (var publicServer in AvaliableServers) + { + if ((publicServer.GetPlayerRegistry().GetPlayerCount() < publicServer._configuration.GameplayServerConfiguration.MaxPlayerCount && publicServer.GetPlayerRegistry().GetPlayerCount() > server.GetPlayerRegistry().GetPlayerCount())) + { + server = publicServer; + } + } + if (server.GetPlayerRegistry().GetPlayerCount() >= server._configuration.GameplayServerConfiguration.MaxPlayerCount) + return false; + instance = server; + return true; + } + + public bool TryGetInstance(string secret, [MaybeNullWhen(false)] out IDedicatedInstance instance) => + _instances.TryGetValue(secret, out instance); + + public bool TryGetInstanceByCode(string code, [MaybeNullWhen(false)] out IDedicatedInstance instance) => + _instancesByCode.TryGetValue(code, out instance); + } +} diff --git a/BeatTogether.DedicatedServer.Instancing/LayerService.cs b/BeatTogether.DedicatedServer.Instancing/LayerService.cs new file mode 100644 index 00000000..b8b323b0 --- /dev/null +++ b/BeatTogether.DedicatedServer.Instancing/LayerService.cs @@ -0,0 +1,93 @@ +using BeatTogether.Core.Abstractions; +using BeatTogether.Core.Enums; +using BeatTogether.DedicatedServer.Instancing.Abstractions; +using BeatTogether.DedicatedServer.Instancing.Configuration; +using BeatTogether.DedicatedServer.Instancing.Implimentations; +using Serilog; +using System.Net; +using System.Threading.Tasks; + +namespace BeatTogether.DedicatedServer.Instancing +{ + public class LayerService : ILayer2 + { + private readonly IInstanceRegistry _instanceRegistry; + private readonly IInstanceFactory _instanceFactory; + private readonly InstancingConfiguration _instancingConfiguration; + private readonly ILogger _logger = Log.ForContext(); + + + public LayerService(IInstanceRegistry instanceRegistry, IInstanceFactory instanceFactory, InstancingConfiguration instancingConfiguration) + { + _instanceRegistry = instanceRegistry; + _instancingConfiguration = instancingConfiguration; + _instanceFactory = instanceFactory; + } + + public Task CloseInstance(string InstanceSecret) + { + if(_instanceRegistry.TryGetInstance(InstanceSecret, out var Instance)){ + Instance.Stop(); + } + return Task.CompletedTask; + } + + public async Task CreateInstance(IServerInstance serverInstance) + { + var inst = _instanceFactory.CreateInstance(serverInstance); + if(inst != null) + await inst.Start(); + return inst != null; + } + + public Task DisconnectPlayer(string InstanceSecret, string PlayerUserId) + { + if (!_instanceRegistry.TryGetInstance(InstanceSecret, out var instance)) + return Task.CompletedTask; + if (instance.GetPlayerRegistry().TryGetPlayer(PlayerUserId, out var player)) + instance.DisconnectPlayer(player); + + return Task.CompletedTask; + } + + public Task GetAvailablePublicServer(InvitePolicy invitePolicy, GameplayServerMode serverMode, SongSelectionMode songMode, GameplayServerControlSettings serverControlSettings, BeatmapDifficultyMask difficultyMask, GameplayModifiersMask modifiersMask, string songPackMasks) + { + IServerInstance? serverInstance = null; + if (_instanceRegistry.TryGetAvailablePublicServer(invitePolicy, serverMode, songMode, serverControlSettings, difficultyMask, modifiersMask, songPackMasks, out var instance)) + { + serverInstance = new ServerInstance(instance, IPEndPoint.Parse($"{_instancingConfiguration.HostName}:{instance._configuration.Port}")); + } + return Task.FromResult(serverInstance); + } + + public Task GetServer(string secret) + { + IServerInstance? serverInstance = null; + if (_instanceRegistry.TryGetInstance(secret, out var instance)) + { + serverInstance = new ServerInstance(instance, IPEndPoint.Parse($"{_instancingConfiguration.HostName}:{instance._configuration.Port}")); + } + return Task.FromResult(serverInstance); + } + + public Task GetServerByCode(string code) + { + IServerInstance? serverInstance = null; + if (_instanceRegistry.TryGetInstanceByCode(code, out var instance)) + { + serverInstance = new ServerInstance(instance, IPEndPoint.Parse($"{_instancingConfiguration.HostName}:{instance._configuration.Port}")); + } + return Task.FromResult(serverInstance); + } + + public Task SetPlayerSessionData(string serverSecret, IPlayer playerSessionData) + { + _logger.Information("Setting playerSessionData: " + playerSessionData.PlayerSessionId + " In instance: " + serverSecret); + if (!_instanceRegistry.TryGetInstance(serverSecret, out var instance)) + return Task.FromResult(false); + _logger.Information("Found instance, setting session data"); + instance.GetPlayerRegistry().AddExtraPlayerSessionData(playerSessionData); + return Task.FromResult(true); + } + } +} diff --git a/BeatTogether.DedicatedServer.Node/PortAllocator.cs b/BeatTogether.DedicatedServer.Instancing/PortAllocator.cs similarity index 81% rename from BeatTogether.DedicatedServer.Node/PortAllocator.cs rename to BeatTogether.DedicatedServer.Instancing/PortAllocator.cs index 169577a7..06a88a3d 100644 --- a/BeatTogether.DedicatedServer.Node/PortAllocator.cs +++ b/BeatTogether.DedicatedServer.Instancing/PortAllocator.cs @@ -1,13 +1,13 @@ -using BeatTogether.DedicatedServer.Node.Abstractions; -using BeatTogether.DedicatedServer.Node.Configuration; +using BeatTogether.DedicatedServer.Instancing.Abstractions; +using BeatTogether.DedicatedServer.Instancing.Configuration; using System.Collections.Generic; using System.Linq; -namespace BeatTogether.DedicatedServer.Node +namespace BeatTogether.DedicatedServer.Instancing { public sealed class PortAllocator : IPortAllocator { - private readonly NodeConfiguration _configuration; + private readonly InstancingConfiguration _configuration; private readonly object _lock = new(); @@ -17,7 +17,7 @@ public sealed class PortAllocator : IPortAllocator private int _lastPort; public PortAllocator( - NodeConfiguration configuration) + InstancingConfiguration configuration) { _configuration = configuration; diff --git a/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj b/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj index d4e8eb39..991752d4 100644 --- a/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj +++ b/BeatTogether.DedicatedServer.Interface/BeatTogether.DedicatedServer.Interface.csproj @@ -7,7 +7,7 @@ BeatTogether Team BeatTogether https://github.com/beattogether/BeatTogether.DedicatedServer - 1.7.3 + 2.0.2 enable @@ -17,6 +17,7 @@ + diff --git a/BeatTogether.DedicatedServer.Interface/Enums/CountdownState.cs b/BeatTogether.DedicatedServer.Interface/Enums/CountdownState.cs deleted file mode 100644 index 652daf71..00000000 --- a/BeatTogether.DedicatedServer.Interface/Enums/CountdownState.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace BeatTogether.DedicatedServer.Interface.Enums -{ - public enum CountdownState : byte - { - NotCountingDown = 0, - CountingDown = 1, - StartBeatmapCountdown = 2, - WaitingForEntitlement = 3 - } -} diff --git a/BeatTogether.DedicatedServer.Interface/Enums/DiscoveryPolicy.cs b/BeatTogether.DedicatedServer.Interface/Enums/DiscoveryPolicy.cs deleted file mode 100644 index 06a31e51..00000000 --- a/BeatTogether.DedicatedServer.Interface/Enums/DiscoveryPolicy.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace BeatTogether.DedicatedServer.Interface.Enums -{ - public enum DiscoveryPolicy : byte - { - Hidden = 0, - WithCode = 1, - Public = 2 - } -} diff --git a/BeatTogether.DedicatedServer.Interface/Enums/GameplayServerControlSettings.cs b/BeatTogether.DedicatedServer.Interface/Enums/GameplayServerControlSettings.cs deleted file mode 100644 index c4eb0165..00000000 --- a/BeatTogether.DedicatedServer.Interface/Enums/GameplayServerControlSettings.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace BeatTogether.DedicatedServer.Interface.Enums -{ - [Flags] - public enum GameplayServerControlSettings - { - None = 0, - AllowModifierSelection = 1, - AllowSpectate = 2, - All = 3 - } -} diff --git a/BeatTogether.DedicatedServer.Interface/Enums/GameplayServerMode.cs b/BeatTogether.DedicatedServer.Interface/Enums/GameplayServerMode.cs deleted file mode 100644 index 1ad500fc..00000000 --- a/BeatTogether.DedicatedServer.Interface/Enums/GameplayServerMode.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace BeatTogether.DedicatedServer.Interface.Enums -{ - public enum GameplayServerMode - { - Countdown = 0, - Managed = 1, - QuickStartOneSong = 2, - Tournament = 3 - } -} diff --git a/BeatTogether.DedicatedServer.Interface/Enums/GameplayState.cs b/BeatTogether.DedicatedServer.Interface/Enums/GameplayState.cs deleted file mode 100644 index 275d7ff3..00000000 --- a/BeatTogether.DedicatedServer.Interface/Enums/GameplayState.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace BeatTogether.DedicatedServer.Interface.Enums -{ - public enum GameplayState : byte - { - None = 0, - SceneLoad = 1, - SongLoad = 2, - Gameplay = 3, - Results = 4 - } -} diff --git a/BeatTogether.DedicatedServer.Interface/Enums/InvitePolicy.cs b/BeatTogether.DedicatedServer.Interface/Enums/InvitePolicy.cs deleted file mode 100644 index 429dc2c3..00000000 --- a/BeatTogether.DedicatedServer.Interface/Enums/InvitePolicy.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace BeatTogether.DedicatedServer.Interface.Enums -{ - public enum InvitePolicy : byte - { - OnlyConnectionOwnerCanInvite = 0, - AnyoneCanInvite = 1 - } -} diff --git a/BeatTogether.DedicatedServer.Interface/Enums/MultiplayerGameState.cs b/BeatTogether.DedicatedServer.Interface/Enums/MultiplayerGameState.cs deleted file mode 100644 index 792b010b..00000000 --- a/BeatTogether.DedicatedServer.Interface/Enums/MultiplayerGameState.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace BeatTogether.DedicatedServer.Interface.Enums -{ - public enum MultiplayerGameState : byte - { - None = 0, - Lobby = 1, - Game = 2 - } -} diff --git a/BeatTogether.DedicatedServer.Interface/Enums/SongSelectionMode.cs b/BeatTogether.DedicatedServer.Interface/Enums/SongSelectionMode.cs deleted file mode 100644 index 532dc61b..00000000 --- a/BeatTogether.DedicatedServer.Interface/Enums/SongSelectionMode.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace BeatTogether.DedicatedServer.Interface.Enums -{ - public enum SongSelectionMode - { - Vote = 0, - Random = 1, - ManagerPicks = 2, - RandomPlayerPicks = 3, - ServerPicks = 4 - } -} diff --git a/BeatTogether.DedicatedServer.Interface/Events/MatchmakingServerStoppedEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/MatchmakingServerStoppedEvent.cs index a0b984f2..f0889094 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/MatchmakingServerStoppedEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/MatchmakingServerStoppedEvent.cs @@ -1,4 +1,5 @@ namespace BeatTogether.DedicatedServer.Interface.Events { - public sealed record MatchmakingServerStoppedEvent(string Secret); + public sealed record MatchmakingServerStoppedEvent( + string Secret); } diff --git a/BeatTogether.DedicatedServer.Interface/Events/NodeOnlineEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/NodeOnlineEvent.cs index d65d06a1..6c8a4b10 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/NodeOnlineEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/NodeOnlineEvent.cs @@ -1,6 +1,7 @@ -using System; - + namespace BeatTogether.DedicatedServer.Interface.Events { - public sealed record NodeOnlineEvent(string EndPoint, string NodeVersion); + public sealed record NodeOnlineEvent( + string EndPoint, + string NodeVersion); } \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Interface/Events/NodeReceivedPlayerEncryptionEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/NodeReceivedPlayerEncryptionEvent.cs deleted file mode 100644 index 09f2b5e8..00000000 --- a/BeatTogether.DedicatedServer.Interface/Events/NodeReceivedPlayerEncryptionEvent.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace BeatTogether.DedicatedServer.Interface.Events -{ - public sealed record NodeReceivedPlayerEncryptionEvent(string EndPoint, string PlayerEndPoint); -} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Interface/Events/NodeReceivedPlayerSessionDataEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/NodeReceivedPlayerSessionDataEvent.cs new file mode 100644 index 00000000..92696207 --- /dev/null +++ b/BeatTogether.DedicatedServer.Interface/Events/NodeReceivedPlayerSessionDataEvent.cs @@ -0,0 +1,6 @@ +namespace BeatTogether.DedicatedServer.Interface.Events +{ + public sealed record NodeReceivedPlayerSessionDataEvent( + string EndPoint, + string PlayerSessionId); +} \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Interface/Events/NodeStartedEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/NodeStartedEvent.cs index 58a41439..06f5501f 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/NodeStartedEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/NodeStartedEvent.cs @@ -1,6 +1,7 @@ -using System; - + namespace BeatTogether.DedicatedServer.Interface.Events { - public sealed record NodeStartedEvent(string EndPoint, string NodeVersion); + public sealed record NodeStartedEvent( + string EndPoint, + string NodeVersion); } \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Interface/Events/PlayerJoinEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/PlayerJoinEvent.cs index 9d687e13..4b406be6 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/PlayerJoinEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/PlayerJoinEvent.cs @@ -1,4 +1,7 @@ -namespace BeatTogether.DedicatedServer.Interface.Events + +namespace BeatTogether.DedicatedServer.Interface.Events { - public sealed record PlayerJoinEvent(string Secret, string EndPoint, string UserId); + public sealed record PlayerJoinEvent( + string Secret, + string HashedUserId); } diff --git a/BeatTogether.DedicatedServer.Interface/Events/PlayerLeaveServerEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/PlayerLeaveServerEvent.cs index b6d98e21..3baf7829 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/PlayerLeaveServerEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/PlayerLeaveServerEvent.cs @@ -1,6 +1,7 @@ -using System.Net; - + namespace BeatTogether.DedicatedServer.Interface.Events { - public sealed record PlayerLeaveServerEvent(string Secret, string UserId, string EndPoint); + public sealed record PlayerLeaveServerEvent( + string Secret, + string HashedUserId); } diff --git a/BeatTogether.DedicatedServer.Interface/Events/ServerInGameplayEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/ServerInGameplayEvent.cs index e314e29c..a644b50c 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/ServerInGameplayEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/ServerInGameplayEvent.cs @@ -1,9 +1,9 @@ - +using BeatTogether.Core.Enums; + namespace BeatTogether.DedicatedServer.Interface.Events { public sealed record ServerInGameplayEvent( string Secret, - bool InGame, - string LevelID + MultiplayerGameState MultiplayerGameState ); } diff --git a/BeatTogether.DedicatedServer.Interface/Events/UpdateInstanceConfigEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/UpdateInstanceConfigEvent.cs index a30a95e2..e470e960 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/UpdateInstanceConfigEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/UpdateInstanceConfigEvent.cs @@ -1,9 +1,7 @@ -using BeatTogether.DedicatedServer.Interface.Models; +using BeatTogether.Core.ServerMessaging.Models; namespace BeatTogether.DedicatedServer.Interface.Events { public sealed record UpdateInstanceConfigEvent( - string Secret, //Cannot change the secret - string ServerName, - GameplayServerConfiguration Configuration); + Server ServerInsance); } diff --git a/BeatTogether.DedicatedServer.Interface/Events/UpdatePlayersEvent.cs b/BeatTogether.DedicatedServer.Interface/Events/UpdatePlayersEvent.cs index a84d13aa..08d45ded 100644 --- a/BeatTogether.DedicatedServer.Interface/Events/UpdatePlayersEvent.cs +++ b/BeatTogether.DedicatedServer.Interface/Events/UpdatePlayersEvent.cs @@ -1,4 +1,6 @@ namespace BeatTogether.DedicatedServer.Interface.Events { - public sealed record UpdatePlayersEvent(string Secret, string[] Users); + public sealed record UpdatePlayersEvent( + string Secret, + string[] HashedUserIds); } diff --git a/BeatTogether.DedicatedServer.Interface/IMatchmakingService.cs b/BeatTogether.DedicatedServer.Interface/IMatchmakingService.cs index d5950f39..fa061a80 100644 --- a/BeatTogether.DedicatedServer.Interface/IMatchmakingService.cs +++ b/BeatTogether.DedicatedServer.Interface/IMatchmakingService.cs @@ -21,7 +21,7 @@ public override void Build(IServiceContractBuilder builder) => .AddEvent() .AddEvent() .AddEvent() - .AddEvent() + .AddEvent() .AddEvent() .AddEvent() .AddEvent(); diff --git a/BeatTogether.DedicatedServer.Interface/Models/GameplayServerConfiguration.cs b/BeatTogether.DedicatedServer.Interface/Models/GameplayServerConfiguration.cs deleted file mode 100644 index 6250cbc0..00000000 --- a/BeatTogether.DedicatedServer.Interface/Models/GameplayServerConfiguration.cs +++ /dev/null @@ -1,12 +0,0 @@ -using BeatTogether.DedicatedServer.Interface.Enums; - -namespace BeatTogether.DedicatedServer.Interface.Models -{ - public record GameplayServerConfiguration( - int MaxPlayerCount, - DiscoveryPolicy DiscoveryPolicy, - InvitePolicy InvitePolicy, - GameplayServerMode GameplayServerMode, - SongSelectionMode SongSelectionMode, - GameplayServerControlSettings GameplayServerControlSettings); -} diff --git a/BeatTogether.DedicatedServer.Interface/Requests/CreateMatchmakingServerRequest.cs b/BeatTogether.DedicatedServer.Interface/Requests/CreateMatchmakingServerRequest.cs index 95cd444e..57dd35b9 100644 --- a/BeatTogether.DedicatedServer.Interface/Requests/CreateMatchmakingServerRequest.cs +++ b/BeatTogether.DedicatedServer.Interface/Requests/CreateMatchmakingServerRequest.cs @@ -1,21 +1,7 @@ -using BeatTogether.DedicatedServer.Interface.Models; +using BeatTogether.Core.ServerMessaging.Models; namespace BeatTogether.DedicatedServer.Interface.Requests { public record CreateMatchmakingServerRequest( - string Secret, - string ManagerId, - GameplayServerConfiguration Configuration, - bool PermanentManager = true, - float Timeout = 10f, - string ServerName = "", - float ResultScreenTime = 20.0f, - float BeatmapStartTime = 5.0f, - float PlayersReadyCountdownTime = 0f, - bool AllowPerPlayerModifiers = false, - bool AllowPerPlayerDifficulties = false, - bool AllowChroma = true, - bool AllowME = true, - bool AllowNE = true - ); + Server Server); } diff --git a/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs b/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs index 84c7e0cc..20d2bc16 100644 --- a/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs +++ b/BeatTogether.DedicatedServer.Interface/Responses/CreateMatchmakingServerResponse.cs @@ -9,9 +9,7 @@ public enum CreateMatchmakingServerError public record CreateMatchmakingServerResponse( CreateMatchmakingServerError Error, - string RemoteEndPoint, - byte[] Random, - byte[] PublicKey) + string RemoteEndPoint) { public bool Success => Error == default; } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs index bf18e1de..957529a7 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IDedicatedInstance.cs @@ -2,8 +2,8 @@ using System.Net; using System.Threading; using System.Threading.Tasks; +using BeatTogether.Core.Enums; using BeatTogether.DedicatedServer.Kernel.Configuration; -using BeatTogether.DedicatedServer.Messaging.Enums; namespace BeatTogether.DedicatedServer.Kernel.Abstractions { @@ -24,7 +24,7 @@ public interface IDedicatedInstance public int Port { get; } MultiplayerGameState State { get; } - float NoPlayersTime { get; } + long NoPlayersTime { get; } IPlayerRegistry GetPlayerRegistry(); IServiceProvider GetServiceProvider(); diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs index 6e09c0c9..6a88398e 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayer.cs @@ -7,21 +7,21 @@ namespace BeatTogether.DedicatedServer.Kernel.Abstractions { - public interface IPlayer + public interface IPlayer : Core.Abstractions.IPlayer { EndPoint Endpoint { get; } IDedicatedInstance Instance { get; } byte ConnectionId { get; } byte RemoteConnectionId { get; } - string UserId { get; } + //string UserId { get; } string UserName { get; } - string PlayerSessionId { get; } + //string PlayerSessionId { get; } byte[]? Random { get; set; } byte[]? PublicEncryptionKey { get; set; } - string ClientVersion { get; set; } - Platform Platform { get; set; } - string PlatformUserId { get; set; } + //string ClientVersion { get; set; } + //Platform Platform { get; set; } + //string PlatformUserId { get; set; } uint ENetPeerId { get; set; } @@ -62,7 +62,7 @@ public interface IPlayer bool UpdateEntitlement { get; set; } public string MapHash { get; set; } - public Dictionary BeatmapDifficultiesRequirements{ get; set; } + public Dictionary BeatmapDifficultiesRequirements { get; set; } long TicksAtLastSyncStateDelta { get; set; } long TicksAtLastSyncState { get; set; } } diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs index 0b7a93b6..c69827b7 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs @@ -14,7 +14,8 @@ public interface IPlayerRegistry bool TryGetPlayer(string userId, [MaybeNullWhen(false)] out IPlayer player); int GetMillisBetweenSyncStatePackets(); - public void AddExtraPlayerSessionData(string playerSessionId, string ClientVersion, byte PlatformId, string PlayerPlatformUserId); - public bool RemoveExtraPlayerSessionData(string playerSessionId, out string ClientVersion, out byte Platform, out string PlayerPlatformUserId); + public void AddExtraPlayerSessionData(Core.Abstractions.IPlayer playerSessionData); + public bool RemoveExtraPlayerSessionDataAndApply(Core.Abstractions.IPlayer playerSessionData/*out string ClientVersion, out byte Platform, out string PlayerPlatformUserId*/); + public bool RemoveExtraPlayerSessionData(string playerSessionId/*out string ClientVersion, out byte Platform, out string PlayerPlatformUserId*/); } } diff --git a/BeatTogether.DedicatedServer.Kernel/BeatTogether.DedicatedServer.Kernel.csproj b/BeatTogether.DedicatedServer.Kernel/BeatTogether.DedicatedServer.Kernel.csproj index a7f9ea63..8f78936c 100644 --- a/BeatTogether.DedicatedServer.Kernel/BeatTogether.DedicatedServer.Kernel.csproj +++ b/BeatTogether.DedicatedServer.Kernel/BeatTogether.DedicatedServer.Kernel.csproj @@ -7,6 +7,7 @@ + diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetCountdownTimeHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetCountdownTimeHandler.cs index 34c473f1..521f4d42 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetCountdownTimeHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetCountdownTimeHandler.cs @@ -19,7 +19,7 @@ public SetCountdownTimeHandler(IPacketDispatcher packetDisapatcher, InstanceConf public override void Handle(IPlayer player, SetCountdown command) { - _Configuration.CountdownConfig.CountdownTimePlayersReady = command.Countdown; + _Configuration.CountdownConfig.CountdownTimePlayersReady = command.Countdown * 1000; _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Countdown time is now: " + command.Countdown diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetResultsTimeHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetResultsTimeHandler.cs index 0fb524db..0063f325 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetResultsTimeHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetResultsTimeHandler.cs @@ -19,7 +19,7 @@ public SetResultsTimeHandler(IPacketDispatcher packetDisapatcher, InstanceConfig public override void Handle(IPlayer player, SetResultsTime command) { - _Configuration.CountdownConfig.ResultsScreenTime = command.Countdown; + _Configuration.CountdownConfig.ResultsScreenTime = command.Countdown*1000; _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Results screen time is now: " + command.Countdown diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/StartBeatmapTimeHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/StartBeatmapTimeHandler.cs index 38d69d9e..d857b6dc 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/StartBeatmapTimeHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/StartBeatmapTimeHandler.cs @@ -19,7 +19,7 @@ public StartBeatmapTimeHandler(IPacketDispatcher packetDisapatcher, InstanceConf public override void Handle(IPlayer player, SetBeatmapStartTime command) { - _Configuration.CountdownConfig.BeatMapStartCountdownTime = command.Countdown; + _Configuration.CountdownConfig.BeatMapStartCountdownTime = command.Countdown*1000; _packetDisapatcher.SendToNearbyPlayers(new MpcTextChatPacket { Text = "Beatmap start time is now: " + command.Countdown diff --git a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs index 2ba9300f..60aa612b 100644 --- a/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs +++ b/BeatTogether.DedicatedServer.Kernel/Configuration/InstanceConfiguration.cs @@ -1,27 +1,29 @@ -using BeatTogether.DedicatedServer.Kernel.Enums; +using BeatTogether.Core.Enums; +using BeatTogether.Core.Models; namespace BeatTogether.DedicatedServer.Kernel.Configuration { public sealed class InstanceConfiguration { - //public int LiteNetPort { get; set; } public int Port { get; set; } public string Secret { get; set; } = string.Empty; + public string Code { get; set; } = string.Empty; public string ServerOwnerId { get; set; } = string.Empty; public string ServerId { get; set; } = "ziuMSceapEuNN7wRGQXrZg"; public string WelcomeMessage { get; set; } = string.Empty; public string ServerName { get; set; } = string.Empty; - public float DestroyInstanceTimeout { get; set; } = 10f; //set to -1 for no timeout(must close using api), 0 would be for instant close, 10 seconds is default. Less than 6 seconds can cause cfr-3 issues + public long DestroyInstanceTimeout { get; set; } = 10000L; //set to -1 for no timeout(must close using api), 0 would be for instant close, 10 seconds is default. Less than 6 seconds can cause cfr-3 issues public string SetConstantManagerFromUserId { get; set; } = string.Empty; //If a user creates a server using the api and enteres there userId (eg uses discord bot with linked account)) public bool AllowPerPlayerDifficulties { get; set; } = false; public bool AllowPerPlayerModifiers { get; set; } = false; public CountdownConfig CountdownConfig { get; set; } = new(); - public int MaxPlayerCount { get; set; } - public DiscoveryPolicy DiscoveryPolicy { get; set; } - public InvitePolicy InvitePolicy { get; set; } - public GameplayServerMode GameplayServerMode { get; set; } - public SongSelectionMode SongSelectionMode { get; set; } - public GameplayServerControlSettings GameplayServerControlSettings { get; set; } + + public GameplayServerConfiguration GameplayServerConfiguration { get; set; } = new(); + + public BeatmapDifficultyMask BeatmapDifficultyMask { get; set; } + public GameplayModifiersMask GameplayModifiersMask { get; set; } + public string SongPacksMask { get; set; } = string.Empty; + public bool AllowChroma { get; set; } public bool AllowMappingExtensions { get; set; } public bool AllowNoodleExtensions { get; set; } @@ -38,6 +40,6 @@ public sealed class CountdownConfig { public long CountdownTimePlayersReady { get; set; } = 30000L; public long BeatMapStartCountdownTime { get; set; } = 5000L; - public float ResultsScreenTime { get; set; } = 20.0f; + public long ResultsScreenTime { get; set; } = 20000L; } } diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index 34de97c3..df450ed9 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -7,7 +7,6 @@ using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Kernel.ENet; -using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Extensions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; @@ -20,6 +19,7 @@ using Serilog; using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using Microsoft.Extensions.DependencyInjection; +using BeatTogether.Core.Enums; namespace BeatTogether.DedicatedServer.Kernel { @@ -35,7 +35,7 @@ public sealed class DedicatedInstance : ENetServer, IDedicatedInstance public int Port => _configuration.Port; public bool IsRunning => IsAlive; public long RunTime => (DateTime.UtcNow.Ticks - _startTime) / 10000L; - public float NoPlayersTime { get; private set; } = -1; //tracks the instance time once there are 0 players in the lobby + public long NoPlayersTime { get; private set; } = -1; //tracks the instance time once there are 0 players in the lobby public MultiplayerGameState State { get; private set; } = MultiplayerGameState.Lobby; public event Action StopEvent = null!; @@ -62,7 +62,6 @@ public sealed class DedicatedInstance : ENetServer, IDedicatedInstance private CancellationTokenSource? _waitForPlayerCts = null; private CancellationTokenSource? _stopServerCts; - public DedicatedInstance( InstanceConfiguration configuration, IPlayerRegistry playerRegistry, @@ -105,13 +104,14 @@ public async Task Start(CancellationToken cancellationToken = default) $"Endpoint={EndPoint}," + $"ServerName='{_configuration.ServerName}', " + $"Secret='{_configuration.Secret}', " + + $"Code='{_configuration.Code}', " + $"ManagerId='{_configuration.ServerOwnerId}', " + - $"MaxPlayerCount={_configuration.MaxPlayerCount}, " + - $"DiscoveryPolicy={_configuration.DiscoveryPolicy}, " + - $"InvitePolicy={_configuration.InvitePolicy}, " + - $"GameplayServerMode={_configuration.GameplayServerMode}, " + - $"SongSelectionMode={_configuration.SongSelectionMode}, " + - $"GameplayServerControlSettings={_configuration.GameplayServerControlSettings})" + $"MaxPlayerCount={_configuration.GameplayServerConfiguration.MaxPlayerCount}, " + + $"DiscoveryPolicy={_configuration.GameplayServerConfiguration.DiscoveryPolicy}, " + + $"InvitePolicy={_configuration.GameplayServerConfiguration.InvitePolicy}, " + + $"GameplayServerMode={_configuration.GameplayServerConfiguration.GameplayServerMode}, " + + $"SongSelectionMode={_configuration.GameplayServerConfiguration.SongSelectionMode}, " + + $"GameplayServerControlSettings={_configuration.GameplayServerConfiguration.GameplayServerControlSettings})" ); _stopServerCts = new CancellationTokenSource(); @@ -119,7 +119,7 @@ public async Task Start(CancellationToken cancellationToken = default) { _waitForPlayerCts = new CancellationTokenSource(); - var waitTimeLimit = (WaitForPlayerTimeLimit + (int)(_configuration.DestroyInstanceTimeout * 1000)); + var waitTimeLimit = (int)(WaitForPlayerTimeLimit + _configuration.DestroyInstanceTimeout); _ = Task.Delay(waitTimeLimit, _waitForPlayerCts.Token) .ContinueWith(t => @@ -149,16 +149,17 @@ public async Task Stop(CancellationToken cancellationToken = default) _logger.Information( "Stopping dedicated server " + - $"(Port={Port}," + + $"(Port={Port}, " + $"ServerName='{_configuration.ServerName}', " + $"Secret='{_configuration.Secret}', " + + $"Code='{_configuration.Code}', " + $"ManagerId='{_configuration.ServerOwnerId}', " + - $"MaxPlayerCount={_configuration.MaxPlayerCount}, " + - $"DiscoveryPolicy={_configuration.DiscoveryPolicy}, " + - $"InvitePolicy={_configuration.InvitePolicy}, " + - $"GameplayServerMode={_configuration.GameplayServerMode}, " + - $"SongSelectionMode={_configuration.SongSelectionMode}, " + - $"GameplayServerControlSettings={_configuration.GameplayServerControlSettings})." + $"MaxPlayerCount={_configuration.GameplayServerConfiguration.MaxPlayerCount}, " + + $"DiscoveryPolicy={_configuration.GameplayServerConfiguration.DiscoveryPolicy}, " + + $"InvitePolicy={_configuration.GameplayServerConfiguration.InvitePolicy}, " + + $"GameplayServerMode={_configuration.GameplayServerConfiguration.GameplayServerMode}, " + + $"SongSelectionMode={_configuration.GameplayServerConfiguration.SongSelectionMode}, " + + $"GameplayServerControlSettings={_configuration.GameplayServerConfiguration.GameplayServerControlSettings})." ); ServerStateHash.WriteToBitMask("terminating"); PacketDispatcher.SendToNearbyPlayers(new INetSerializable[]{ @@ -188,7 +189,7 @@ public int GetNextSortIndex() return sortIndex; _lastSortIndex++; - if (_lastSortIndex > _configuration.MaxPlayerCount) + if (_lastSortIndex > _configuration.GameplayServerConfiguration.MaxPlayerCount) { return 0; } @@ -248,7 +249,7 @@ public void SetState(MultiplayerGameState state) goto EndOfTryAccept; } - _logger.Debug( + _logger.Information( "Handling connection request though Enet" + $"(RemoteEndPoint='{endPoint}', " + $"PlayerSessionId='{connectionRequestData.PlayerSessionId}', " + @@ -269,7 +270,7 @@ public void SetState(MultiplayerGameState state) PlayerNoJoin = true; goto EndOfTryAccept; } - if (_playerRegistry.GetPlayerCount() >= _configuration.MaxPlayerCount) + if (_playerRegistry.GetPlayerCount() >= _configuration.GameplayServerConfiguration.MaxPlayerCount) { _logger.Warning("Master server sent a player to a full server"); PlayerNoJoin = true; @@ -305,7 +306,7 @@ public void SetState(MultiplayerGameState state) if (_configuration.ServerName == string.Empty) { - _logger.Information("About to update servers name" + _configuration.ServerName); + //_logger.Information("About to update servers name" + _configuration.ServerName); _configuration.ServerName = player.UserName + "'s server"; InstanceConfigUpdated(); _logger.Information("Updated servers name to: " + _configuration.ServerName); @@ -315,7 +316,7 @@ public void SetState(MultiplayerGameState state) $"(RemoteEndPoint='{player.Endpoint}', " + $"ConnectionId={player.ConnectionId}, " + $"PlayerSessionId='{player.PlayerSessionId}', " + - $"UserId='{player.UserId}', " + + $"UserId='{player.HashedUserId}', " + $"UserName='{player.UserName}', " + $"SortIndex={player.SortIndex})." ); @@ -323,20 +324,23 @@ public void SetState(MultiplayerGameState state) if (_waitForPlayerCts != null) _waitForPlayerCts.Cancel(); - if (GetPlayerRegistry().RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out var ClientVer, out var Platform, out var PlayerPlatformUserId)) + //UserID, UserName, and session + _logger.Information("Applying session data recv from master"); + if (GetPlayerRegistry().RemoveExtraPlayerSessionDataAndApply(player)) { - player.ClientVersion = ClientVer; - player.Platform = (Enums.Platform)Platform; - player.PlatformUserId = PlayerPlatformUserId; + _logger.Information("Successfull session data extraction"); } + _logger.Information("Client ver: " + player.PlayerClientVersion.ToString()); + _logger.Information("Client platform: " + player.PlayerPlatform.ToString()); + _logger.Information("Client PlatformUserId: " + player.PlatformUserId); return player; EndOfTryAccept: if (PlayerNoJoin) { - GetPlayerRegistry().RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId, out _, out _, out _); - string[] Players = _playerRegistry.Players.Select(p => p.UserId).ToArray(); + GetPlayerRegistry().RemoveExtraPlayerSessionData(connectionRequestData.PlayerSessionId); + string[] Players = _playerRegistry.Players.Select(p => p.HashedUserId).ToArray(); PlayerDisconnectBeforeJoining?.Invoke(_configuration.Secret, endPoint, Players); return null; } @@ -367,13 +371,13 @@ public override void OnConnect(EndPoint endPoint) new PlayerConnectedPacket { RemoteConnectionId = player.ConnectionId, - UserId = player.UserId, + UserId = player.HashedUserId, UserName = player.UserName, IsConnectionOwner = false }, new PlayerSortOrderPacket { - UserId = player.UserId, + UserId = player.HashedUserId, SortIndex = player.SortIndex }, new MpNodePoseSyncStatePacket @@ -392,7 +396,7 @@ public override void OnConnect(EndPoint endPoint) }, new PlayerSortOrderPacket { - UserId = player.UserId, + UserId = player.HashedUserId, SortIndex = player.SortIndex }, new PlayerConnectedPacket @@ -403,12 +407,12 @@ public override void OnConnect(EndPoint endPoint) IsConnectionOwner = true }, new PlayerStatePacket - { - PlayerState = ServerStateHash - }, + { + PlayerState = ServerStateHash + }, new SetIsStartButtonEnabledPacket// Disables start button if they are server owner without selected song { - Reason = player.UserId == _configuration.ServerOwnerId ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None + Reason = player.HashedUserId == _configuration.ServerOwnerId ? CannotStartGameReason.NoSongSelected : CannotStartGameReason.None }, new MpNodePoseSyncStatePacket { @@ -428,13 +432,13 @@ public override void OnConnect(EndPoint endPoint) MakeBigPacketToSendToPlayer.Add(new PlayerConnectedPacket { RemoteConnectionId = p.ConnectionId, - UserId = p.UserId, + UserId = p.HashedUserId, UserName = p.UserName, IsConnectionOwner = false }); MakeBigPacketToSendToPlayer.Add(new PlayerSortOrderPacket { - UserId = p.UserId, + UserId = p.HashedUserId, SortIndex = p.SortIndex }); } @@ -448,6 +452,7 @@ public override void OnConnect(EndPoint endPoint) INetSerializable[] SendToPlayerFromPlayers = new INetSerializable[2]; SendToPlayerFromPlayers[0] = new PlayerIdentityPacket(); SendToPlayerFromPlayers[1] = new MpPlayerData(); + //TODO send selected modifiers if they have any, selected beatmap and custom bm packet. foreach (IPlayer p in _playerRegistry.Players) { @@ -459,8 +464,8 @@ public override void OnConnect(EndPoint endPoint) ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).Random = new ByteArray { Data = p.Random }; ((PlayerIdentityPacket)SendToPlayerFromPlayers[0]).PublicEncryptionKey = new ByteArray { Data = p.PublicEncryptionKey }; ((MpPlayerData)SendToPlayerFromPlayers[1]).PlatformID = p.PlatformUserId; - ((MpPlayerData)SendToPlayerFromPlayers[1]).Platform = p.Platform.Convert(); - ((MpPlayerData)SendToPlayerFromPlayers[1]).ClientVersion = p.ClientVersion; + ((MpPlayerData)SendToPlayerFromPlayers[1]).Platform = p.PlayerPlatform.Convert(); + ((MpPlayerData)SendToPlayerFromPlayers[1]).ClientVersion = p.PlayerClientVersion.ToString(); // Send all player avatars and states to just joined player PacketDispatcher.SendFromPlayerToPlayer(p, player, SendToPlayerFromPlayers, IgnoranceChannelTypes.Reliable); @@ -468,16 +473,16 @@ public override void OnConnect(EndPoint endPoint) } // Update permissions - if ((_configuration.SetConstantManagerFromUserId == player.UserId || _playerRegistry.GetPlayerCount() == 1) && _configuration.GameplayServerMode == GameplayServerMode.Managed) + if ((_configuration.SetConstantManagerFromUserId == player.HashedUserId || _playerRegistry.GetPlayerCount() == 1) && _configuration.GameplayServerConfiguration.GameplayServerMode == Core.Enums.GameplayServerMode.Managed) SetNewServerOwner(player); - if (player.Platform == Enums.Platform.Test) //If the player is a bot, send permissions. Normal players request this in a packet when they join + if (player.PlayerPlatform == Core.Enums.Platform.Test) //If the player is a bot, send permissions. Normal players request this in a packet when they join { bool HasManager = (_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var ServerOwner) && !player.IsServerOwner); PlayerPermissionConfiguration[] playerPermissionConfigurations = new PlayerPermissionConfiguration[HasManager ? 2 : 1]; playerPermissionConfigurations[0] = new PlayerPermissionConfiguration { - UserId = player.UserId, + UserId = player.HashedUserId, IsServerOwner = player.IsServerOwner, HasRecommendBeatmapsPermission = player.CanRecommendBeatmaps, HasRecommendGameplayModifiersPermission = player.CanRecommendModifiers, @@ -487,7 +492,7 @@ public override void OnConnect(EndPoint endPoint) if (HasManager) playerPermissionConfigurations[1] = new PlayerPermissionConfiguration { - UserId = ServerOwner!.UserId, + UserId = ServerOwner!.HashedUserId, IsServerOwner = ServerOwner!.IsServerOwner, HasRecommendBeatmapsPermission = ServerOwner!.CanRecommendBeatmaps, HasRecommendGameplayModifiersPermission = ServerOwner!.CanRecommendModifiers, @@ -511,17 +516,18 @@ public override void OnConnect(EndPoint endPoint) PacketDispatcher.SendFromPlayerToPlayer(player, p, new MpPlayerData { PlatformID = player.PlatformUserId!, - Platform = player.Platform.Convert(), - ClientVersion = player.ClientVersion! + Platform = player.PlayerPlatform.Convert(), + ClientVersion = player.PlayerClientVersion.ToString()! }, IgnoranceChannelTypes.Reliable); } } PacketDispatcher.SendToNearbyPlayers(new MpcTextChatPacket { - Text = player.UserName + " Joined, Platform: " + player.Platform.ToString() + " Version: " + player.ClientVersion + Text = player.UserName + " Joined, Platform: " + player.PlayerPlatform.ToString() + " Version: " + player.PlayerClientVersion.ToString() }, IgnoranceChannelTypes.Reliable); + _logger.Information($"Sent connection data though for (RemoteEndPoint='{endPoint}')"); } public void DisconnectPlayer(IPlayer player) @@ -560,7 +566,7 @@ public override void OnDisconnect(EndPoint endPoint) if(_playerRegistry.GetPlayerCount() != 0) { - if (player.IsServerOwner && _configuration.GameplayServerMode == GameplayServerMode.Managed) + if (player.IsServerOwner && _configuration.GameplayServerConfiguration.GameplayServerMode == Core.Enums.GameplayServerMode.Managed) { // Update permissions SetNewServerOwner(_playerRegistry.Players[0]); @@ -577,7 +583,7 @@ public override void OnDisconnect(EndPoint endPoint) if (_configuration.DestroyInstanceTimeout != -1) { _waitForPlayerCts = new CancellationTokenSource(); - _ = Task.Delay((int)(_configuration.DestroyInstanceTimeout * 1000), _waitForPlayerCts.Token).ContinueWith(t => + _ = Task.Delay((int)(_configuration.DestroyInstanceTimeout), _waitForPlayerCts.Token).ContinueWith(t => { if (!t.IsCanceled && _playerRegistry.GetPlayerCount() == 0) { @@ -601,7 +607,7 @@ private void SetNewServerOwner(IPlayer NewOwner) { if (_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var OldOwner)) { - _configuration.ServerOwnerId = NewOwner.UserId; + _configuration.ServerOwnerId = NewOwner.HashedUserId; PacketDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket { PermissionConfiguration = new PlayersPermissionConfiguration @@ -610,7 +616,7 @@ private void SetNewServerOwner(IPlayer NewOwner) { new PlayerPermissionConfiguration() { - UserId = OldOwner.UserId, + UserId = OldOwner.HashedUserId, IsServerOwner = OldOwner.IsServerOwner, HasRecommendBeatmapsPermission = OldOwner.CanRecommendBeatmaps, HasRecommendGameplayModifiersPermission = OldOwner.CanRecommendModifiers, @@ -619,7 +625,7 @@ private void SetNewServerOwner(IPlayer NewOwner) }, new PlayerPermissionConfiguration() { - UserId = NewOwner.UserId, + UserId = NewOwner.HashedUserId, IsServerOwner = NewOwner.IsServerOwner, HasRecommendBeatmapsPermission = NewOwner.CanRecommendBeatmaps, HasRecommendGameplayModifiersPermission = NewOwner.CanRecommendModifiers, @@ -636,7 +642,7 @@ private void SetNewServerOwner(IPlayer NewOwner) } else { - _configuration.ServerOwnerId = NewOwner.UserId; + _configuration.ServerOwnerId = NewOwner.HashedUserId; PacketDispatcher.SendToNearbyPlayers(new SetPlayersPermissionConfigurationPacket { PermissionConfiguration = new PlayersPermissionConfiguration @@ -645,7 +651,7 @@ private void SetNewServerOwner(IPlayer NewOwner) { new PlayerPermissionConfiguration() { - UserId = NewOwner.UserId, + UserId = NewOwner.HashedUserId, IsServerOwner = NewOwner.IsServerOwner, HasRecommendBeatmapsPermission = NewOwner.CanRecommendBeatmaps, HasRecommendGameplayModifiersPermission = NewOwner.CanRecommendModifiers, diff --git a/BeatTogether.DedicatedServer.Kernel/Enums/CountdownState.cs b/BeatTogether.DedicatedServer.Kernel/Enums/CountdownState.cs deleted file mode 100644 index 5ffa7571..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Enums/CountdownState.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace BeatTogether.DedicatedServer.Kernel.Enums -{ - public enum CountdownState : byte - { - NotCountingDown = 0, - CountingDown = 1, - StartBeatmapCountdown = 2, - WaitingForEntitlement = 3 - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Enums/DiscoveryPolicy.cs b/BeatTogether.DedicatedServer.Kernel/Enums/DiscoveryPolicy.cs deleted file mode 100644 index 59339aff..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Enums/DiscoveryPolicy.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace BeatTogether.DedicatedServer.Kernel.Enums -{ - public enum DiscoveryPolicy : byte - { - Hidden = 0, - WithCode = 1, - Public = 2 - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Enums/GameplayServerControlSettings.cs b/BeatTogether.DedicatedServer.Kernel/Enums/GameplayServerControlSettings.cs deleted file mode 100644 index 797c68bf..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Enums/GameplayServerControlSettings.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace BeatTogether.DedicatedServer.Kernel.Enums -{ - [Flags] - public enum GameplayServerControlSettings - { - None = 0, - AllowModifierSelection = 1, - AllowSpectate = 2, - All = 3 - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Enums/GameplayServerMode.cs b/BeatTogether.DedicatedServer.Kernel/Enums/GameplayServerMode.cs deleted file mode 100644 index 74eaed61..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Enums/GameplayServerMode.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace BeatTogether.DedicatedServer.Kernel.Enums -{ - public enum GameplayServerMode - { - Countdown = 0, - Managed = 1, - QuickStartOneSong = 2, - Tournament = 3 - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Enums/InvitePolicy.cs b/BeatTogether.DedicatedServer.Kernel/Enums/InvitePolicy.cs deleted file mode 100644 index 2439c019..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Enums/InvitePolicy.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace BeatTogether.DedicatedServer.Kernel.Enums -{ - public enum InvitePolicy : byte - { - OnlyConnectionOwnerCanInvite = 0, - AnyoneCanInvite = 1 - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Enums/Platform.cs b/BeatTogether.DedicatedServer.Kernel/Enums/Platform.cs deleted file mode 100644 index f5fc4aa3..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Enums/Platform.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace BeatTogether.DedicatedServer.Kernel.Enums -{ - public enum Platform : byte - { - Test, - OculusRift, - OculusQuest, - Steam, - PS4, - PS4Dev, - PS4Cert, - Oculus = 1 - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Enums/SongSelectionMode.cs b/BeatTogether.DedicatedServer.Kernel/Enums/SongSelectionMode.cs deleted file mode 100644 index 7781431e..00000000 --- a/BeatTogether.DedicatedServer.Kernel/Enums/SongSelectionMode.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace BeatTogether.DedicatedServer.Kernel.Enums -{ - public enum SongSelectionMode - { - Vote = 0, - Random = 1, - ServerOwnerPicks = 2, - RandomPlayerPicks = 3, - ServerPicks = 4 - } -} diff --git a/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs b/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs index b1022423..4c9b870d 100644 --- a/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs +++ b/BeatTogether.DedicatedServer.Kernel/Extensions/GamePlatformToMpCorePlatform.cs @@ -4,15 +4,15 @@ namespace BeatTogether.DedicatedServer.Kernel.Extensions { public static class GamePlatformToMpCorePlatform { - public static Platform Convert(this Enums.Platform gamePlatform) + public static Platform Convert(this Core.Enums.Platform gamePlatform) { return gamePlatform switch { - Enums.Platform.Test => Platform.Unknown, - Enums.Platform.OculusRift => Platform.OculusPC, - Enums.Platform.OculusQuest => Platform.OculusQuest, - Enums.Platform.Steam => Platform.Steam, - Enums.Platform.PS4 or Enums.Platform.PS4Dev or Enums.Platform.PS4Cert => Platform.PS4, + Core.Enums.Platform.Test => Platform.Unknown, + Core.Enums.Platform.OculusRift => Platform.OculusPC, + Core.Enums.Platform.OculusQuest => Platform.OculusQuest, + Core.Enums.Platform.Steam => Platform.Steam, + Core.Enums.Platform.PS4 or Core.Enums.Platform.PS4Dev or Core.Enums.Platform.PS4Cert => Platform.PS4, _ => 0, }; } diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs index 14b9105e..4d60a0c2 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/Abstractions/ILobbyManager.cs @@ -1,5 +1,5 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Enums; +using BeatTogether.Core.Enums; +using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; using System.Collections.Generic; diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs index 028bde36..cbfdcea6 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/GameplayManager.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.Core.Enums; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; @@ -103,7 +104,7 @@ public async void StartSong(CancellationToken cancellationToken) { if (player.WantsToPlayNextLevel && !player.IsSpectating && !player.IsBackgrounded && !player.ForceLateJoin) { - PlayersAtStart.Add(player.UserId); + PlayersAtStart.Add(player.HashedUserId); } //if (!player.IsSpectating && !player.ForceLateJoin && !player.IsBackgrounded) // PlayersAtStart.Add(player.UserId); @@ -198,8 +199,8 @@ public async void StartSong(CancellationToken cancellationToken) State = GameplayManagerState.Results; - if (_levelCompletionResults.Values.Any(result => result.LevelEndStateType == LevelEndStateType.Cleared) && _instance._configuration.CountdownConfig.ResultsScreenTime > 0) - await Task.Delay((int)(_instance._configuration.CountdownConfig.ResultsScreenTime * 1000), cancellationToken); + if (_levelCompletionResults.Values.Any(result => result.LevelEndStateType == LevelEndStateType.Cleared) && _instance._configuration.CountdownConfig.ResultsScreenTime != 0) + await Task.Delay((int)_instance._configuration.CountdownConfig.ResultsScreenTime, cancellationToken); // End gameplay and reset SetBeatmap(null, new()); @@ -223,17 +224,17 @@ private void ResetValues() public void HandleGameSceneLoaded(IPlayer player, SetGameplaySceneReadyPacket packet) { - if (State == GameplayManagerState.SceneLoad && _sceneReadyTcs.TryGetValue(player.UserId, out var tcs) && !tcs.Task.IsCompleted) + if (State == GameplayManagerState.SceneLoad && _sceneReadyTcs.TryGetValue(player.HashedUserId, out var tcs) && !tcs.Task.IsCompleted) { - _playerSpecificSettings[player.UserId] = packet.PlayerSpecificSettings; - PlayerSceneReady(player.UserId); + _playerSpecificSettings[player.HashedUserId] = packet.PlayerSpecificSettings; + PlayerSceneReady(player.HashedUserId); return; } if (_instance.State != MultiplayerGameState.Game || State == GameplayManagerState.Results || State == GameplayManagerState.None) //Returns player to lobby { _packetDispatcher.SendToPlayer(player, new ReturnToMenuPacket(), IgnoranceChannelTypes.Reliable); - LeaveGameplay(player.UserId); + LeaveGameplay(player.HashedUserId); return; } @@ -241,7 +242,7 @@ public void HandleGameSceneLoaded(IPlayer player, SetGameplaySceneReadyPacket pa { _packetDispatcher.SendToNearbyPlayers(new SetPlayerDidConnectLatePacket { - UserId = player.UserId, + UserId = player.HashedUserId, PlayersAtStart = new PlayerSpecificSettingsAtStart { ActivePlayerSpecificSettingsAtStart = _playerSpecificSettings.Values.ToArray() @@ -254,9 +255,9 @@ public void HandleGameSceneLoaded(IPlayer player, SetGameplaySceneReadyPacket pa public void HandleGameSongLoaded(IPlayer player) { - if (State == GameplayManagerState.SongLoad && _songReadyTcs.TryGetValue(player.UserId, out var tcs) && !tcs.Task.IsCompleted) + if (State == GameplayManagerState.SongLoad && _songReadyTcs.TryGetValue(player.HashedUserId, out var tcs) && !tcs.Task.IsCompleted) { - PlayerSongReady(player.UserId); + PlayerSongReady(player.HashedUserId); return; } if (_instance.State != MultiplayerGameState.Game || State == GameplayManagerState.Results || State == GameplayManagerState.None) //Player is sent back to lobby @@ -275,10 +276,10 @@ public void HandleGameSongLoaded(IPlayer player) public void HandleLevelFinished(IPlayer player, LevelFinishedPacket packet) { - if (_levelFinishedTcs.TryGetValue(player.UserId, out var tcs) && tcs.Task.IsCompleted) + if (_levelFinishedTcs.TryGetValue(player.HashedUserId, out var tcs) && tcs.Task.IsCompleted) return; - _levelCompletionResults[player.UserId] = packet.Results.LevelCompletionResults; - PlayerFinishLevel(player.UserId); + _levelCompletionResults[player.HashedUserId] = packet.Results.LevelCompletionResults; + PlayerFinishLevel(player.HashedUserId); } public void SignalRequestReturnToMenu() @@ -290,7 +291,7 @@ public void SignalRequestReturnToMenu() //will set players tasks as done if they leave gameplay due to disconnect or returning to the menu public void HandlePlayerLeaveGameplay(IPlayer player) { - LeaveGameplay(player.UserId); + LeaveGameplay(player.HashedUserId); } private void LeaveGameplay(string UserId) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 9d4e3d1f..c30e5b5d 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -3,10 +3,10 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using BeatTogether.Core.Enums; using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; -using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Models; @@ -43,7 +43,7 @@ public sealed class LobbyManager : ILobbyManager, IDisposable private BeatmapIdentifier? _lastBeatmap = null; private bool _lastSpectatorState; private bool _LastCanEveryonePlayBeatmap; - private string _lastManagerId = null!; + //private string _lastManagerId = null!; private readonly CancellationTokenSource _stopCts = new(); private const int LoopTime = 100; public GameplayModifiers EmptyModifiers { get; } = new(); @@ -151,14 +151,14 @@ public void Update() if (_instance.State != MultiplayerGameState.Lobby) return; - if (!_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var serverOwner) && _configuration.SongSelectionMode == SongSelectionMode.ServerOwnerPicks) + if (!_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var serverOwner) && _configuration.GameplayServerConfiguration.SongSelectionMode == SongSelectionMode.ManagerPicks) return; UpdateBeatmap(GetSelectedBeatmap(), GetSelectedModifiers()); UpdatePlayersMissingEntitlementsMessages(); - if (_configuration.SongSelectionMode == SongSelectionMode.ServerOwnerPicks) + if (_configuration.GameplayServerConfiguration.SongSelectionMode == SongSelectionMode.ManagerPicks) { if (_lastBeatmap != SelectedBeatmap || _LastCanEveryonePlayBeatmap != CanEveryonePlayBeatmap || _lastSpectatorState != AllPlayersNotWantToPlayNextLevel) { @@ -169,9 +169,9 @@ public void Update() } } - switch (_configuration.SongSelectionMode) //server modes + switch (_configuration.GameplayServerConfiguration.SongSelectionMode) //server modes { - case SongSelectionMode.ServerOwnerPicks: + case SongSelectionMode.ManagerPicks: CountingDown(serverOwner!.IsReady, !serverOwner.IsReady || AllPlayersNotWantToPlayNextLevel || !CanEveryonePlayBeatmap); break; case SongSelectionMode.Vote: @@ -186,7 +186,7 @@ public void Update() } _LastCanEveryonePlayBeatmap = CanEveryonePlayBeatmap; - _lastManagerId = _configuration.ServerOwnerId; + //_lastManagerId = _configuration.ServerOwnerId; _lastSpectatorState = AllPlayersNotWantToPlayNextLevel; _lastBeatmap = SelectedBeatmap; } @@ -262,7 +262,7 @@ private void UpdateBeatmap(BeatmapIdentifier? beatmap, GameplayModifiers modifie _packetDispatcher.SendToNearbyPlayers(new SetSelectedBeatmap() { Beatmap = SelectedBeatmap - }, IgnoranceChannelTypes.Reliable); + }, IgnoranceChannelTypes.Reliable); //TODO send custom mp packet details else _packetDispatcher.SendToNearbyPlayers(new ClearSelectedBeatmap(), IgnoranceChannelTypes.Reliable); } @@ -292,7 +292,7 @@ private void UpdatePlayersMissingEntitlementsMessages() { PlayersWithoutEntitlements = _playerRegistry.Players .Where(p => (p.GetEntitlement(player.BeatmapIdentifier.LevelId) is EntitlementStatus.NotOwned) && !p.IsSpectating && p.WantsToPlayNextLevel && !p.IsBackgrounded) - .Select(p => p.UserId).ToArray() + .Select(p => p.HashedUserId).ToArray() }, IgnoranceChannelTypes.Reliable); //_logger.Debug("Sent missing entitlement packet"); } @@ -413,6 +413,7 @@ private void CancelCountdown() private bool PlayerMapCheck(IPlayer p) { + if(p.BeatmapIdentifier == null) return false; //If no map hash then treat as base game map for compat reasons and while waiting for a packet var Passed = string.IsNullOrEmpty(p.MapHash); //If not passed, then we have difficulties, and if we have the diff we are looking for, then we can check it for requirements. @@ -423,9 +424,9 @@ private bool PlayerMapCheck(IPlayer p) private BeatmapIdentifier? GetSelectedBeatmap() { - switch(_configuration.SongSelectionMode) + switch(_configuration.GameplayServerConfiguration.SongSelectionMode) { - case SongSelectionMode.ServerOwnerPicks: + case SongSelectionMode.ManagerPicks: { if (_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var p) && p.BeatmapIdentifier != null) { @@ -463,7 +464,7 @@ private bool PlayerMapCheck(IPlayer p) { Random rand = new(); int selectedPlayer = rand.Next(_playerRegistry.GetPlayerCount() - 1); - RandomlyPickedPlayer = _playerRegistry.Players[selectedPlayer].UserId; + RandomlyPickedPlayer = _playerRegistry.Players[selectedPlayer].HashedUserId; return PlayerMapCheck(_playerRegistry.Players[selectedPlayer]) ? _playerRegistry.Players[selectedPlayer].BeatmapIdentifier : null; } return SelectedBeatmap; @@ -478,9 +479,9 @@ private bool PlayerMapCheck(IPlayer p) private GameplayModifiers GetSelectedModifiers() { - switch(_configuration.SongSelectionMode) + switch(_configuration.GameplayServerConfiguration.SongSelectionMode) { - case SongSelectionMode.ServerOwnerPicks: + case SongSelectionMode.ManagerPicks: if(_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var ServerOwner)) return ServerOwner.Modifiers; return EmptyModifiers; diff --git a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs index 3c69f147..5f2d3c30 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketDispatcher.cs @@ -31,7 +31,7 @@ public PacketDispatcher( private void SendInternal(IPlayer player, ref SpanBuffer writer, IgnoranceChannelTypes deliveryMethod) { - _logger.Verbose($"Sending packet (SenderId={ServerId}) to player {player.ConnectionId} with UserId {player.UserId}"); + _logger.Verbose($"Sending packet (SenderId={ServerId}) to player {player.ConnectionId} with UserId {player.HashedUserId}"); _serverInstance.Send(player, writer.Data, deliveryMethod); } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs index 009f4872..b15f7e66 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetCountdownEndTimePacketHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.Core.Enums; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; @@ -26,7 +27,7 @@ public override void Handle(IPlayer sender, GetCountdownEndTimePacket packet) $"Handling packet of type '{nameof(GetCountdownEndTimePacket)}' " + $"(SenderId={sender.ConnectionId} CountdownTime={_lobbyManager.CountdownEndTime})." ); - if(_lobbyManager.CountDownState == Enums.CountdownState.CountingDown) + if(_lobbyManager.CountDownState == CountdownState.CountingDown) _packetDispatcher.SendToPlayer(sender, new SetCountdownEndTimePacket { CountdownTime = _lobbyManager.CountdownEndTime diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsInLobbyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsInLobbyPacketHandler.cs index 0412283d..0ce108bf 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsInLobbyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetIsInLobbyPacketHandler.cs @@ -1,7 +1,7 @@ -using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.Core.Enums; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; -using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using Serilog; diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs index bddaaaf6..2d8dd787 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs @@ -35,7 +35,7 @@ public override void Handle(IPlayer sender, GetPlayersPermissionConfigurationPac PlayerPermissionConfiguration[] playerPermissionConfigurations = new PlayerPermissionConfiguration[HasManager ? 2 : 1]; playerPermissionConfigurations[0] = new PlayerPermissionConfiguration { - UserId = sender.UserId, + UserId = sender.HashedUserId, IsServerOwner = sender.IsServerOwner, HasRecommendBeatmapsPermission = sender.CanRecommendBeatmaps, HasRecommendGameplayModifiersPermission = sender.CanRecommendModifiers, @@ -45,7 +45,7 @@ public override void Handle(IPlayer sender, GetPlayersPermissionConfigurationPac if (HasManager) playerPermissionConfigurations[1] = new PlayerPermissionConfiguration { - UserId = ServerOwner!.UserId, + UserId = ServerOwner!.HashedUserId, IsServerOwner = ServerOwner!.IsServerOwner, HasRecommendBeatmapsPermission = ServerOwner!.CanRecommendBeatmaps, HasRecommendGameplayModifiersPermission = ServerOwner!.CanRecommendModifiers, diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedBeatmapPacketHandler.cs index 99deced7..e75fdfbf 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetRecommendedBeatmapPacketHandler.cs @@ -22,8 +22,8 @@ public override void Handle(IPlayer sender, GetRecommendedBeatmapPacket packet) $"Handling packet of type '{nameof(GetRecommendedBeatmapPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - - if(sender.BeatmapIdentifier != null) + //TODO send custom packet details + if (sender.BeatmapIdentifier != null) _packetDispatcher.SendToPlayer(sender, new SetRecommendedBeatmapPacket { BeatmapIdentifier = sender.BeatmapIdentifier diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedBeatmapHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedBeatmapHandler.cs index b3f2a60e..33f6646f 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedBeatmapHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedBeatmapHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.Core.Enums; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; @@ -32,7 +33,8 @@ public override void Handle(IPlayer sender, GetSelectedBeatmap packet) $"Handling packet of type '{nameof(GetSelectedBeatmap)}' " + $"(SenderId={sender.ConnectionId})." ); - if(_instance.State == Messaging.Enums.MultiplayerGameState.Lobby && _lobbyManager.SelectedBeatmap != null) + //TODO send custom packet details + if (_instance.State != MultiplayerGameState.Game && _lobbyManager.SelectedBeatmap != null) { _packetDispatcher.SendToPlayer(sender, new SetSelectedBeatmap { @@ -40,7 +42,7 @@ public override void Handle(IPlayer sender, GetSelectedBeatmap packet) }, IgnoranceChannelTypes.Reliable); return; } - if (_instance.State == Messaging.Enums.MultiplayerGameState.Game && _gameplayManager.CurrentBeatmap != null) + if (_instance.State == MultiplayerGameState.Game && _gameplayManager.CurrentBeatmap != null) { _packetDispatcher.SendToPlayer(sender, new SetSelectedBeatmap { diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedGameplayModifiersHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedGameplayModifiersHandler.cs index 0c32148e..1979e4fe 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedGameplayModifiersHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetSelectedGameplayModifiersHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.Core.Enums; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; @@ -32,7 +33,7 @@ public override void Handle(IPlayer sender, GetSelectedGameplayModifiers packet) $"Handling packet of type '{nameof(GetSelectedGameplayModifiers)}' " + $"(SenderId={sender.ConnectionId})." ); - if(_instance.State == Messaging.Enums.MultiplayerGameState.Lobby && _lobbyManager.SelectedModifiers != _lobbyManager.EmptyModifiers) + if(_instance.State != MultiplayerGameState.Game && _lobbyManager.SelectedModifiers != _lobbyManager.EmptyModifiers) { _packetDispatcher.SendToPlayer(sender, new SetSelectedGameplayModifiers { @@ -40,7 +41,7 @@ public override void Handle(IPlayer sender, GetSelectedGameplayModifiers packet) }, IgnoranceChannelTypes.Reliable); return; } - if (_instance.State == Messaging.Enums.MultiplayerGameState.Game) + if (_instance.State == MultiplayerGameState.Game) { _packetDispatcher.SendToPlayer(sender, new SetSelectedGameplayModifiers { diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs index d26f228d..10910223 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetStartedLevelPacketHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.Core.Enums; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Kernel.Enums; @@ -7,7 +8,6 @@ using BeatTogether.DedicatedServer.Messaging.Models; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using Serilog; -using System.Linq; namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs index aa06740a..db533291 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetIsReadyPacketHandler.cs @@ -1,8 +1,8 @@ -using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.Core.Enums; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Managers.Abstractions; -using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc; using Serilog; diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs index 7115e2a4..adf46185 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/SetRecommendedBeatmapPacketHandler.cs @@ -40,6 +40,7 @@ public override void Handle(IPlayer sender, SetRecommendedBeatmapPacket packet) } sender.BeatmapIdentifier = packet.BeatmapIdentifier; sender.UpdateEntitlement = true; + //Our custom mpbeatmap packet stuff gets sent anyway //TODO apply this logic to all entitlement checks, and check it works well. Might need to send everyones entitlements to a player when they select a map _packetDispatcher.SendToPlayers(_playerRegistry.Players.Where(p => p.GetEntitlement(sender.BeatmapIdentifier.LevelId) == Messaging.Enums.EntitlementStatus.Unknown).ToArray(), new GetIsEntitledToLevelPacket { diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs index 721568a2..9367b7f8 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/DediPacketSetNewManagerHandler.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; +using BeatTogether.Core.Enums; +using BeatTogether.DedicatedServer.Ignorance.IgnoranceCore; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Configuration; using BeatTogether.DedicatedServer.Messaging.Models; @@ -33,7 +34,7 @@ public override void Handle(IPlayer sender, DediPacketSetNewManagerPacket packet $"(SenderId={sender.ConnectionId})." ); - if (sender.IsServerOwner && _configuration.GameplayServerMode == Enums.GameplayServerMode.Managed) + if (sender.IsServerOwner && _configuration.GameplayServerConfiguration.GameplayServerMode == GameplayServerMode.Managed) { _configuration.ServerOwnerId = packet.NewManagerID; @@ -43,7 +44,7 @@ public override void Handle(IPlayer sender, DediPacketSetNewManagerPacket packet { PlayersPermission = _playerRegistry.Players.Select(x => new PlayerPermissionConfiguration { - UserId = x.UserId, + UserId = x.HashedUserId, IsServerOwner = x.IsServerOwner, HasRecommendBeatmapsPermission = x.CanRecommendBeatmaps, HasRecommendGameplayModifiersPermission = x.CanRecommendModifiers, diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs index 6f34093a..cb6d0746 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetExtraPlayerDataPacketHandler.cs @@ -26,8 +26,8 @@ public override void Handle(IPlayer sender, MpPlayerData packet) _PacketDispatcher.SendFromPlayerToPlayer(Player, sender, new MpPlayerData() { PlatformID = Player.PlatformUserId, - Platform = Player.Platform.Convert(), - ClientVersion = Player.ClientVersion + Platform = Player.PlayerPlatform.Convert(), + ClientVersion = Player.PlayerClientVersion.ToString(), }, IgnoranceChannelTypes.Reliable); } } diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs index 049ebb16..9bf14e7d 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerSortOrderPacketHandler.cs @@ -21,7 +21,7 @@ public override void Handle(IPlayer sender, PlayerSortOrderPacket packet) $"Handling packet of type '{nameof(PlayerSortOrderPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - if (sender.UserId == packet.UserId && sender.SortIndex != packet.SortIndex) //If they send themselves as being in the wrong place, correct them. Although this probably shouldnt have a handler + if (sender.HashedUserId == packet.UserId && sender.SortIndex != packet.SortIndex) //If they send themselves as being in the wrong place, correct them. Although this probably shouldnt have a handler { packet.SortIndex = sender.SortIndex; _packetDispatcher.SendToPlayer(sender, packet, IgnoranceChannelTypes.Reliable); diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index 8105162b..2cf4b44f 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Net; +using BeatTogether.Core.Enums; using BeatTogether.DedicatedServer.Kernel.Abstractions; using BeatTogether.DedicatedServer.Kernel.Enums; using BeatTogether.DedicatedServer.Kernel.Types; @@ -16,9 +17,9 @@ public sealed class Player : IPlayer public IDedicatedInstance Instance { get; } public byte ConnectionId { get; } public byte RemoteConnectionId => 0; - public string UserId { get; } + public string HashedUserId { get; set; } public string UserName { get; } - public string PlayerSessionId { get; } + public string PlayerSessionId { get; set; } public uint ENetPeerId { get; set; } @@ -29,8 +30,8 @@ public sealed class Player : IPlayer public int SortIndex { get; set; } public byte[]? Random { get; set; } public byte[]? PublicEncryptionKey { get; set; } - public string ClientVersion { get; set; } = "Unknown"; - public Platform Platform { get; set; } = Platform.Test; //Unknown + public Version PlayerClientVersion { get; set; } = new(); + public Platform PlayerPlatform { get; set; } = Platform.Test; //Unknown public string PlatformUserId { get; set; } = ""; public MultiplayerAvatarsData Avatar { get; set; } = new(); public bool IsReady { get; set; } @@ -39,13 +40,13 @@ public sealed class Player : IPlayer public BeatmapIdentifier? BeatmapIdentifier { get; set; } = null; public GameplayModifiers Modifiers { get; set; } = new(); public PlayerStateHash State { get; set; } = new(); - public bool IsServerOwner => UserId == Instance._configuration.ServerOwnerId; + public bool IsServerOwner => HashedUserId == Instance._configuration.ServerOwnerId; public bool CanRecommendBeatmaps => true;// This check is wrong as GameplayServerControlSettings is None in Quickplay to disable Modifier selection //Instance._configuration.GameplayServerControlSettings is not GameplayServerControlSettings.None; public bool CanRecommendModifiers => - Instance._configuration.GameplayServerControlSettings is GameplayServerControlSettings.AllowModifierSelection or GameplayServerControlSettings.All; - public bool CanKickVote => UserId == Instance._configuration.ServerOwnerId; + Instance._configuration.GameplayServerConfiguration.GameplayServerControlSettings is GameplayServerControlSettings.AllowModifierSelection or GameplayServerControlSettings.All; + public bool CanKickVote => HashedUserId == Instance._configuration.ServerOwnerId; public bool CanInvite => - Instance._configuration.DiscoveryPolicy is DiscoveryPolicy.WithCode or DiscoveryPolicy.Public; + Instance._configuration.GameplayServerConfiguration.DiscoveryPolicy is DiscoveryPolicy.WithCode or DiscoveryPolicy.Public; public bool ForceLateJoin { get; set; } = false; //Used to force trouble players to late join a mp game/tell them to spectate public bool IsPlayer => State.Contains("player"); //If the user is a player @@ -67,7 +68,7 @@ public Player(EndPoint endPoint, IDedicatedInstance instance, Endpoint = endPoint; Instance = instance; ConnectionId = connectionId; - UserId = userId; + HashedUserId = userId; UserName = userName; PlayerSessionId = playerSessionId; _AccessLevel = accessLevel; @@ -103,7 +104,7 @@ public void SetEntitlement(string levelId, EntitlementStatus entitlement) public bool UpdateEntitlement { get; set; } = false; public string MapHash { get; set; } = string.Empty; - public Dictionary BeatmapDifficultiesRequirements { get; set; } + public Dictionary BeatmapDifficultiesRequirements { get; set; } = new(); public long TicksAtLastSyncStateDelta { get; set; } = 0; //33ms gaps for 30/sec, 66ms gap for 15/sec public long TicksAtLastSyncState { get; set; } = 0; diff --git a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs index 12acbe03..9d4f69b5 100644 --- a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs @@ -16,38 +16,36 @@ public sealed class PlayerRegistry : IPlayerRegistry private readonly Dictionary _playersByConnectionId = new(); private readonly Dictionary _playersByUserId = new(); - private readonly object pendingPlayerSessionData_Lock = new(); - private readonly Dictionary _pendingPlayerSessionData = new(); + private readonly Dictionary _pendingPlayerSessionData = new(); - public void AddExtraPlayerSessionData(string playerSessionId, string ClientVersion, byte PlatformId, string PlayerPlatformUserId) + public void AddExtraPlayerSessionData(Core.Abstractions.IPlayer playerSessionData) { - lock (pendingPlayerSessionData_Lock) - { - _pendingPlayerSessionData[playerSessionId] = (ClientVersion, PlatformId, PlayerPlatformUserId); - } + _pendingPlayerSessionData[playerSessionData.PlayerSessionId] = playerSessionData; } - public bool RemoveExtraPlayerSessionData(string playerSessionId, out string ClientVersion, out byte Platform, out string PlayerPlatformUserId) + public bool RemoveExtraPlayerSessionDataAndApply(Core.Abstractions.IPlayer playerSessionData) { - lock (pendingPlayerSessionData_Lock) + + if (_pendingPlayerSessionData.Remove(playerSessionData.PlayerSessionId, out var Value)) { - if (_pendingPlayerSessionData.Remove(playerSessionId, out var Values)) - { - ClientVersion = Values.Item1; - Platform = Values.Item2; - PlayerPlatformUserId = Values.Item3; - return true; - } - ClientVersion = "ERROR"; - Platform = 0; - PlayerPlatformUserId = "ERROR"; - return false; + playerSessionData.PlayerClientVersion = Value.PlayerClientVersion; + playerSessionData.PlayerPlatform = Value.PlayerPlatform; + playerSessionData.PlatformUserId = Value.PlatformUserId; + return true; } + playerSessionData.PlayerClientVersion = new System.Version("1.0.0"); + playerSessionData.PlayerPlatform = Core.Enums.Platform.Test; + playerSessionData.PlatformUserId = "ERROR"; + return false; } + public bool RemoveExtraPlayerSessionData(string playerSessionId) + { + return _pendingPlayerSessionData.Remove(playerSessionId, out _); + } private int _PlayerCount = 0; @@ -73,7 +71,7 @@ public bool AddPlayer(IPlayer player) { lock (PlayerDictionaries_Lock) { - if (_playersByUserId.TryAdd(player.UserId, player)) + if (_playersByUserId.TryAdd(player.HashedUserId, player)) { _playersByRemoteEndPoint.TryAdd(player.Endpoint, player); _playersByConnectionId.TryAdd(player.ConnectionId, player); @@ -89,7 +87,7 @@ public void RemovePlayer(IPlayer player) { lock (PlayerDictionaries_Lock) { - if (_playersByUserId.Remove(player.UserId, out _)) + if (_playersByUserId.Remove(player.HashedUserId, out _)) { _playersByRemoteEndPoint.Remove(player.Endpoint, out _); _playersByConnectionId.Remove(player.ConnectionId, out _); diff --git a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj index 29409fe6..9ed81f49 100644 --- a/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj +++ b/BeatTogether.DedicatedServer.Messaging/BeatTogether.DedicatedServer.Messaging.csproj @@ -7,6 +7,7 @@ + diff --git a/BeatTogether.DedicatedServer.Messaging/Enums/MultiplayerGameState.cs b/BeatTogether.DedicatedServer.Messaging/Enums/MultiplayerGameState.cs deleted file mode 100644 index d2e4238d..00000000 --- a/BeatTogether.DedicatedServer.Messaging/Enums/MultiplayerGameState.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace BeatTogether.DedicatedServer.Messaging.Enums -{ - public enum MultiplayerGameState - { - None = 0, - Lobby = 1, - Game = 2 - } -} diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs index d6d2b986..8727e360 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MenuRpc/SetMultiplayerGameStatePacket.cs @@ -1,7 +1,7 @@ using BeatTogether.DedicatedServer.Messaging.Abstractions; -using BeatTogether.DedicatedServer.Messaging.Enums; using BeatTogether.Extensions; using BeatTogether.DedicatedServer.Messaging.Util; +using BeatTogether.Core.Enums; namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MenuRpc { diff --git a/BeatTogether.DedicatedServer.Node/Abstractions/IInstanceFactory.cs b/BeatTogether.DedicatedServer.Node/Abstractions/IInstanceFactory.cs deleted file mode 100644 index 65845bcd..00000000 --- a/BeatTogether.DedicatedServer.Node/Abstractions/IInstanceFactory.cs +++ /dev/null @@ -1,25 +0,0 @@ -using BeatTogether.DedicatedServer.Interface.Models; -using BeatTogether.DedicatedServer.Kernel.Abstractions; - -namespace BeatTogether.DedicatedServer.Node.Abstractions -{ - public interface IInstanceFactory - { - public IDedicatedInstance? CreateInstance( - string secret, - string managerId, - GameplayServerConfiguration config, - bool permanentManager = false,//If a user links there account to discord and uses a bot to make a lobby, then can enter there userId - float instanceTimeout = 0f, - string ServerName = "", - long resultScreenTime = 20, - long BeatmapStartTime = 5, - long PlayersReadyCountdownTime = 0, - bool AllowPerPlayerModifiers = false, - bool AllowPerPlayerDifficulties = false, - bool AllowChroma = true, - bool AllowME = true, - bool AllowNE = true - ); - } -} diff --git a/BeatTogether.DedicatedServer.Node/Abstractions/IInstanceRegistry.cs b/BeatTogether.DedicatedServer.Node/Abstractions/IInstanceRegistry.cs deleted file mode 100644 index 99a5928c..00000000 --- a/BeatTogether.DedicatedServer.Node/Abstractions/IInstanceRegistry.cs +++ /dev/null @@ -1,12 +0,0 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using System.Diagnostics.CodeAnalysis; - -namespace BeatTogether.DedicatedServer.Node.Abstractions -{ - public interface IInstanceRegistry - { - public bool AddInstance(IDedicatedInstance instance); - public bool RemoveInstance(IDedicatedInstance instance); - public bool TryGetInstance(string secret, [MaybeNullWhen(false)] out IDedicatedInstance instance); - } -} diff --git a/BeatTogether.DedicatedServer.Node/Abstractions/INodeService.cs b/BeatTogether.DedicatedServer.Node/Abstractions/INodeService.cs deleted file mode 100644 index 33e39416..00000000 --- a/BeatTogether.DedicatedServer.Node/Abstractions/INodeService.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace BeatTogether.DedicatedServer.Node.Abstractions -{ - public interface INodeService - { - } -} diff --git a/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj b/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj index 7da5c8c4..06d26b42 100644 --- a/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj +++ b/BeatTogether.DedicatedServer.Node/BeatTogether.DedicatedServer.Node.csproj @@ -12,13 +12,13 @@ - - + + - + diff --git a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs index eafd2838..75b264b2 100644 --- a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs +++ b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs @@ -4,9 +4,7 @@ namespace BeatTogether.DedicatedServer.Node.Configuration { public sealed class NodeConfiguration { - public string HostName { get; set; } = "127.0.0.1"; - public Version NodeVersion { get; } = new Version(1,6,0); - public int BasePort { get; set; } = 30000; - public int MaximumSlots { get; set; } = 10000; + public string HostName { get; set; } = "192.168.0.21"; + public Version NodeVersion { get; } = new Version(2,0,0); } } diff --git a/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs b/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs index 3c2137ee..1395bdfe 100644 --- a/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs +++ b/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs @@ -1,10 +1,6 @@ -using System.Security.Cryptography; using Autobus; +using BeatTogether.Core.ServerMessaging; using BeatTogether.DedicatedServer.Interface; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Extensions; -using BeatTogether.DedicatedServer.Kernel.Providers; -using BeatTogether.DedicatedServer.Node.Abstractions; using BeatTogether.DedicatedServer.Node.Configuration; using BeatTogether.Extensions; using Microsoft.Extensions.DependencyInjection; @@ -19,19 +15,12 @@ public static IHostBuilder UseDedicatedServerNode(this IHostBuilder hostBuilder) .ConfigureAppConfiguration() .UseSerilog() .UseAutobus() - .UseDedicatedInstances() .ConfigureServices((hostBuilderContext, services) => services - .AddCoreSecurity() .AddConfiguration("Node") - .AddSingleton(RandomNumberGenerator.Create()) - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddServiceKernel() - .AddHostedService() + .AddServiceKernel() + .AddSingleton() + .AddHostedService() ); } } \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.Node/ForwardServerEventsLayer.cs b/BeatTogether.DedicatedServer.Node/ForwardServerEventsLayer.cs new file mode 100644 index 00000000..f455cae4 --- /dev/null +++ b/BeatTogether.DedicatedServer.Node/ForwardServerEventsLayer.cs @@ -0,0 +1,57 @@ +using Autobus; +using BeatTogether.Core.Abstractions; +using BeatTogether.Core.ServerMessaging; +using BeatTogether.DedicatedServer.Interface.Events; +using System; +using System.Linq; + +namespace BeatTogether.DedicatedServer.Node +{ + public class ForwardServerEventsLayer : ILayer1 + { + + private readonly IAutobus _autobus; + //private readonly ILogger _logger = Log.ForContext(); + + public ForwardServerEventsLayer( + IAutobus autobus) + { + _autobus = autobus; + } + + public void InstanceClosed(IServerInstance instance) + { + _autobus.Publish(new MatchmakingServerStoppedEvent(instance.Secret)); + } + + public void InstanceConfigChanged(IServerInstance instance) + { + _autobus.Publish(new UpdateInstanceConfigEvent(new Core.ServerMessaging.Models.Server(instance))); + } + + public void InstanceCreated(IServerInstance instance) + { + throw new NotImplementedException(); + } + + public void InstancePlayersChanged(IServerInstance instance) + { + _autobus.Publish(new UpdatePlayersEvent(instance.Secret, instance.PlayerHashes.ToArray())); + } + + public void InstanceStateChanged(IServerInstance instance) + { + _autobus.Publish(new ServerInGameplayEvent(instance.Secret, instance.GameState)); + } + + public void PlayerJoined(IServerInstance instance, IPlayer player) + { + _autobus.Publish(new PlayerJoinEvent(instance.Secret, player.HashedUserId)); + } + + public void PlayerLeft(IServerInstance instance, IPlayer player) + { + _autobus.Publish(new PlayerLeaveServerEvent(instance.Secret, player.HashedUserId)); + } + } +} diff --git a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs b/BeatTogether.DedicatedServer.Node/InstanceFactory.cs deleted file mode 100644 index a7bb7f78..00000000 --- a/BeatTogether.DedicatedServer.Node/InstanceFactory.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using BeatTogether.DedicatedServer.Interface.Models; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Kernel.Configuration; -using BeatTogether.DedicatedServer.Kernel.Enums; -using BeatTogether.DedicatedServer.Node.Abstractions; -using Microsoft.Extensions.DependencyInjection; - -namespace BeatTogether.DedicatedServer.Node -{ - public sealed class InstanceFactory : IInstanceFactory - { - private readonly IInstanceRegistry _instanceRegistry; - private readonly IServiceProvider _serviceProvider; - private readonly IPortAllocator _portAllocator; - - public InstanceFactory( - IInstanceRegistry instanceRegistry, - IServiceProvider serviceProvider, - IPortAllocator portAllocator) - { - _instanceRegistry = instanceRegistry; - _serviceProvider = serviceProvider; - _portAllocator = portAllocator; - } - - public IDedicatedInstance? CreateInstance( - string secret, - string managerId, - GameplayServerConfiguration config, - bool permanentManager, - float instanceTimeout, - string ServerName, - long resultScreenTime, - long BeatmapStartTime, - long PlayersReadyCountdownTime, - bool AllowPerPlayerModifiers, - bool AllowPerPlayerDifficulties, - bool AllowChroma, - bool AllowME, - bool AllowNE - ) - { - var Port = _portAllocator.AcquirePort(); - - if (!Port.HasValue) - return null; - - var scope = _serviceProvider.CreateScope(); - - var instanceConfig = scope.ServiceProvider.GetRequiredService(); - instanceConfig.Port = (int)Port!; - instanceConfig.Secret = secret; - instanceConfig.ServerOwnerId = managerId; - instanceConfig.MaxPlayerCount = Math.Min(config.MaxPlayerCount,250); //max size of 254, id 127 routes packets to all, max is 250, last 4 ID's will be reserved for future features - instanceConfig.DiscoveryPolicy = (DiscoveryPolicy)config.DiscoveryPolicy; - instanceConfig.InvitePolicy = (InvitePolicy)config.InvitePolicy; - instanceConfig.GameplayServerMode = (GameplayServerMode)config.GameplayServerMode; - instanceConfig.SongSelectionMode = (SongSelectionMode)config.SongSelectionMode; - instanceConfig.GameplayServerControlSettings = (GameplayServerControlSettings)config.GameplayServerControlSettings; - instanceConfig.DestroyInstanceTimeout = instanceTimeout; - instanceConfig.ServerName = ServerName; - instanceConfig.CountdownConfig.BeatMapStartCountdownTime = Math.Max(BeatmapStartTime,0); - instanceConfig.CountdownConfig.ResultsScreenTime = Math.Max(resultScreenTime,0); - instanceConfig.AllowChroma = AllowChroma; - instanceConfig.AllowMappingExtensions = AllowME; - instanceConfig.AllowNoodleExtensions = AllowNE; - instanceConfig.AllowPerPlayerDifficulties = AllowPerPlayerDifficulties; - instanceConfig.AllowPerPlayerModifiers = AllowPerPlayerModifiers; - if (permanentManager) - instanceConfig.SetConstantManagerFromUserId = managerId; - instanceConfig.CountdownConfig.CountdownTimePlayersReady = Math.Max(PlayersReadyCountdownTime,0L); - if (instanceConfig.CountdownConfig.CountdownTimePlayersReady == 0L) - instanceConfig.CountdownConfig.CountdownTimePlayersReady = instanceConfig.GameplayServerMode == GameplayServerMode.Managed ? 15000L : 30000L; - var instance = scope.ServiceProvider.GetRequiredService(); - if (!_instanceRegistry.AddInstance(instance)) - return null; - instance.StopEvent += HandleStopEvent; - return instance; - } - - private void HandleStopEvent(IDedicatedInstance Instance) - { - _instanceRegistry.RemoveInstance(Instance); - _portAllocator.ReleasePort(Instance.Port); - } - } -} diff --git a/BeatTogether.DedicatedServer.Node/InstanceRegistry.cs b/BeatTogether.DedicatedServer.Node/InstanceRegistry.cs deleted file mode 100644 index 5929bfa9..00000000 --- a/BeatTogether.DedicatedServer.Node/InstanceRegistry.cs +++ /dev/null @@ -1,21 +0,0 @@ -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Node.Abstractions; -using System.Collections.Concurrent; -using System.Diagnostics.CodeAnalysis; - -namespace BeatTogether.DedicatedServer.Node -{ - public sealed class InstanceRegistry : IInstanceRegistry - { - private readonly ConcurrentDictionary _instances = new(); - - public bool AddInstance(IDedicatedInstance instance) => - _instances.TryAdd(instance._configuration.Secret, instance); - - public bool RemoveInstance(IDedicatedInstance instance) => - _instances.TryRemove(instance._configuration.Secret, out _); - - public bool TryGetInstance(string secret, [MaybeNullWhen(false)] out IDedicatedInstance instance) => - _instances.TryGetValue(secret, out instance); - } -} diff --git a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs b/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs deleted file mode 100644 index cfd91018..00000000 --- a/BeatTogether.DedicatedServer.Node/MasterServerEventHandler.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using Autobus; -using BeatTogether.DedicatedServer.Interface.Events; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Node.Abstractions; -using BeatTogether.DedicatedServer.Node.Configuration; -using BeatTogether.MasterServer.Interface.Events; -using Microsoft.Extensions.Hosting; -using Serilog; - -namespace BeatTogether.DedicatedServer.Node -{ - public sealed class MasterServerEventHandler : IHostedService - { - private readonly IAutobus _autobus; - private readonly ILogger _logger = Log.ForContext(); - private readonly NodeConfiguration _configuration; - private readonly IInstanceRegistry _instanceRegistry; - - public MasterServerEventHandler( - IAutobus autobus, - NodeConfiguration nodeConfiguration, - IInstanceRegistry instanceRegistry) - { - _autobus = autobus; - _configuration = nodeConfiguration; - _instanceRegistry = instanceRegistry; - } - - #region Start/Stop - - public Task StartAsync(CancellationToken cancellationToken) - { - _autobus.Subscribe(HandlePlayerConnectedToMatchmaking); - _autobus.Subscribe(HandleCheckNode); - _autobus.Subscribe(HandleDisconnectPlayer); - _autobus.Subscribe(HandleCloseServer); - _autobus.Publish(new NodeStartedEvent(_configuration.HostName, _configuration.NodeVersion.ToString())); - _logger.Information("Dedicated node version: " + _configuration.NodeVersion.ToString() + " starting: " + _configuration.HostName); - return Task.CompletedTask; - } - - public Task StopAsync(CancellationToken cancellationToken) - { - _autobus.Unsubscribe(HandlePlayerConnectedToMatchmaking); - _autobus.Unsubscribe(HandleCheckNode); - _autobus.Unsubscribe(HandleDisconnectPlayer); - _autobus.Unsubscribe(HandleCloseServer); - return Task.CompletedTask; - } - - #endregion - - #region Handlers - - private Task HandlePlayerConnectedToMatchmaking(PlayerConnectedToMatchmakingServerEvent @event) - { - if (@event.NodeEndpoint != _configuration.HostName) - return Task.CompletedTask; - - //var remoteEndPoint = IPEndPoint.Parse(@event.RemoteEndPoint); - var playerSessionId = @event.PlayerSessionId; - var serverSecret = @event.Secret; - var PlayerClientVersion = @event.ClientVersion; - var PlayerPlatform = @event.Platform; - var PlayerPlatformUserId = @event.PlatformUserId; - - - TryGetDedicatedInstance(serverSecret)?.GetPlayerRegistry().AddExtraPlayerSessionData(playerSessionId, PlayerClientVersion, PlayerPlatform, PlayerPlatformUserId); - - _autobus.Publish(new NodeReceivedPlayerEncryptionEvent(_configuration.HostName, @event.RemoteEndPoint)); - return Task.CompletedTask; - } - - private Task HandleCheckNode(CheckNodesEvent checkNodesEvent) - { - _autobus.Publish(new NodeOnlineEvent(_configuration.HostName, _configuration.NodeVersion.ToString())); - return Task.CompletedTask; - } - - private Task HandleDisconnectPlayer(DisconnectPlayerFromMatchmakingServerEvent disconnectEvent) - { - var instance = TryGetDedicatedInstance(disconnectEvent.Secret); - if (instance != null && instance.GetPlayerRegistry().TryGetPlayer(disconnectEvent.UserId, out var player)) - { - instance.DisconnectPlayer(player); - } - - return Task.CompletedTask; - } - - private Task HandleCloseServer(CloseServerInstanceEvent closeEvent) - { - TryGetDedicatedInstance(closeEvent.Secret)?.Stop(); - return Task.CompletedTask; - } - - #endregion - - #region Util - - private IDedicatedInstance? TryGetDedicatedInstance(string secret) => - _instanceRegistry.TryGetInstance(secret, out var instance) ? instance : null; - - #endregion - } -} diff --git a/BeatTogether.DedicatedServer.Node/Models/PlayerFromMessage.cs b/BeatTogether.DedicatedServer.Node/Models/PlayerFromMessage.cs new file mode 100644 index 00000000..c6b39aef --- /dev/null +++ b/BeatTogether.DedicatedServer.Node/Models/PlayerFromMessage.cs @@ -0,0 +1,24 @@ +using BeatTogether.Core.Abstractions; +using BeatTogether.Core.Enums; +using System; + +namespace BeatTogether.DedicatedServer.Node.Models +{ + public class PlayerFromMessage : IPlayer + { + public string HashedUserId { get; set; } + public string PlatformUserId { get; set; } + public string PlayerSessionId { get; set; } + public Platform PlayerPlatform { get; set; } + public Version PlayerClientVersion { get; set; } + + public PlayerFromMessage(Core.ServerMessaging.Models.Player player) + { + HashedUserId = player.HashedUserId; + PlatformUserId = player.PlatformUserId; + PlayerSessionId = player.PlayerSessionId; + PlayerPlatform = player.PlayerPlatform; + PlayerClientVersion = new Version(player.PlayerClientVersion); + } + } +} diff --git a/BeatTogether.DedicatedServer.Node/Models/ServerFromMessage.cs b/BeatTogether.DedicatedServer.Node/Models/ServerFromMessage.cs new file mode 100644 index 00000000..45c6907e --- /dev/null +++ b/BeatTogether.DedicatedServer.Node/Models/ServerFromMessage.cs @@ -0,0 +1,81 @@ +using BeatTogether.Core.Abstractions; +using BeatTogether.Core.Enums; +using BeatTogether.Core.Models; +using System.Collections.Generic; +using System.Net; + +namespace BeatTogether.DedicatedServer.Node.Models +{ + public class ServerFromMessage : IServerInstance + { + public string ServerName { get; set; } + + public string Secret { get; set; } + + public string Code { get; set; } + + public string InstanceId { get; set; } + + public MultiplayerGameState GameState { get; set; } + + public BeatmapDifficultyMask BeatmapDifficultyMask { get; set; } + + public GameplayModifiersMask GameplayModifiersMask { get; set; } + + public GameplayServerConfiguration GameplayServerConfiguration { get; set; } + + public string SongPackMasks { get; set; } + + public string ManagerId { get; set; } + + public bool PermanentManager { get; set; } + + public long ServerStartJoinTimeout { get; set; } + + public bool NeverCloseServer { get; set; } + + public long ResultScreenTime { get; set; } + + public long BeatmapStartTime { get; set; } + + public long PlayersReadyCountdownTime { get; set; } + + public bool AllowPerPlayerModifiers { get; set; } + + public bool AllowPerPlayerDifficulties { get; set; } + + public bool AllowChroma { get; set; } + + public bool AllowME { get; set; } + + public bool AllowNE { get; set; } + + public IPEndPoint InstanceEndPoint { get; set; } = null!; + public HashSet PlayerHashes { get; set; } = null!; + + public ServerFromMessage(Core.ServerMessaging.Models.Server instance) + { + ServerName = instance.ServerName; + Secret = instance.Secret; + Code = instance.Code; + InstanceId = instance.InstanceId; + GameState = instance.GameState; + BeatmapDifficultyMask = instance.BeatmapDifficultyMask; + GameplayModifiersMask = instance.GameplayModifiersMask; + GameplayServerConfiguration = instance.GameplayServerConfiguration; + SongPackMasks = instance.SongPackMasks; + ManagerId = instance.ManagerId; + PermanentManager = instance.PermanentManager; + ServerStartJoinTimeout = instance.ServerStartJoinTimeout; + NeverCloseServer = instance.NeverCloseServer; + ResultScreenTime = instance.ResultScreenTime; + BeatmapStartTime = instance.BeatmapStartTime; + PlayersReadyCountdownTime = instance.PlayersReadyCountdownTime; + AllowPerPlayerDifficulties = instance.AllowPerPlayerDifficulties; + AllowPerPlayerModifiers = instance.AllowPerPlayerModifiers; + AllowChroma = instance.AllowChroma; + AllowME = instance.AllowME; + AllowNE = instance.AllowNE; + } + } +} diff --git a/BeatTogether.DedicatedServer.Node/NodeMessageEventHandler.cs b/BeatTogether.DedicatedServer.Node/NodeMessageEventHandler.cs new file mode 100644 index 00000000..3bdb89b3 --- /dev/null +++ b/BeatTogether.DedicatedServer.Node/NodeMessageEventHandler.cs @@ -0,0 +1,100 @@ +using System.Threading; +using System.Threading.Tasks; +using Autobus; +using BeatTogether.Core.Abstractions; +using BeatTogether.Core.Extensions; +using BeatTogether.Core.ServerMessaging.Models; +using BeatTogether.DedicatedServer.Interface.Events; +using BeatTogether.DedicatedServer.Node.Configuration; +using BeatTogether.DedicatedServer.Node.Models; +using BeatTogether.MasterServer.Interface.Events; +using BinaryRecords; +using Microsoft.Extensions.Hosting; +using Serilog; + +namespace BeatTogether.DedicatedServer.Node +{ + public sealed class NodeMessageEventHandler : IHostedService + { + private readonly IAutobus _autobus; + private readonly ILogger _logger = Log.ForContext(); + private readonly NodeConfiguration _configuration; + private readonly ILayer2 _Layer2; + + public NodeMessageEventHandler( + IAutobus autobus, + NodeConfiguration nodeConfiguration, + ILayer2 layer2) + { + _autobus = autobus; + _configuration = nodeConfiguration; + _Layer2 = layer2; + + BinarySerializer.AddGeneratorProvider( + (Player value, ref BinaryBufferWriter buffer) => BinaryBufferWriterExtensions.WritePlayer(ref buffer, value), + (ref BinaryBufferReader bufferReader) => BinaryBufferReaderExtensions.ReadPlayer(ref bufferReader) + ); + BinarySerializer.AddGeneratorProvider( + (Server value, ref BinaryBufferWriter buffer) => BinaryBufferWriterExtensions.WriteServer(ref buffer, value), + (ref BinaryBufferReader bufferReader) => BinaryBufferReaderExtensions.ReadServer(ref bufferReader) + ); + } + + #region Start/Stop + + public Task StartAsync(CancellationToken cancellationToken) + { + _autobus.Subscribe(HandlePlayerConnectedToMatchmaking); + _autobus.Subscribe(HandleCheckNode); + _autobus.Subscribe(HandleDisconnectPlayer); + _autobus.Subscribe(HandleCloseServer); + _autobus.Publish(new NodeStartedEvent(_configuration.HostName, _configuration.NodeVersion.ToString())); + _logger.Information("Dedicated node version: " + _configuration.NodeVersion.ToString() + " starting: " + _configuration.HostName); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + _autobus.Unsubscribe(HandlePlayerConnectedToMatchmaking); + _autobus.Unsubscribe(HandleCheckNode); + _autobus.Unsubscribe(HandleDisconnectPlayer); + _autobus.Unsubscribe(HandleCloseServer); + return Task.CompletedTask; + } + + #endregion + + #region Handlers + + private async Task HandlePlayerConnectedToMatchmaking(PlayerSessionDataSendToDediEvent SessionDataEvent) + { + if (SessionDataEvent.NodeEndpoint != _configuration.HostName) + return; + + Core.Abstractions.IPlayer player = new PlayerFromMessage(SessionDataEvent.Player); + if (!await _Layer2.SetPlayerSessionData(SessionDataEvent.serverInstanceSecret, player)) + return; + + _autobus.Publish(new NodeReceivedPlayerSessionDataEvent(_configuration.HostName, SessionDataEvent.Player.PlayerSessionId)); + return; + } + + private Task HandleCheckNode(CheckNodesEvent checkNodesEvent) + { + _autobus.Publish(new NodeOnlineEvent(_configuration.HostName, _configuration.NodeVersion.ToString())); + return Task.CompletedTask; + } + + private async Task HandleDisconnectPlayer(DisconnectPlayerFromMatchmakingServerEvent disconnectEvent) + { + await _Layer2.DisconnectPlayer(disconnectEvent.Secret, disconnectEvent.HashedUserId); + } + + private async Task HandleCloseServer(CloseServerInstanceEvent closeEvent) + { + await _Layer2.CloseInstance(closeEvent.Secret); + } + + #endregion + } +} diff --git a/BeatTogether.DedicatedServer.Node/NodeService.cs b/BeatTogether.DedicatedServer.Node/NodeService.cs index 90f5f161..b97098f5 100644 --- a/BeatTogether.DedicatedServer.Node/NodeService.cs +++ b/BeatTogether.DedicatedServer.Node/NodeService.cs @@ -1,123 +1,49 @@ -using System; -using System.Net; -using System.Threading.Tasks; -using Autobus; +using System.Threading.Tasks; +using BeatTogether.Core.Abstractions; using BeatTogether.DedicatedServer.Interface; -using BeatTogether.DedicatedServer.Interface.Events; using BeatTogether.DedicatedServer.Interface.Requests; using BeatTogether.DedicatedServer.Interface.Responses; -using BeatTogether.DedicatedServer.Kernel.Abstractions; -using BeatTogether.DedicatedServer.Messaging.Models; -using BeatTogether.DedicatedServer.Node.Abstractions; -using BeatTogether.DedicatedServer.Node.Configuration; +using BeatTogether.DedicatedServer.Node.Models; using Serilog; namespace BeatTogether.DedicatedServer.Node { - public sealed class NodeService : IMatchmakingService + public sealed class NodeMatchmakingService : IMatchmakingService { - private readonly NodeConfiguration _configuration; - private readonly IInstanceFactory _instanceFactory; - private readonly IAutobus _autobus; - private readonly ILogger _logger = Log.ForContext(); + private readonly ILayer2 _Layer2; + private readonly ILogger _logger = Log.ForContext(); - public NodeService( - NodeConfiguration configuration, - IInstanceFactory instanceFactory, - IAutobus autobus) + public NodeMatchmakingService( + ILayer2 layer2) { - _configuration = configuration; - _instanceFactory = instanceFactory; - _autobus = autobus; + _Layer2 = layer2; } public async Task CreateMatchmakingServer(CreateMatchmakingServerRequest request) { - _logger.Debug($"Received request to create matchmaking server. " + - $"(Secret={request.Secret}, " + - $"ManagerId={request.ManagerId}, " + - $"MaxPlayerCount={request.Configuration.MaxPlayerCount}, " + - $"DiscoveryPolicy={request.Configuration.DiscoveryPolicy}, " + - $"InvitePolicy={request.Configuration.InvitePolicy}, " + - $"GameplayServerMode={request.Configuration.GameplayServerMode}, " + - $"SongSelectionMode={request.Configuration.SongSelectionMode}, " + - $"GameplayServerControlSettings={request.Configuration.GameplayServerControlSettings})"); + _logger.Debug($"Received request to create matchmaking server from node messaging. " + + $"(Secret={request.Server.Secret}, " + + $"Code={request.Server.Code}, " + + $"ManagerId={request.Server.ManagerId}, " + + $"MaxPlayerCount={request.Server.GameplayServerConfiguration.MaxPlayerCount}, " + + $"DiscoveryPolicy={request.Server.GameplayServerConfiguration.DiscoveryPolicy}, " + + $"InvitePolicy={request.Server.GameplayServerConfiguration.InvitePolicy}, " + + $"GameplayServerMode={request.Server.GameplayServerConfiguration.GameplayServerMode}, " + + $"SongSelectionMode={request.Server.GameplayServerConfiguration.SongSelectionMode}, " + + $"GameplayServerControlSettings={request.Server.GameplayServerConfiguration.GameplayServerControlSettings})"); - var matchmakingServer = _instanceFactory.CreateInstance( - request.Secret, - request.ManagerId, - request.Configuration, - request.PermanentManager, - request.Timeout, - request.ServerName, - (long)request.ResultScreenTime, - ((long)request.BeatmapStartTime) * 1000, - ((long)request.PlayersReadyCountdownTime) * 1000, - request.AllowPerPlayerModifiers, - request.AllowPerPlayerDifficulties, - request.AllowChroma, - request.AllowME, - request.AllowNE - ); - if (matchmakingServer is null) - return new CreateMatchmakingServerResponse(CreateMatchmakingServerError.NoAvailableSlots, string.Empty, Array.Empty(), Array.Empty()); + IServerInstance serverInstance = new ServerFromMessage(request.Server); - matchmakingServer.PlayerConnectedEvent += HandleUpdatePlayerEvent; - matchmakingServer.PlayerDisconnectedEvent += HandlePlayerDisconnectEvent; - matchmakingServer.PlayerDisconnectBeforeJoining += HandlePlayerLeaveBeforeJoining; - matchmakingServer.StopEvent += HandleStopEvent; - matchmakingServer.GameIsInLobby += HandleGameInLobbyEvent; - matchmakingServer.UpdateInstanceEvent += HandleConfigChangeEvent; - await matchmakingServer.Start(); + var result = await _Layer2.CreateInstance(serverInstance); + + if(!result) + return new CreateMatchmakingServerResponse(CreateMatchmakingServerError.NoAvailableSlots, string.Empty); + return new CreateMatchmakingServerResponse( CreateMatchmakingServerError.None, - $"{_configuration.HostName}:{matchmakingServer.Port}", - Array.Empty(), - Array.Empty() + $"{serverInstance.InstanceEndPoint}" ); } - - - #region EventHandlers - - private void HandleGameInLobbyEvent(string secret, bool state) - { - _autobus.Publish(new ServerInGameplayEvent(secret, !state, string.Empty)); - } - - private void HandleConfigChangeEvent(IDedicatedInstance inst) - { - _autobus.Publish(new UpdateInstanceConfigEvent( - inst._configuration.Secret, - inst._configuration.ServerName, - new Interface.Models.GameplayServerConfiguration( - inst._configuration.MaxPlayerCount, - (Interface.Enums.DiscoveryPolicy)inst._configuration.DiscoveryPolicy, - (Interface.Enums.InvitePolicy)inst._configuration.InvitePolicy, - (Interface.Enums.GameplayServerMode)inst._configuration.GameplayServerMode, - (Interface.Enums.SongSelectionMode)inst._configuration.SongSelectionMode, - (Interface.Enums.GameplayServerControlSettings)inst._configuration.GameplayServerControlSettings - ) - )); - } - - private void HandleStopEvent(IDedicatedInstance inst) - { - _autobus.Publish(new MatchmakingServerStoppedEvent(inst._configuration.Secret)); - } - private void HandleUpdatePlayerEvent(IPlayer player) - { - _autobus.Publish(new PlayerJoinEvent(player.Instance._configuration.Secret, ((IPEndPoint)player.Endpoint).ToString(), player.UserId)); - } - private void HandlePlayerDisconnectEvent(IPlayer player) - { - _autobus.Publish(new PlayerLeaveServerEvent(player.Instance._configuration.Secret, player.UserId, ((IPEndPoint)player.Endpoint).ToString())); - } - private void HandlePlayerLeaveBeforeJoining(string Secret, EndPoint endPoint, string[] Players) - { - _autobus.Publish(new UpdatePlayersEvent(Secret, Players)); - } - #endregion } } \ No newline at end of file diff --git a/BeatTogether.DedicatedServer.sln b/BeatTogether.DedicatedServer.sln index ed19c0a4..ef5f959d 100644 --- a/BeatTogether.DedicatedServer.sln +++ b/BeatTogether.DedicatedServer.sln @@ -13,7 +13,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BeatTogether.DedicatedServe EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BeatTogether.DedicatedServer.Node", "BeatTogether.DedicatedServer.Node\BeatTogether.DedicatedServer.Node.csproj", "{D2B3DC3B-FECD-4E06-8B20-7A60A0BE3C2E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeatTogether.DedicatedServer.Ignorance", "BeatTogether.DedicatedServer.Ignorance\BeatTogether.DedicatedServer.Ignorance.csproj", "{775C10CC-FE88-41DD-A9E3-7F66CBA87470}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BeatTogether.DedicatedServer.Ignorance", "BeatTogether.DedicatedServer.Ignorance\BeatTogether.DedicatedServer.Ignorance.csproj", "{775C10CC-FE88-41DD-A9E3-7F66CBA87470}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BeatTogether.DedicatedServer.Instancing", "BeatTogether.DedicatedServer.Instancing\BeatTogether.DedicatedServer.Instancing.csproj", "{2C9A5AAD-D817-4410-BBF2-2EA765C31C1B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -45,6 +47,10 @@ Global {775C10CC-FE88-41DD-A9E3-7F66CBA87470}.Debug|Any CPU.Build.0 = Debug|Any CPU {775C10CC-FE88-41DD-A9E3-7F66CBA87470}.Release|Any CPU.ActiveCfg = Release|Any CPU {775C10CC-FE88-41DD-A9E3-7F66CBA87470}.Release|Any CPU.Build.0 = Release|Any CPU + {2C9A5AAD-D817-4410-BBF2-2EA765C31C1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C9A5AAD-D817-4410-BBF2-2EA765C31C1B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C9A5AAD-D817-4410-BBF2-2EA765C31C1B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C9A5AAD-D817-4410-BBF2-2EA765C31C1B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/BeatTogether.DedicatedServer/BeatTogether.DedicatedServer.csproj b/BeatTogether.DedicatedServer/BeatTogether.DedicatedServer.csproj index f9defa64..d2e91a76 100644 --- a/BeatTogether.DedicatedServer/BeatTogether.DedicatedServer.csproj +++ b/BeatTogether.DedicatedServer/BeatTogether.DedicatedServer.csproj @@ -29,6 +29,7 @@ + diff --git a/BeatTogether.DedicatedServer/Program.cs b/BeatTogether.DedicatedServer/Program.cs index aacc2d0b..f6a45f76 100644 --- a/BeatTogether.DedicatedServer/Program.cs +++ b/BeatTogether.DedicatedServer/Program.cs @@ -1,4 +1,5 @@ -using BeatTogether.DedicatedServer.Node.Extensions; +using BeatTogether.DedicatedServer.Instancing.Extensions; +using BeatTogether.DedicatedServer.Node.Extensions; using Microsoft.Extensions.Hosting; namespace BeatTogether.DedicatedServer @@ -9,6 +10,6 @@ public static void Main(string[] args) => CreateHostBuilder(args).Build().Run(); public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args).UseDedicatedServerNode(); + Host.CreateDefaultBuilder(args).UseDedicatedServerNode().UseDedicatedServerInstancing(); } } From bcf21253ab06b2b8e5e6af88bc5ecaaa6e502aa6 Mon Sep 17 00:00:00 2001 From: cubic Date: Thu, 9 May 2024 05:28:57 +0100 Subject: [PATCH 104/120] Added ping packet on join, Removed some logging --- .../DedicatedInstance.cs | 17 +++++++++-------- .../Managers/LobbyManager.cs | 4 ++++ ...ayersPermissionConfigurationPacketHandler.cs | 2 +- BeatTogether.DedicatedServer.Kernel/Player.cs | 3 +-- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index df450ed9..a1dc6b24 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -325,14 +325,11 @@ public void SetState(MultiplayerGameState state) _waitForPlayerCts.Cancel(); //UserID, UserName, and session - _logger.Information("Applying session data recv from master"); - if (GetPlayerRegistry().RemoveExtraPlayerSessionDataAndApply(player)) + if (!GetPlayerRegistry().RemoveExtraPlayerSessionDataAndApply(player)) { - _logger.Information("Successfull session data extraction"); + goto EndOfTryAccept; } - _logger.Information("Client ver: " + player.PlayerClientVersion.ToString()); - _logger.Information("Client platform: " + player.PlayerPlatform.ToString()); - _logger.Information("Client PlatformUserId: " + player.PlatformUserId); + return player; @@ -354,7 +351,7 @@ public override void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, I public override void OnConnect(EndPoint endPoint) { - _logger.Information($"Endpoint connected (RemoteEndPoint='{endPoint}')"); + //_logger.Information($"Endpoint connected (RemoteEndPoint='{endPoint}')"); if (!_playerRegistry.TryGetPlayer(endPoint, out var player)) { @@ -390,6 +387,10 @@ public override void OnConnect(EndPoint endPoint) //Send server infomation to player var Player_ConnectPacket = new INetSerializable[] { + new PingPacket + { + PingTime = RunTime + }, new SyncTimePacket { SyncTime = RunTime @@ -527,7 +528,7 @@ public override void OnConnect(EndPoint endPoint) Text = player.UserName + " Joined, Platform: " + player.PlayerPlatform.ToString() + " Version: " + player.PlayerClientVersion.ToString() }, IgnoranceChannelTypes.Reliable); - _logger.Information($"Sent connection data though for (RemoteEndPoint='{endPoint}')"); + //_logger.Information($"Sent connection data though for (RemoteEndPoint='{endPoint}')"); } public void DisconnectPlayer(IPlayer player) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index c30e5b5d..cd7b36e5 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -222,6 +222,10 @@ private void CountingDown(bool isReady, bool NotStartable) if (CountDownState != CountdownState.WaitingForEntitlement) { SetCountdown(CountdownState.WaitingForEntitlement); + _packetDispatcher.SendToPlayers(_playerRegistry.Players.Where(p => p.GetEntitlement(SelectedBeatmap!.LevelId) == Messaging.Enums.EntitlementStatus.Unknown).ToArray(), new GetIsEntitledToLevelPacket + { + LevelId = SelectedBeatmap!.LevelId + }, IgnoranceChannelTypes.Reliable); } if (_playerRegistry.Players.All(p => (p.GetEntitlement(SelectedBeatmap!.LevelId) is EntitlementStatus.Ok) || p.IsSpectating || !p.WantsToPlayNextLevel || p.IsBackgrounded || p.ForceLateJoin)) { diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs index 2d8dd787..14b243e1 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MenuRpc/GetPlayersPermissionConfigurationPacketHandler.cs @@ -30,7 +30,7 @@ public override void Handle(IPlayer sender, GetPlayersPermissionConfigurationPac $"Handling packet of type '{nameof(GetPlayersPermissionConfigurationPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - + //sends player there own permissions, and those of the player who is the current manager. bool HasManager = (_playerRegistry.TryGetPlayer(_configuration.ServerOwnerId, out var ServerOwner) && !sender.IsServerOwner); PlayerPermissionConfiguration[] playerPermissionConfigurations = new PlayerPermissionConfiguration[HasManager ? 2 : 1]; playerPermissionConfigurations[0] = new PlayerPermissionConfiguration diff --git a/BeatTogether.DedicatedServer.Kernel/Player.cs b/BeatTogether.DedicatedServer.Kernel/Player.cs index 2cf4b44f..b6b5ddcf 100644 --- a/BeatTogether.DedicatedServer.Kernel/Player.cs +++ b/BeatTogether.DedicatedServer.Kernel/Player.cs @@ -25,7 +25,7 @@ public sealed class Player : IPlayer public RollingAverage Latency { get; } = new(30); public long SyncTime => - Math.Min(Instance.RunTime - Latency.CurrentAverage - _syncTimeOffset, + Math.Min(Instance.RunTime - Latency.CurrentAverage, Instance.RunTime); public int SortIndex { get; set; } public byte[]? Random { get; set; } @@ -59,7 +59,6 @@ public sealed class Player : IPlayer public bool FinishedLevel => State.Contains("finished_level"); //If the player has finished the level public bool InMenu => State.Contains("in_menu"); //Should be true while in lobby - private const long _syncTimeOffset = 6L; private readonly ConcurrentDictionary _entitlements = new(); //Set a max amount of like 50 or something. public Player(EndPoint endPoint, IDedicatedInstance instance, From ea41f71f5cefdb9d42e57621ba04c79f09c38351 Mon Sep 17 00:00:00 2001 From: cubic Date: Thu, 9 May 2024 21:40:13 +0100 Subject: [PATCH 105/120] add branch to workflow --- .github/workflows/nuget.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index 08e0e638..a3158285 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -5,6 +5,7 @@ on: - master - dev - dev-1.35.0 + - dev-1.35.0-Restructured jobs: nuget-1: From c453ba7d2b9e7fee8523abfd7474eac8f759db23 Mon Sep 17 00:00:00 2001 From: cubic Date: Thu, 9 May 2024 23:27:44 +0100 Subject: [PATCH 106/120] Fix IP adress of nodes --- .../Configuration/InstancingConfiguration.cs | 3 ++- .../Configuration/NodeConfiguration.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs b/BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs index 8be3b3b2..03d0bbdd 100644 --- a/BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs +++ b/BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs @@ -4,7 +4,8 @@ namespace BeatTogether.DedicatedServer.Instancing.Configuration { public sealed class InstancingConfiguration { - public string HostName { get; set; } = "192.168.0.21"; + //public string HostName { get; set; } = "192.168.0.21"; + public string HostName { get; set; } = "127.0.0.1"; public int BasePort { get; set; } = 30000; public int MaximumSlots { get; set; } = 10000; } diff --git a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs index 75b264b2..4eac3f23 100644 --- a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs +++ b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs @@ -4,7 +4,8 @@ namespace BeatTogether.DedicatedServer.Node.Configuration { public sealed class NodeConfiguration { - public string HostName { get; set; } = "192.168.0.21"; + //public string HostName { get; set; } = "192.168.0.21"; + public string HostName { get; set; } = "127.0.0.1"; public Version NodeVersion { get; } = new Version(2,0,0); } } From 3628d6bbc637b6d7de1a87c586e9b96457500168 Mon Sep 17 00:00:00 2001 From: cubic Date: Sat, 11 May 2024 15:47:27 +0100 Subject: [PATCH 107/120] Updating config --- .../Configuration/InstancingConfiguration.cs | 3 +-- .../Extensions/HostBuilderExtensions.cs | 2 +- .../InstanceFactory.cs | 2 +- .../LayerService.cs | 6 +++--- .../Configuration/NodeConfiguration.cs | 3 +-- .../Extensions/HostBuilderExtensions.cs | 2 +- .../NodeMessageEventHandler.cs | 10 +++++----- .../appsettings.Development.json | 3 +++ BeatTogether.DedicatedServer/appsettings.json | 3 +++ 9 files changed, 19 insertions(+), 15 deletions(-) diff --git a/BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs b/BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs index 03d0bbdd..3bcd5368 100644 --- a/BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs +++ b/BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs @@ -4,8 +4,7 @@ namespace BeatTogether.DedicatedServer.Instancing.Configuration { public sealed class InstancingConfiguration { - //public string HostName { get; set; } = "192.168.0.21"; - public string HostName { get; set; } = "127.0.0.1"; + public string HostEndpoint { get; set; } = "127.0.0.1"; public int BasePort { get; set; } = 30000; public int MaximumSlots { get; set; } = 10000; } diff --git a/BeatTogether.DedicatedServer.Instancing/Extensions/HostBuilderExtensions.cs b/BeatTogether.DedicatedServer.Instancing/Extensions/HostBuilderExtensions.cs index b918e4fe..c53498dc 100644 --- a/BeatTogether.DedicatedServer.Instancing/Extensions/HostBuilderExtensions.cs +++ b/BeatTogether.DedicatedServer.Instancing/Extensions/HostBuilderExtensions.cs @@ -17,7 +17,7 @@ public static IHostBuilder UseDedicatedServerInstancing(this IHostBuilder hostBu .UseDedicatedInstances() .ConfigureServices((hostBuilderContext, services) => services - .AddConfiguration("Instancing") + .AddConfiguration("ServerConfiguration") .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/BeatTogether.DedicatedServer.Instancing/InstanceFactory.cs b/BeatTogether.DedicatedServer.Instancing/InstanceFactory.cs index 4d8ece01..44c473a6 100644 --- a/BeatTogether.DedicatedServer.Instancing/InstanceFactory.cs +++ b/BeatTogether.DedicatedServer.Instancing/InstanceFactory.cs @@ -79,7 +79,7 @@ public InstanceFactory( } instance.StopEvent += HandleStopEvent; - serverInstance.InstanceEndPoint = IPEndPoint.Parse($"{_config.HostName}:{instanceConfig.Port}"); + serverInstance.InstanceEndPoint = IPEndPoint.Parse($"{_config.HostEndpoint}:{instanceConfig.Port}"); //Subscribe to server events if the layer above allows this. if(_SendEventsLayer != null) diff --git a/BeatTogether.DedicatedServer.Instancing/LayerService.cs b/BeatTogether.DedicatedServer.Instancing/LayerService.cs index b8b323b0..fd496a74 100644 --- a/BeatTogether.DedicatedServer.Instancing/LayerService.cs +++ b/BeatTogether.DedicatedServer.Instancing/LayerService.cs @@ -55,7 +55,7 @@ public Task DisconnectPlayer(string InstanceSecret, string PlayerUserId) IServerInstance? serverInstance = null; if (_instanceRegistry.TryGetAvailablePublicServer(invitePolicy, serverMode, songMode, serverControlSettings, difficultyMask, modifiersMask, songPackMasks, out var instance)) { - serverInstance = new ServerInstance(instance, IPEndPoint.Parse($"{_instancingConfiguration.HostName}:{instance._configuration.Port}")); + serverInstance = new ServerInstance(instance, IPEndPoint.Parse($"{_instancingConfiguration.HostEndpoint}:{instance._configuration.Port}")); } return Task.FromResult(serverInstance); } @@ -65,7 +65,7 @@ public Task DisconnectPlayer(string InstanceSecret, string PlayerUserId) IServerInstance? serverInstance = null; if (_instanceRegistry.TryGetInstance(secret, out var instance)) { - serverInstance = new ServerInstance(instance, IPEndPoint.Parse($"{_instancingConfiguration.HostName}:{instance._configuration.Port}")); + serverInstance = new ServerInstance(instance, IPEndPoint.Parse($"{_instancingConfiguration.HostEndpoint}:{instance._configuration.Port}")); } return Task.FromResult(serverInstance); } @@ -75,7 +75,7 @@ public Task DisconnectPlayer(string InstanceSecret, string PlayerUserId) IServerInstance? serverInstance = null; if (_instanceRegistry.TryGetInstanceByCode(code, out var instance)) { - serverInstance = new ServerInstance(instance, IPEndPoint.Parse($"{_instancingConfiguration.HostName}:{instance._configuration.Port}")); + serverInstance = new ServerInstance(instance, IPEndPoint.Parse($"{_instancingConfiguration.HostEndpoint}:{instance._configuration.Port}")); } return Task.FromResult(serverInstance); } diff --git a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs index 4eac3f23..13d80cb4 100644 --- a/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs +++ b/BeatTogether.DedicatedServer.Node/Configuration/NodeConfiguration.cs @@ -4,8 +4,7 @@ namespace BeatTogether.DedicatedServer.Node.Configuration { public sealed class NodeConfiguration { - //public string HostName { get; set; } = "192.168.0.21"; - public string HostName { get; set; } = "127.0.0.1"; + public string HostEndpoint { get; set; } = "127.0.0.1"; public Version NodeVersion { get; } = new Version(2,0,0); } } diff --git a/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs b/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs index 1395bdfe..e99cf440 100644 --- a/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs +++ b/BeatTogether.DedicatedServer.Node/Extensions/HostBuilderExtensions.cs @@ -17,7 +17,7 @@ public static IHostBuilder UseDedicatedServerNode(this IHostBuilder hostBuilder) .UseAutobus() .ConfigureServices((hostBuilderContext, services) => services - .AddConfiguration("Node") + .AddConfiguration("ServerConfiguration") .AddServiceKernel() .AddSingleton() .AddHostedService() diff --git a/BeatTogether.DedicatedServer.Node/NodeMessageEventHandler.cs b/BeatTogether.DedicatedServer.Node/NodeMessageEventHandler.cs index 3bdb89b3..6dbb3743 100644 --- a/BeatTogether.DedicatedServer.Node/NodeMessageEventHandler.cs +++ b/BeatTogether.DedicatedServer.Node/NodeMessageEventHandler.cs @@ -48,8 +48,8 @@ public Task StartAsync(CancellationToken cancellationToken) _autobus.Subscribe(HandleCheckNode); _autobus.Subscribe(HandleDisconnectPlayer); _autobus.Subscribe(HandleCloseServer); - _autobus.Publish(new NodeStartedEvent(_configuration.HostName, _configuration.NodeVersion.ToString())); - _logger.Information("Dedicated node version: " + _configuration.NodeVersion.ToString() + " starting: " + _configuration.HostName); + _autobus.Publish(new NodeStartedEvent(_configuration.HostEndpoint, _configuration.NodeVersion.ToString())); + _logger.Information("Dedicated node version: " + _configuration.NodeVersion.ToString() + ". Host Endpoint: " + _configuration.HostEndpoint); return Task.CompletedTask; } @@ -68,20 +68,20 @@ public Task StopAsync(CancellationToken cancellationToken) private async Task HandlePlayerConnectedToMatchmaking(PlayerSessionDataSendToDediEvent SessionDataEvent) { - if (SessionDataEvent.NodeEndpoint != _configuration.HostName) + if (SessionDataEvent.NodeEndpoint != _configuration.HostEndpoint) return; Core.Abstractions.IPlayer player = new PlayerFromMessage(SessionDataEvent.Player); if (!await _Layer2.SetPlayerSessionData(SessionDataEvent.serverInstanceSecret, player)) return; - _autobus.Publish(new NodeReceivedPlayerSessionDataEvent(_configuration.HostName, SessionDataEvent.Player.PlayerSessionId)); + _autobus.Publish(new NodeReceivedPlayerSessionDataEvent(_configuration.HostEndpoint, SessionDataEvent.Player.PlayerSessionId)); return; } private Task HandleCheckNode(CheckNodesEvent checkNodesEvent) { - _autobus.Publish(new NodeOnlineEvent(_configuration.HostName, _configuration.NodeVersion.ToString())); + _autobus.Publish(new NodeOnlineEvent(_configuration.HostEndpoint, _configuration.NodeVersion.ToString())); return Task.CompletedTask; } diff --git a/BeatTogether.DedicatedServer/appsettings.Development.json b/BeatTogether.DedicatedServer/appsettings.Development.json index 2b1699ff..27727fad 100644 --- a/BeatTogether.DedicatedServer/appsettings.Development.json +++ b/BeatTogether.DedicatedServer/appsettings.Development.json @@ -5,6 +5,9 @@ "Overrides": { "Microsoft": "Warning" } + }, + "ServerConfiguration": { + "HostEndpoint": "127.0.0.1" } } } diff --git a/BeatTogether.DedicatedServer/appsettings.json b/BeatTogether.DedicatedServer/appsettings.json index 0c9c125c..12a9f2bf 100644 --- a/BeatTogether.DedicatedServer/appsettings.json +++ b/BeatTogether.DedicatedServer/appsettings.json @@ -2,6 +2,9 @@ "Serilog": { "File": { "Path": "logs/BeatTogether.DedicatedServer-{Date}.log" + }, + "ServerConfiguration": { + "HostEndpoint": "127.0.0.1" } } } From e251152b490c08af45c348369d97a95c9d69cd3c Mon Sep 17 00:00:00 2001 From: cubic Date: Tue, 14 May 2024 23:36:12 +0100 Subject: [PATCH 108/120] Added score sync state packet and lowered the frequency of sync state packets --- .../Abstractions/IPlayerRegistry.cs | 3 +- .../DedicatedInstance.cs | 33 ++++++++++++++----- .../PlayerRegistry.cs | 20 ++++++++--- .../MpCorePackets/MpScoreSyncStatePacket.cs | 24 ++++++++++++++ 4 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpScoreSyncStatePacket.cs diff --git a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs index c69827b7..f837e818 100644 --- a/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/Abstractions/IPlayerRegistry.cs @@ -12,7 +12,8 @@ public interface IPlayerRegistry bool TryGetPlayer(EndPoint remoteEndPoint, [MaybeNullWhen(false)] out IPlayer player); bool TryGetPlayer(byte connectionId, [MaybeNullWhen(false)] out IPlayer player); bool TryGetPlayer(string userId, [MaybeNullWhen(false)] out IPlayer player); - int GetMillisBetweenSyncStatePackets(); + long GetMillisBetweenPoseSyncStateDeltaPackets(); + long GetMillisBetweenScoreSyncStateDeltaPackets(); public void AddExtraPlayerSessionData(Core.Abstractions.IPlayer playerSessionData); public bool RemoveExtraPlayerSessionDataAndApply(Core.Abstractions.IPlayer playerSessionData/*out string ClientVersion, out byte Platform, out string PlayerPlatformUserId*/); diff --git a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs index a1dc6b24..1a8ab84a 100644 --- a/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs +++ b/BeatTogether.DedicatedServer.Kernel/DedicatedInstance.cs @@ -379,9 +379,14 @@ public override void OnConnect(EndPoint endPoint) }, new MpNodePoseSyncStatePacket { - fullStateUpdateFrequency = 100L, - deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() + fullStateUpdateFrequency = Math.Max(_playerRegistry.GetMillisBetweenPoseSyncStateDeltaPackets(), 100L), + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenPoseSyncStateDeltaPackets() }, + new MpScoreSyncStatePacket + { + fullStateUpdateFrequency = Math.Max(_playerRegistry.GetMillisBetweenScoreSyncStateDeltaPackets(), 500L), + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenScoreSyncStateDeltaPackets() + } }, IgnoranceChannelTypes.Reliable); //Send server infomation to player @@ -417,9 +422,14 @@ public override void OnConnect(EndPoint endPoint) }, new MpNodePoseSyncStatePacket { - fullStateUpdateFrequency = 100L, - deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() + fullStateUpdateFrequency = Math.Max(_playerRegistry.GetMillisBetweenPoseSyncStateDeltaPackets(), 100L), + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenPoseSyncStateDeltaPackets() }, + new MpScoreSyncStatePacket + { + fullStateUpdateFrequency = Math.Max(_playerRegistry.GetMillisBetweenScoreSyncStateDeltaPackets(), 500L), + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenScoreSyncStateDeltaPackets() + } }; PacketDispatcher.SendToPlayer(player, Player_ConnectPacket, IgnoranceChannelTypes.Reliable); @@ -572,10 +582,17 @@ public override void OnDisconnect(EndPoint endPoint) // Update permissions SetNewServerOwner(_playerRegistry.Players[0]); } - PacketDispatcher.SendToNearbyPlayers(new MpNodePoseSyncStatePacket - { - fullStateUpdateFrequency = 100L, - deltaUpdateFrequency = _playerRegistry.GetMillisBetweenSyncStatePackets() + PacketDispatcher.SendToNearbyPlayers(new INetSerializable[] { + new MpNodePoseSyncStatePacket + { + fullStateUpdateFrequency = Math.Max(_playerRegistry.GetMillisBetweenPoseSyncStateDeltaPackets(), 100L), + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenPoseSyncStateDeltaPackets() + }, + new MpScoreSyncStatePacket + { + fullStateUpdateFrequency = Math.Max(_playerRegistry.GetMillisBetweenScoreSyncStateDeltaPackets(), 500L), + deltaUpdateFrequency = _playerRegistry.GetMillisBetweenScoreSyncStateDeltaPackets() + } }, IgnoranceChannelTypes.Reliable); } else diff --git a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs index 9d4f69b5..fab74c85 100644 --- a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs @@ -76,7 +76,8 @@ public bool AddPlayer(IPlayer player) _playersByRemoteEndPoint.TryAdd(player.Endpoint, player); _playersByConnectionId.TryAdd(player.ConnectionId, player); _PlayerCount++; - MillisBetweenSyncStatePackets = (int)(0.84 * _PlayerCount + 15.789); + MillisBetweenPoseSyncStatePackets = (long)(0.94 * _PlayerCount + 15); + MillisBetweenScoreSyncStatePackets = (long)(1.5 * _PlayerCount + 20); return true; } } @@ -92,7 +93,8 @@ public void RemovePlayer(IPlayer player) _playersByRemoteEndPoint.Remove(player.Endpoint, out _); _playersByConnectionId.Remove(player.ConnectionId, out _); _PlayerCount--; - MillisBetweenSyncStatePackets = (int)(0.84 * _PlayerCount + 15.789); + MillisBetweenPoseSyncStatePackets = (long)(0.94 * _PlayerCount + 15); + MillisBetweenScoreSyncStatePackets = (long)(1.5 * _PlayerCount + 20); } } } @@ -119,10 +121,18 @@ public bool TryGetPlayer(string userId, [MaybeNullWhen(false)] out IPlayer playe } } - private int MillisBetweenSyncStatePackets = 0; - public int GetMillisBetweenSyncStatePackets() + + + private long MillisBetweenPoseSyncStatePackets = 0; + public long GetMillisBetweenPoseSyncStateDeltaPackets() + { + return MillisBetweenPoseSyncStatePackets; + } + + private long MillisBetweenScoreSyncStatePackets = 0; + public long GetMillisBetweenScoreSyncStateDeltaPackets() { - return MillisBetweenSyncStatePackets; + return MillisBetweenScoreSyncStatePackets; } } } diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpScoreSyncStatePacket.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpScoreSyncStatePacket.cs new file mode 100644 index 00000000..5c254dab --- /dev/null +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpScoreSyncStatePacket.cs @@ -0,0 +1,24 @@ +using BeatTogether.Extensions; +using BeatTogether.DedicatedServer.Messaging.Abstractions; +using BeatTogether.DedicatedServer.Messaging.Util; + +namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets +{ + public sealed class MpScoreSyncStatePacket : INetSerializable + { + public long deltaUpdateFrequency; + public long fullStateUpdateFrequency; + + public void WriteTo(ref SpanBuffer bufferWriter) + { + bufferWriter.WriteVarLong(deltaUpdateFrequency); + bufferWriter.WriteVarLong(fullStateUpdateFrequency); + } + public void ReadFrom(ref SpanBuffer bufferReader) + { + deltaUpdateFrequency = bufferReader.ReadVarLong(); + fullStateUpdateFrequency = bufferReader.ReadVarLong(); + } + } + +} From f5acdda7cbfa5f02ad559dc0e48d361aaf819dac Mon Sep 17 00:00:00 2001 From: cubic Date: Wed, 15 May 2024 00:08:28 +0100 Subject: [PATCH 109/120] sync states during 1 player drasticly lowered --- BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs index fab74c85..4fa16d86 100644 --- a/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs +++ b/BeatTogether.DedicatedServer.Kernel/PlayerRegistry.cs @@ -76,8 +76,8 @@ public bool AddPlayer(IPlayer player) _playersByRemoteEndPoint.TryAdd(player.Endpoint, player); _playersByConnectionId.TryAdd(player.ConnectionId, player); _PlayerCount++; - MillisBetweenPoseSyncStatePackets = (long)(0.94 * _PlayerCount + 15); - MillisBetweenScoreSyncStatePackets = (long)(1.5 * _PlayerCount + 20); + MillisBetweenPoseSyncStatePackets = _PlayerCount == 1 ? 1000 : (long)(0.94 * _PlayerCount + 15); + MillisBetweenScoreSyncStatePackets = _PlayerCount == 1 ? 1000 : (long)(1.5 * _PlayerCount + 20); return true; } } @@ -93,8 +93,8 @@ public void RemovePlayer(IPlayer player) _playersByRemoteEndPoint.Remove(player.Endpoint, out _); _playersByConnectionId.Remove(player.ConnectionId, out _); _PlayerCount--; - MillisBetweenPoseSyncStatePackets = (long)(0.94 * _PlayerCount + 15); - MillisBetweenScoreSyncStatePackets = (long)(1.5 * _PlayerCount + 20); + MillisBetweenPoseSyncStatePackets = _PlayerCount == 1 ? 1000 : (long)(0.94 * _PlayerCount + 15); + MillisBetweenScoreSyncStatePackets = _PlayerCount == 1 ? 1000 : (long)(1.5 * _PlayerCount + 20); } } } From 0330223bfb9d082ab4b5f250cd402529b017d27d Mon Sep 17 00:00:00 2001 From: cubic Date: Wed, 15 May 2024 00:21:51 +0100 Subject: [PATCH 110/120] fix wrongly named function --- BeatTogether.DedicatedServer.Kernel/PacketSource.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index dd1f3b88..801b4e3e 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -118,24 +118,22 @@ public void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, IgnoranceC { if (_configuration.DisableNotes || (_playerRegistry.GetPlayerCount() >= _configuration.DisableNotesPlayerCount) && !_configuration.ForceEnableNotes) return; - method = IgnoranceChannelTypes.Unthrottled; break; } else if (packet is NodePoseSyncStatePacket) { - if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncState) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets()) + if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncState) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenPoseSyncStateDeltaPackets()) { - _logger.Verbose($"Skipping sync state packet from {sender.ConnectionId} (Secret='{sender.Instance._configuration.Secret}')."); + //_logger.Verbose($"Skipping sync state packet from {sender.ConnectionId} (Secret='{sender.Instance._configuration.Secret}')."); return; } - method = IgnoranceChannelTypes.Unthrottled; sender.TicksAtLastSyncState = DateTime.UtcNow.Ticks; } else if (packet is NodePoseSyncStateDeltaPacket) { - if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncStateDelta) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenSyncStatePackets()) + if ((DateTime.UtcNow.Ticks - sender.TicksAtLastSyncStateDelta) / TimeSpan.TicksPerMillisecond < _playerRegistry.GetMillisBetweenPoseSyncStateDeltaPackets()) { - _logger.Verbose($"Skipping sync state packet from {sender.ConnectionId} (Secret='{sender.Instance._configuration.Secret}')."); + //_logger.Verbose($"Skipping sync state packet from {sender.ConnectionId} (Secret='{sender.Instance._configuration.Secret}')."); return; } sender.TicksAtLastSyncStateDelta = DateTime.UtcNow.Ticks; From dd7d5007603c395e26a6cdb5ff28c5a5f427e423 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 16 Jun 2024 13:30:39 +0200 Subject: [PATCH 111/120] Log score for debugging --- .../GameplayRpc/LevelFinishedPacketHandler.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/LevelFinishedPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/LevelFinishedPacketHandler.cs index 3fb5b5b5..82cb94ec 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/LevelFinishedPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/GameplayRpc/LevelFinishedPacketHandler.cs @@ -20,7 +20,9 @@ public override void Handle(IPlayer sender, LevelFinishedPacket packet) { _logger.Debug( $"Handling packet of type '{nameof(LevelFinishedPacket)}' " + - $"(SenderId={sender.ConnectionId})." + $"(SenderId={sender.ConnectionId}, HasValue0={packet.HasValue0}, HasAnyResult={packet.Results.HasAnyResult()}, " + + $"ModifiedScore={(packet.HasValue0 && packet.Results.HasAnyResult() ? packet.Results.LevelCompletionResults.ModifiedScore : "NoValue/NoResults" )}, " + + $"MultipliedScore={(packet.HasValue0 && packet.Results.HasAnyResult() ? packet.Results.LevelCompletionResults.MultipliedScore : "NoValue/NoResults")})." ); _gameplayManager.HandleLevelFinished(sender, packet); From dfc327dc13d88160257b14104b65bc2124fb16ca Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 16 Jun 2024 15:59:54 +0200 Subject: [PATCH 112/120] Fix spacing for log line --- .../PacketHandlers/PlayerStatePacketHandler.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs index d6621d66..43635cc4 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/PlayerStatePacketHandler.cs @@ -19,10 +19,10 @@ public override void Handle(IPlayer sender, PlayerStatePacket packet) { _logger.Debug( $"Handling packet of type '{nameof(PlayerStatePacket)}' " + - $"(SenderId={sender.ConnectionId}, IsPlayer={packet.PlayerState.Contains("player")}" + - $"IsActive={packet.PlayerState.Contains("is_active")}, WantsToPlayNextLevel={packet.PlayerState.Contains("wants_to_play_next_level")}" + - $"IsSpectating={packet.PlayerState.Contains("spectating")}, InMenu={packet.PlayerState.Contains("in_menu")}" + - $"backgrounded={packet.PlayerState.Contains("backgrounded")}, in_gameplay={packet.PlayerState.Contains("in_gameplay")}" + + $"(SenderId={sender.ConnectionId}, IsPlayer={packet.PlayerState.Contains("player")}, " + + $"IsActive={packet.PlayerState.Contains("is_active")}, WantsToPlayNextLevel={packet.PlayerState.Contains("wants_to_play_next_level")}, " + + $"IsSpectating={packet.PlayerState.Contains("spectating")}, InMenu={packet.PlayerState.Contains("in_menu")}, " + + $"backgrounded={packet.PlayerState.Contains("backgrounded")}, in_gameplay={packet.PlayerState.Contains("in_gameplay")}, " + $"was_active_at_level_start={packet.PlayerState.Contains("was_active_at_level_start")}, finished_level={packet.PlayerState.Contains("finished_level")})." ); From c8bd9e08840c993c730c7d0eaca2dc047f9438a7 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 16 Jun 2024 16:06:27 +0200 Subject: [PATCH 113/120] Additional logging when countdown is cancelled --- .../Managers/LobbyManager.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index cd7b36e5..8d1df527 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -211,7 +211,11 @@ private void CountingDown(bool isReady, bool NotStartable) //If the beatmap is not playable or the game is not startable if ( NotStartable ) { - _logger.Debug("Canceling countdown"); + _logger.Debug($"Canceling countdown check SelectedBeatmapNotNull={SelectedBeatmap != null}"); + foreach (var p in _playerRegistry.Players.Where(p => (p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned) && !p.IsSpectating && !p.IsBackgrounded && p.WantsToPlayNextLevel)) + { + _logger.Debug($"Player causing cancel UserId={p.HashedUserId} Username={p.UserName} Entitlement={p.GetEntitlement(SelectedBeatmap.LevelId)} IsSpectating={p.IsSpectating} IsBackgrounded={p.IsBackgrounded} WantsToPlayNextLevel={p.WantsToPlayNextLevel}"); + } CancelCountdown(); return; } From b32cc25e1b27abf7b1251db175ada2d65288e33e Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 16 Jun 2024 19:01:47 +0200 Subject: [PATCH 114/120] Fix nullref in added logging --- BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 8d1df527..35840a40 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -212,9 +212,9 @@ private void CountingDown(bool isReady, bool NotStartable) if ( NotStartable ) { _logger.Debug($"Canceling countdown check SelectedBeatmapNotNull={SelectedBeatmap != null}"); - foreach (var p in _playerRegistry.Players.Where(p => (p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned) && !p.IsSpectating && !p.IsBackgrounded && p.WantsToPlayNextLevel)) + foreach (var p in _playerRegistry.Players.Where(p => (SelectedBeatmap != null && p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned) && !p.IsSpectating && !p.IsBackgrounded && p.WantsToPlayNextLevel)) { - _logger.Debug($"Player causing cancel UserId={p.HashedUserId} Username={p.UserName} Entitlement={p.GetEntitlement(SelectedBeatmap.LevelId)} IsSpectating={p.IsSpectating} IsBackgrounded={p.IsBackgrounded} WantsToPlayNextLevel={p.WantsToPlayNextLevel}"); + _logger.Debug($"Player causing cancel UserId={p.HashedUserId} Username={p.UserName} Entitlement={(SelectedBeatmap != null ? p.GetEntitlement(SelectedBeatmap.LevelId) : "SelectedBeatmap is null")} IsSpectating={p.IsSpectating} IsBackgrounded={p.IsBackgrounded} WantsToPlayNextLevel={p.WantsToPlayNextLevel}"); } CancelCountdown(); return; From 57bcd69649ba936af942ed752b9b06c4013f2b8c Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sat, 13 Jul 2024 22:08:30 +0200 Subject: [PATCH 115/120] Register PerPlayer and GetPerPlayer packets --- .../Registries/MultiplayerCorePacketRegistry.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs index 74c9b0ba..37ef38ec 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs @@ -21,6 +21,8 @@ public override void Register() AddPacket(); AddPacket(); AddPacket(); + AddPacket(); + AddPacket(); } public bool TryCreatePacket(string packetId, [MaybeNullWhen(false)] out INetSerializable packet) From b8d96febe8df7630ec8e77708c1b3d87307f8ce9 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sat, 13 Jul 2024 22:55:51 +0200 Subject: [PATCH 116/120] Rename PerPlayer packets --- .../CommandHandlers/SetPerPlayerDiffHandler.cs | 2 +- .../CommandHandlers/SetPerPlayerModHandler.cs | 2 +- ...ayerHandler.cs => GetMpPerPlayerPacketHandler.cs} | 12 ++++++------ ...rPlayerHandler.cs => MpPerPlayerPacketHandler.cs} | 12 ++++++------ .../{GetPerPlayer.cs => GetMpPerPlayerPacket.cs} | 2 +- .../{PerPlayer.cs => MpPerPlayerPacket.cs} | 2 +- .../Registries/MultiplayerCorePacketRegistry.cs | 4 ++-- 7 files changed, 18 insertions(+), 18 deletions(-) rename BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/{GetPerPlayerHandler.cs => GetMpPerPlayerPacketHandler.cs} (69%) rename BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/{PerPlayerHandler.cs => MpPerPlayerPacketHandler.cs} (74%) rename BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/{GetPerPlayer.cs => GetMpPerPlayerPacket.cs} (85%) rename BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/{PerPlayer.cs => MpPerPlayerPacket.cs} (91%) diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs index 771255ce..0224708d 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerDiffHandler.cs @@ -25,7 +25,7 @@ public override void Handle(IPlayer player, SetPerPlayerDifficulties command) { Text = "Per player difficulties: " + command.Enabled }, IgnoranceChannelTypes.Reliable); - _packetDisapatcher.SendToNearbyPlayers(new PerPlayer() + _packetDisapatcher.SendToNearbyPlayers(new MpPerPlayerPacket() { PPDEnabled = _Configuration.AllowPerPlayerDifficulties, PPMEnabled = _Configuration.AllowPerPlayerModifiers, diff --git a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs index 56f8fb67..a7baf5f9 100644 --- a/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/CommandHandlers/SetPerPlayerModHandler.cs @@ -26,7 +26,7 @@ public override void Handle(IPlayer player, SetPerPlayerModifiers command) { Text = "Per player modifiers: " + command.Enabled }, IgnoranceChannelTypes.Reliable); - _packetDisapatcher.SendToNearbyPlayers(new PerPlayer() + _packetDisapatcher.SendToNearbyPlayers(new MpPerPlayerPacket() { PPDEnabled = _Configuration.AllowPerPlayerDifficulties, PPMEnabled = _Configuration.AllowPerPlayerModifiers, diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetPerPlayerHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetMpPerPlayerPacketHandler.cs similarity index 69% rename from BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetPerPlayerHandler.cs rename to BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetMpPerPlayerPacketHandler.cs index 225272f4..b367bed2 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetPerPlayerHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/GetMpPerPlayerPacketHandler.cs @@ -6,13 +6,13 @@ namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { - class GetPerPlayerHandler : BasePacketHandler + class GetMpPerPlayerPacketHandler : BasePacketHandler { private readonly InstanceConfiguration _configuration; private readonly IPacketDispatcher _PacketDispatcher; - private readonly ILogger _logger = Log.ForContext(); + private readonly ILogger _logger = Log.ForContext(); - public GetPerPlayerHandler( + public GetMpPerPlayerPacketHandler( IPacketDispatcher PacketDispatcher, InstanceConfiguration configuration) { @@ -20,14 +20,14 @@ public GetPerPlayerHandler( _configuration = configuration; } - public override void Handle(IPlayer sender, GetPerPlayer packet) + public override void Handle(IPlayer sender, GetMpPerPlayerPacket packet) { _logger.Debug( - $"Handling packet of type '{nameof(GetPerPlayer)}' " + + $"Handling packet of type '{nameof(GetMpPerPlayerPacket)}' " + $"(SenderId={sender.ConnectionId})." ); - _PacketDispatcher.SendToPlayer(sender, new PerPlayer() + _PacketDispatcher.SendToPlayer(sender, new MpPerPlayerPacket() { PPDEnabled = _configuration.AllowPerPlayerDifficulties, PPMEnabled = _configuration.AllowPerPlayerModifiers, diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/PerPlayerHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MpPerPlayerPacketHandler.cs similarity index 74% rename from BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/PerPlayerHandler.cs rename to BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MpPerPlayerPacketHandler.cs index 533d36ff..c4775d94 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/PerPlayerHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MpPerPlayerPacketHandler.cs @@ -6,13 +6,13 @@ namespace BeatTogether.DedicatedServer.Kernel.PacketHandlers.MultiplayerSession.MenuRpc { - class PerPlayerHandler : BasePacketHandler + class MpPerPlayerPacketHandler : BasePacketHandler { private readonly InstanceConfiguration _configuration; private readonly IPacketDispatcher _PacketDispatcher; - private readonly ILogger _logger = Log.ForContext(); + private readonly ILogger _logger = Log.ForContext(); - public PerPlayerHandler( + public MpPerPlayerPacketHandler( IPacketDispatcher PacketDispatcher, InstanceConfiguration configuration) { @@ -20,18 +20,18 @@ public PerPlayerHandler( _configuration = configuration; } - public override void Handle(IPlayer sender, PerPlayer packet) + public override void Handle(IPlayer sender, MpPerPlayerPacket packet) { _logger.Debug( - $"Handling packet of type '{nameof(PerPlayer)}' " + + $"Handling packet of type '{nameof(MpPerPlayerPacket)}' " + $"(SenderId={sender.ConnectionId})." ); if(sender.IsServerOwner) { _configuration.AllowPerPlayerDifficulties = packet.PPDEnabled; _configuration.AllowPerPlayerModifiers = packet.PPMEnabled; - _PacketDispatcher.SendToNearbyPlayers(new PerPlayer() + _PacketDispatcher.SendToNearbyPlayers(new MpPerPlayerPacket() { PPDEnabled = _configuration.AllowPerPlayerDifficulties, PPMEnabled = _configuration.AllowPerPlayerModifiers, diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetPerPlayer.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetMpPerPlayerPacket.cs similarity index 85% rename from BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetPerPlayer.cs rename to BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetMpPerPlayerPacket.cs index 67e7a923..a15f2f5b 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetPerPlayer.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/GetMpPerPlayerPacket.cs @@ -3,7 +3,7 @@ namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets { - public sealed class GetPerPlayer : INetSerializable + public sealed class GetMpPerPlayerPacket : INetSerializable { public void ReadFrom(ref SpanBuffer bufferReader) { diff --git a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/PerPlayer.cs b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPerPlayerPacket.cs similarity index 91% rename from BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/PerPlayer.cs rename to BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPerPlayerPacket.cs index 0dad8bfb..3877d5a0 100644 --- a/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/PerPlayer.cs +++ b/BeatTogether.DedicatedServer.Messaging/Packets/MultiplayerSession/MpCorePackets/MpPerPlayerPacket.cs @@ -3,7 +3,7 @@ namespace BeatTogether.DedicatedServer.Messaging.Packets.MultiplayerSession.MpCorePackets { - public sealed class PerPlayer : INetSerializable + public sealed class MpPerPlayerPacket : INetSerializable { public bool PPDEnabled; public bool PPMEnabled; diff --git a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs index 37ef38ec..949f535e 100644 --- a/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs +++ b/BeatTogether.DedicatedServer.Messaging/Registries/MultiplayerCorePacketRegistry.cs @@ -21,8 +21,8 @@ public override void Register() AddPacket(); AddPacket(); AddPacket(); - AddPacket(); - AddPacket(); + AddPacket(); + AddPacket(); } public bool TryCreatePacket(string packetId, [MaybeNullWhen(false)] out INetSerializable packet) From ae45643296954e454c1f31698333f20845bd7df4 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 14 Jul 2024 23:27:48 +0200 Subject: [PATCH 117/120] Add chonky logging to StartLevel when per player difficulty and per player modifiers are enabled --- .../Managers/LobbyManager.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index 35840a40..f6b580a7 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -211,7 +211,7 @@ private void CountingDown(bool isReady, bool NotStartable) //If the beatmap is not playable or the game is not startable if ( NotStartable ) { - _logger.Debug($"Canceling countdown check SelectedBeatmapNotNull={SelectedBeatmap != null}"); + _logger.Debug($"Canceling countdown check SelectedBeatmapNull={SelectedBeatmap == null}"); foreach (var p in _playerRegistry.Players.Where(p => (SelectedBeatmap != null && p.GetEntitlement(SelectedBeatmap.LevelId) is EntitlementStatus.NotOwned) && !p.IsSpectating && !p.IsBackgrounded && p.WantsToPlayNextLevel)) { _logger.Debug($"Player causing cancel UserId={p.HashedUserId} Username={p.UserName} Entitlement={(SelectedBeatmap != null ? p.GetEntitlement(SelectedBeatmap.LevelId) : "SelectedBeatmap is null")} IsSpectating={p.IsSpectating} IsBackgrounded={p.IsBackgrounded} WantsToPlayNextLevel={p.WantsToPlayNextLevel}"); @@ -388,6 +388,11 @@ private void StartBeatmapPacket() { if (_configuration.AllowPerPlayerDifficulties && player.BeatmapIdentifier != null && diff != null && diff.ContainsKey((uint)player.BeatmapIdentifier.Difficulty)) bm.Difficulty = player.BeatmapIdentifier.Difficulty; + _logger.Debug($"Start level settings for player '{player.UserName}|{player.HashedUserId}'" + + $"(LevelId={bm.LevelId}, Difficulty={bm.Difficulty} Modifiers={(_configuration.AllowPerPlayerModifiers ? player.Modifiers : SelectedModifiers)}) " + + $"Checks: (AllowPerPlayerDifficulties={_configuration.AllowPerPlayerDifficulties}, " + + $"Original Difficulty={SelectedBeatmap?.Difficulty}, Player Difficulty={player.BeatmapIdentifier?.Difficulty}, " + + $"diff.ContainsKey={(player.BeatmapIdentifier?.Difficulty != null ? diff?.ContainsKey((uint)player.BeatmapIdentifier.Difficulty) : "Player Beatmap null")})"); _packetDispatcher.SendToPlayer(player, new StartLevelPacket { Beatmap = bm!, From dc4d1b493c017542f4ff59aab54c91906e897f94 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Mon, 15 Jul 2024 20:11:09 +0200 Subject: [PATCH 118/120] Fix PPD --- .../Managers/LobbyManager.cs | 23 ++++++++++++------- .../MpPerPlayerPacketHandler.cs | 3 ++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs index f6b580a7..872580f7 100644 --- a/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs +++ b/BeatTogether.DedicatedServer.Kernel/Managers/LobbyManager.cs @@ -24,7 +24,7 @@ */ namespace BeatTogether.DedicatedServer.Kernel.Managers { - public sealed class LobbyManager : ILobbyManager, IDisposable + public sealed class LobbyManager : ILobbyManager, IDisposable { public bool AllPlayersReady => _playerRegistry.Players.All(p => p.IsReady || !p.WantsToPlayNextLevel || p.IsBackgrounded || p.IsSpectating); //If all are ready or spectating or backgrounded or a spectator type public bool AnyPlayersReady => _playerRegistry.Players.Any(p => p.IsReady && p.WantsToPlayNextLevel && !p.IsBackgrounded && !p.IsSpectating); //If anyone who is active wants to play @@ -321,15 +321,20 @@ private void UpdatePlayersMissingEntitlementsMessages() { if (!SelectedBeatmap!.LevelId.StartsWith("custom_level_")) { - return null; - } + return null; + } + + var selectedLevelHash = SelectedBeatmap!.LevelId.Substring(13); + foreach (var player in _playerRegistry.Players) { - if(SelectedBeatmap!.LevelId == player.MapHash) + _logger.Verbose($"GetDiffRequirements checking: SelectedHash {selectedLevelHash} Player MapHash {player.MapHash}"); + if(selectedLevelHash == player.MapHash) { return player.BeatmapDifficultiesRequirements; } } + _logger.Error($"Failed to find matching requirements searched SelectedHash {selectedLevelHash}"); return null; } @@ -386,16 +391,18 @@ private void StartBeatmapPacket() BeatmapIdentifier bm = SelectedBeatmap!; foreach (var player in _playerRegistry.Players) { - if (_configuration.AllowPerPlayerDifficulties && player.BeatmapIdentifier != null && diff != null && diff.ContainsKey((uint)player.BeatmapIdentifier.Difficulty)) + // Check that PPD is enabled and that the difficulty the player has selected + // exists on the level or if the player has the same map selected + if (_configuration.AllowPerPlayerDifficulties && player.BeatmapIdentifier != null && (diff != null && diff.ContainsKey((uint)player.BeatmapIdentifier.Difficulty) || SelectedBeatmap.LevelId == player.BeatmapIdentifier.LevelId)) bm.Difficulty = player.BeatmapIdentifier.Difficulty; _logger.Debug($"Start level settings for player '{player.UserName}|{player.HashedUserId}'" + $"(LevelId={bm.LevelId}, Difficulty={bm.Difficulty} Modifiers={(_configuration.AllowPerPlayerModifiers ? player.Modifiers : SelectedModifiers)}) " + $"Checks: (AllowPerPlayerDifficulties={_configuration.AllowPerPlayerDifficulties}, " + - $"Original Difficulty={SelectedBeatmap?.Difficulty}, Player Difficulty={player.BeatmapIdentifier?.Difficulty}, " + - $"diff.ContainsKey={(player.BeatmapIdentifier?.Difficulty != null ? diff?.ContainsKey((uint)player.BeatmapIdentifier.Difficulty) : "Player Beatmap null")})"); + $"diff == null? {diff == null}, " + + $"diff.ContainsKey={(player.BeatmapIdentifier?.Difficulty != null && diff != null ? diff.ContainsKey((uint)player.BeatmapIdentifier.Difficulty) : "Player beatmap null or diff null")})"); _packetDispatcher.SendToPlayer(player, new StartLevelPacket { - Beatmap = bm!, + Beatmap = bm!, Modifiers = _configuration.AllowPerPlayerModifiers ? player.Modifiers : SelectedModifiers, StartTime = CountdownEndTime }, IgnoranceChannelTypes.Reliable); diff --git a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MpPerPlayerPacketHandler.cs b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MpPerPlayerPacketHandler.cs index c4775d94..42d7eb53 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MpPerPlayerPacketHandler.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketHandlers/MultiplayerSession/MultiplayerCore/MpPerPlayerPacketHandler.cs @@ -25,7 +25,8 @@ public override void Handle(IPlayer sender, MpPerPlayerPacket packet) _logger.Debug( $"Handling packet of type '{nameof(MpPerPlayerPacket)}' " + - $"(SenderId={sender.ConnectionId})." + $"(SenderId={sender.ConnectionId})" + + $"(PPDEnabled={packet.PPDEnabled}, PPMEnabled={packet.PPMEnabled})." ); if(sender.IsServerOwner) { From cbe1fd098703ab652d18217907053197e5aa3725 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sat, 27 Jul 2024 19:22:44 +0200 Subject: [PATCH 119/120] Add Invalidated bool to LevelCompletionResults --- .../Models/LevelCompletionResults.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs b/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs index b970401f..26149a2f 100644 --- a/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs +++ b/BeatTogether.DedicatedServer.Messaging/Models/LevelCompletionResults.cs @@ -31,6 +31,7 @@ public sealed class LevelCompletionResults : INetSerializable public float AverageCutScoreForNotesWithFullScoreScoringType { get; set; } public int MaxCombo { get; set; } public float EndSongTime { get; set; } + public bool Invalidated { get; set; } public void ReadFrom(ref SpanBuffer reader) { @@ -58,6 +59,7 @@ public void ReadFrom(ref SpanBuffer reader) AverageCutScoreForNotesWithFullScoreScoringType = reader.ReadFloat32(); MaxCombo = reader.ReadVarInt(); EndSongTime = reader.ReadFloat32(); + Invalidated = reader.ReadBool(); // Added in 1.37.1 } public void WriteTo(ref SpanBuffer writer) @@ -86,6 +88,7 @@ public void WriteTo(ref SpanBuffer writer) writer.WriteFloat32(AverageCutScoreForNotesWithFullScoreScoringType); writer.WriteVarInt(MaxCombo); writer.WriteFloat32(EndSongTime); + writer.WriteBool(Invalidated); // Added in 1.37.1 } } } From d196b46d9e103073ace239bff5e7226d1828cbae Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sat, 27 Jul 2024 19:52:53 +0200 Subject: [PATCH 120/120] Ensure we account for packets having more data than expected --- BeatTogether.DedicatedServer.Kernel/PacketSource.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs index 801b4e3e..ebcc90de 100644 --- a/BeatTogether.DedicatedServer.Kernel/PacketSource.cs +++ b/BeatTogether.DedicatedServer.Kernel/PacketSource.cs @@ -167,6 +167,11 @@ public void OnReceive(EndPoint remoteEndPoint, ref SpanBuffer reader, IgnoranceC continue; } + // Ensure we always skip/rewind our reader + var processedBytesToSkip = HandleRead.Offset - prevPosition; + try { HandleRead.SkipBytes((int)length - processedBytesToSkip); } + catch (EndOfBufferException) { _logger.Warning("Packet was an incorrect length"); goto RoutePacket; } + ((Abstractions.IPacketHandler)packetHandler).Handle(sender, packet); } RoutePacket: