Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion MultiplayerCore/Installers/MpAppInstaller.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using BeatSaverSharp;
using BGNet.Core.GameLift;
using MultiplayerCore.Beatmaps.Providers;
using MultiplayerCore.Networking;
using MultiplayerCore.NodePoseSyncState;
Expand All @@ -7,6 +8,7 @@
using MultiplayerCore.Players;
using MultiplayerCore.Repositories;
using SiraUtil.Zenject;
using System;
using Zenject;

namespace MultiplayerCore.Installers
Expand All @@ -31,11 +33,16 @@ public override void InstallBindings()
Container.Bind<MpLevelDownloader>().ToSelf().AsSingle();
Container.Bind<MpBeatmapLevelProvider>().ToSelf().AsSingle();
Container.BindInterfacesAndSelfTo<CustomLevelsPatcher>().AsSingle();
Container.BindInterfacesAndSelfTo<NetworkConfigPatcher>().AsSingle();
Container.BindInterfacesAndSelfTo<NetworkConfigPatcher>().AsSingle();
Container.BindInterfacesAndSelfTo<ModeSelectionPatcher>().AsSingle();
Container.BindInterfacesAndSelfTo<PlayerCountPatcher>().AsSingle();
Container.Bind<BGNetDebugLogger>().ToSelf().AsSingle();
Container.BindInterfacesAndSelfTo<MpStatusRepository>().AsSingle();

if (Container.HasBinding<IGameLiftPlayerSessionProvider>())
{
Plugin.Logger.Trace("IGameLiftPlayerSessionProvider found in AppInstaller");
}
}
}
}
17 changes: 14 additions & 3 deletions MultiplayerCore/Installers/MpMenuInstaller.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using MultiplayerCore.Patchers;
using BGNet.Core.GameLift;
using MultiplayerCore.Objects;
using MultiplayerCore.Patchers;
using MultiplayerCore.UI;
using Zenject;

Expand All @@ -15,8 +17,17 @@ public override void InstallBindings()
Container.BindInterfacesAndSelfTo<GameServerPlayerTableCellPatcher>().AsSingle();
Container.BindInterfacesAndSelfTo<BeatmapSelectionViewPatcher>().AsSingle();

// Inject sira stuff that didn't get injected on appinit
Container.Inject(Container.Resolve<NetworkPlayerEntitlementChecker>());
if (Container.HasBinding<IGameLiftPlayerSessionProvider>())
{
Plugin.Logger.Trace("IGameLiftPlayerSessionProvider found in MenuInstaller");
}

//Container.Rebind<IGameLiftPlayerSessionProvider>()
// .To<CustomPlayerSessionProvider>()
// .AsSingle();

// Inject sira stuff that didn't get injected on appinit
Container.Inject(Container.Resolve<NetworkPlayerEntitlementChecker>());
}

}
Expand Down
21 changes: 18 additions & 3 deletions MultiplayerCore/MultiplayerCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,17 @@
<None Remove="UI\RequirementsUI.bsml" />
</ItemGroup>
<ItemGroup>
<Reference Include="netstandard"/>
<Reference Include="BeatSaber.Multiplayer.Core" Publicize="true">
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\BeatSaber.Multiplayer.Core.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="BGLib.AppFlow" Publicize="true">
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\BGLib.AppFlow.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="netstandard" />
<Reference Include="Microsoft.CSharp">
<!--<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\Microsoft.CSharp.dll</HintPath>
<Private>False</Private>
Expand All @@ -57,6 +67,11 @@
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>-->
</Reference>
<Reference Include="OculusStudios.Platform.Core" Publicize="true">
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\OculusStudios.Platform.Core.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System">
<!--<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\System.dll</HintPath>
<Private>False</Private>
Expand Down Expand Up @@ -118,12 +133,12 @@
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\BGLib.UnityExtension.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="BGNet">
<Reference Include="BGNet" Publicize="true">
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\Ignorance.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="BGNetCore">
<Reference Include="BGNetCore" Publicize="true">
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\BGNetCore.dll</HintPath>
</Reference>
<Reference Include="BGNetLogging">
Expand Down
20 changes: 10 additions & 10 deletions MultiplayerCore/Networking/MpPacketSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,29 @@

namespace MultiplayerCore.Networking
{
public class MpPacketSerializer : INetworkPacketSubSerializer<IConnectedPlayer>, IInitializable, IDisposable
public class MpPacketSerializer : INetworkPacketSubSerializer<IBeatSaberConnectedPlayer>, IInitializable, IDisposable
{
private const int ID = 100;

private Dictionary<string, Action<NetDataReader, int, IConnectedPlayer>> packetHandlers = new();
private Dictionary<string, Action<NetDataReader, int, IBeatSaberConnectedPlayer>> packetHandlers = new();
private List<Type> registeredTypes = new();

private readonly MultiplayerSessionManager _sessionManager;
private readonly BeatSaberMultiplayerSessionManager _sessionManager;
private readonly SiraLog _logger;

internal MpPacketSerializer(
IMultiplayerSessionManager sessionManager,
IBeatSaberMultiplayerSessionManager sessionManager,
SiraLog logger)
{
_sessionManager = (sessionManager as MultiplayerSessionManager)!;
_sessionManager = (sessionManager as BeatSaberMultiplayerSessionManager)!;
_logger = logger;
}

public void Initialize()
=> _sessionManager.RegisterSerializer((MultiplayerSessionManager.MessageType)ID, this);
=> _sessionManager.RegisterSerializer((NetworkMessageType)ID, this);

public void Dispose()
=> _sessionManager.UnregisterSerializer((MultiplayerSessionManager.MessageType)ID, this);
=> _sessionManager.UnregisterSerializer((NetworkMessageType)ID, this);

/// <summary>
/// Method the base game uses to serialize an <see cref="INetSerializable"/>.
Expand All @@ -54,14 +54,14 @@ public void Serialize(NetDataWriter writer, INetSerializable packet)
/// <param name="reader">The buffer to read from</param>
/// <param name="length">Length of the packet</param>
/// <param name="data">The sender of the packet</param>
public void Deserialize(NetDataReader reader, int length, IConnectedPlayer data)
public void Deserialize(NetDataReader reader, int length, IBeatSaberConnectedPlayer data)
{
int prevPosition = reader.Position;
string packetId = reader.GetString();
length -= reader.Position - prevPosition;
prevPosition = reader.Position;

Action<NetDataReader, int, IConnectedPlayer> action;
Action<NetDataReader, int, IBeatSaberConnectedPlayer> action;
if (packetHandlers.TryGetValue(packetId, out action) && action != null)
{
try
Expand Down Expand Up @@ -141,7 +141,7 @@ public void RegisterType<TPacket>()
return packet!;
};

packetHandlers[packetId] = delegate (NetDataReader reader, int size, IConnectedPlayer player)
packetHandlers[packetId] = delegate (NetDataReader reader, int size, IBeatSaberConnectedPlayer player)
{
callback(deserialize(reader, size), player);
};
Expand Down
135 changes: 135 additions & 0 deletions MultiplayerCore/Objects/CustomPlayerSessionProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
using BGNet.Core.GameLift;
using IPA.Utilities;
using MultiplayerCore.Patchers;
using SiraUtil.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;

namespace MultiplayerCore.Objects
{
public class CustomPlayerSessionProvider : GameLiftPlayerSessionProvider, IGameLiftPlayerSessionProvider
{
internal NetworkConfigPatcher? _customNetconfig;
private readonly SiraLog _logger;
public CustomPlayerSessionProvider(INetworkConfig networkConfig, IMultiplayerStatusModel multiplayerStatusModel/*, NetworkConfigPatcher customNetconfig*/, SiraLog logger) : base(networkConfig, multiplayerStatusModel)
{
//_customNetconfig = customNetconfig;
_logger = logger;
}

public new async Task<PlayerSessionInfo> GetGameLiftPlayerSessionInfo(IAuthenticationTokenProvider authenticationTokenProvider, string userId, BeatmapLevelSelectionMask beatmapLevelSelectionMask, GameplayServerConfiguration gameplayServerConfiguration, string secret, string code, CancellationToken cancellationToken)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
string ticketId = null;
string placementId = null;
string graphAPIAccessToken = _networkConfig.graphAccessToken;
AuthenticationToken.PlatformType? userPlatform = null;
AuthenticationToken? singleUsePlatformAuthToken = null;
XPlatformAccessTokenData xPlatformAccessToken = await GetXPlatformAccessToken(authenticationTokenProvider, cancellationToken);
if (xPlatformAccessToken.IsValid())
{
userPlatform = authenticationTokenProvider.GetTokenPlatform(xPlatformAccessToken.platformEnvironment);
graphAPIAccessToken = xPlatformAccessToken.token;
}

try
{
int numAttempts = 0;
while (stopwatch.ElapsedMilliseconds < 120000 && !cancellationToken.IsCancellationRequested)
{
if (!xPlatformAccessToken.IsValid() || (_customNetconfig != null && _customNetconfig.IsOverridingApi))
{
singleUsePlatformAuthToken = await authenticationTokenProvider.GetAuthenticationToken();
userPlatform = singleUsePlatformAuthToken.Value.platform;
}

GetMultiplayerInstanceResponse getMatchmakingInstanceResponse;
try
{
numAttempts++;
getMatchmakingInstanceResponse = await _graphAPIClient.Post<GetMultiplayerInstanceRequest, GetMultiplayerInstanceResponse>("beat_saber_get_multiplayer_instance", graphAPIAccessToken, new GetMultiplayerInstanceRequest(Application.version, _networkConfig.serviceEnvironment, userId, beatmapLevelSelectionMask, gameplayServerConfiguration, userPlatform.Value, singleUsePlatformAuthToken?.userId, singleUsePlatformAuthToken?.sessionToken, secret, code, GetAverageLatencies(), ticketId, placementId, _networkConfig.customLocation), default(GraphAPIClient.PostOptions), cancellationToken);
}
catch (ConnectionFailedException ex) when (numAttempts <= 1 && ex.reason == ConnectionFailedReason.AuthenticationFailed)
{
xPlatformAccessToken = await GetXPlatformAccessToken(authenticationTokenProvider, cancellationToken, skipCache: true);
if (xPlatformAccessToken.IsValid())
{
userPlatform = authenticationTokenProvider.GetTokenPlatform(xPlatformAccessToken.platformEnvironment);
graphAPIAccessToken = xPlatformAccessToken.token;
}

continue;
}

if (getMatchmakingInstanceResponse.errorCode != 0 && getMatchmakingInstanceResponse.errorCode != MultiplayerPlacementErrorCode.RequestTimeout)
{
throw new ConnectionFailedException(getMatchmakingInstanceResponse.errorCode.ToConnectionFailedReason());
}

if (getMatchmakingInstanceResponse.playerSessionInfo != null && !string.IsNullOrEmpty(getMatchmakingInstanceResponse.playerSessionInfo.gameSessionId) && !string.IsNullOrEmpty(getMatchmakingInstanceResponse.playerSessionInfo.playerSessionId))
{
return getMatchmakingInstanceResponse.playerSessionInfo;
}

if (string.IsNullOrEmpty(getMatchmakingInstanceResponse.ticketId) && string.IsNullOrEmpty(getMatchmakingInstanceResponse.placementId))
{
throw new ConnectionFailedException(ConnectionFailedReason.Timeout);
}

ticketId = getMatchmakingInstanceResponse.ticketId;
placementId = getMatchmakingInstanceResponse.placementId;
if (getMatchmakingInstanceResponse.pollIntervalMs > 0)
{
await Task.Delay(getMatchmakingInstanceResponse.pollIntervalMs, cancellationToken);
}
}
}
catch (TaskCanceledException)
{
}

if (!cancellationToken.IsCancellationRequested)
{
throw new ConnectionFailedException(ConnectionFailedReason.FailedToFindMatch);
}

if (!string.IsNullOrEmpty(ticketId) || !string.IsNullOrEmpty(placementId))
{
if (!xPlatformAccessToken.IsValid())
{
singleUsePlatformAuthToken = await authenticationTokenProvider.GetAuthenticationToken();
userPlatform = singleUsePlatformAuthToken.Value.platform;
}

try
{
CancellationToken token = new CancellationTokenSource(TimeSpan.FromSeconds(5.0)).Token;
await _graphAPIClient.Post<GetMultiplayerInstanceRequest, GetMultiplayerInstanceResponse>("beat_saber_multiplayer_cancel_matchmaking_ticket", graphAPIAccessToken, new GetMultiplayerInstanceRequest(Application.version, _networkConfig.serviceEnvironment, userId, beatmapLevelSelectionMask, gameplayServerConfiguration, userPlatform.Value, singleUsePlatformAuthToken?.userId, singleUsePlatformAuthToken?.sessionToken, secret, code, GetAverageLatencies(), ticketId, placementId), default(GraphAPIClient.PostOptions), token);
}
catch
{
}
}

throw new TaskCanceledException("Cancelled Request");
}


internal void UpdateServer()
{
GameLiftPlayerSessionProvider instance = this as GameLiftPlayerSessionProvider;
instance.SetField(nameof(_graphAPIClient), new GraphAPIClient(_networkConfig.graphUrl, _networkConfig.graphAccessToken));
GetMultiplayerStatusData();
}


}
}
4 changes: 2 additions & 2 deletions MultiplayerCore/Objects/MpEntitlementChecker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ public class MpEntitlementChecker : NetworkPlayerEntitlementChecker
private ConcurrentDictionary<string, ConcurrentDictionary<string, EntitlementsStatus>> _entitlementsDictionary = new();
private ConcurrentDictionary<string, ConcurrentDictionary<string, TaskCompletionSource<EntitlementsStatus>>> _tcsDictionary = new();

private IMultiplayerSessionManager _sessionManager = null!;
private IBeatSaberMultiplayerSessionManager _sessionManager = null!;
private BeatSaver _beatsaver = null!;
private IPALogger _logger = null!;

[Inject]
internal void Inject(
IMultiplayerSessionManager sessionManager)
IBeatSaberMultiplayerSessionManager sessionManager)
{
_sessionManager = sessionManager;
_beatsaver = Plugin._beatsaver;
Expand Down
8 changes: 4 additions & 4 deletions MultiplayerCore/Objects/MpLevelLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ public class MpLevelLoader : MultiplayerLevelLoader, IProgress<double>

public ILevelGameplaySetupData? CurrentLoadingData => _gameplaySetupData;

internal readonly IMultiplayerSessionManager _sessionManager;
internal readonly IBeatSaberMultiplayerSessionManager _sessionManager;
internal readonly MpLevelDownloader _levelDownloader;
internal readonly MpEntitlementChecker _entitlementChecker;
internal readonly IMenuRpcManager _rpcManager;
internal readonly SiraLog _logger;

internal MpLevelLoader(
IMultiplayerSessionManager sessionManager,
IBeatSaberMultiplayerSessionManager sessionManager,
MpLevelDownloader levelDownloader,
NetworkPlayerEntitlementChecker entitlementChecker,
IMenuRpcManager rpcManager,
Expand Down Expand Up @@ -108,7 +108,7 @@ private async Task<LoadBeatmapLevelDataResult> DownloadBeatmapLevelAsync(string
// If the download fails we go into spectator
_rpcManager.SetIsEntitledToLevel(levelId, EntitlementsStatus.NotOwned);
_beatmapLevelData = null;
return LoadBeatmapLevelDataResult.Error;
return LoadBeatmapLevelDataResult.BeatmapLevelDataNotFound;
}

// Reload custom level set
Expand All @@ -120,7 +120,7 @@ private async Task<LoadBeatmapLevelDataResult> DownloadBeatmapLevelAsync(string

// Load level data
var method = AccessTools.Method(_beatmapLevelsModel.GetType(), nameof(_beatmapLevelsModel.LoadBeatmapLevelDataAsync));
LoadBeatmapLevelDataResult loadResult = LoadBeatmapLevelDataResult.Error;
LoadBeatmapLevelDataResult loadResult = LoadBeatmapLevelDataResult.BeatmapLevelDataNotFound;
if (method != null)
{
if (method.GetParameters().Length > 2)
Expand Down
Loading