-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a344bea
commit 44d928b
Showing
89 changed files
with
932 additions
and
787 deletions.
There are no files selected for viewing
11 changes: 11 additions & 0 deletions
11
BeatTogether.DedicatedServer.Instancing/Abstractions/IInstanceFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
BeatTogether.DedicatedServer.Instancing/Abstractions/IInstanceRegistry.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
...erver.Node/Abstractions/IPortAllocator.cs → ...Instancing/Abstractions/IPortAllocator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
BeatTogether.DedicatedServer.Instancing/BeatTogether.DedicatedServer.Instancing.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<LangVersion>9</LangVersion> | ||
<PackageIcon>icon.png</PackageIcon> | ||
<Authors>BeatTogether Team</Authors> | ||
<Company>BeatTogether</Company> | ||
<RepositoryUrl>https://github.com/beattogether/BeatTogether.DedicatedServer</RepositoryUrl> | ||
<Version>1.0.0</Version> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="BeatTogether.Core" Version="1.0.3" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\BeatTogether.DedicatedServer.Kernel\BeatTogether.DedicatedServer.Kernel.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
11 changes: 11 additions & 0 deletions
11
BeatTogether.DedicatedServer.Instancing/Configuration/InstancingConfiguration.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
BeatTogether.DedicatedServer.Instancing/Extensions/HostBuilderExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<InstancingConfiguration>("Instancing") | ||
.AddSingleton<IPortAllocator, PortAllocator>() | ||
.AddSingleton<IInstanceRegistry, InstanceRegistry>() | ||
.AddSingleton<IInstanceFactory, InstanceFactory>() | ||
.AddSingleton<ILayer2, LayerService>() | ||
); | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
BeatTogether.DedicatedServer.Instancing/Implimentations/ServerInstance.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<string> 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(); } | ||
} | ||
} |
104 changes: 104 additions & 0 deletions
104
BeatTogether.DedicatedServer.Instancing/InstanceFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<InstanceFactory>(); | ||
|
||
public InstanceFactory( | ||
IInstanceRegistry instanceRegistry, | ||
IServiceProvider serviceProvider, | ||
IPortAllocator portAllocator, | ||
InstancingConfiguration instancingConfiguration) | ||
{ | ||
_instanceRegistry = instanceRegistry; | ||
_serviceProvider = serviceProvider; | ||
_portAllocator = portAllocator; | ||
_config = instancingConfiguration; | ||
|
||
_SendEventsLayer = _serviceProvider.GetService<ILayer1>(); | ||
} | ||
|
||
public IDedicatedInstance? CreateInstance(IServerInstance serverInstance) | ||
{ | ||
var Port = _portAllocator.AcquirePort(); | ||
|
||
if (!Port.HasValue) | ||
return null; | ||
|
||
var scope = _serviceProvider.CreateScope(); | ||
|
||
var instanceConfig = scope.ServiceProvider.GetRequiredService<InstanceConfiguration>(); | ||
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<IDedicatedInstance>(); | ||
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); | ||
} | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
BeatTogether.DedicatedServer.Instancing/InstanceRegistry.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<string, IDedicatedInstance> _instances = new(); | ||
private readonly ConcurrentDictionary<string, IDedicatedInstance> _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); | ||
} | ||
} |
Oops, something went wrong.