Major refactors and cleanup

* Add gameserver constructor to enable state-sharing
* Reorganize project setup
* Make library netstandard2.1 and disable executable generation
* Make new playground project for anyone to play around with without affecting the library build
This commit is contained in:
Mooshua 2023-08-12 22:28:25 -07:00
parent 2ab5710c11
commit 4af55e27a9
11 changed files with 117 additions and 41 deletions

View File

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<DockerDefaultTargetOS>Windows</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<Content Include="..\.dockerignore">
<Link>.dockerignore</Link>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BattleBitAPI\BattleBitAPI.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,18 @@
FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["CommunityServerAPI.Playground/CommunityServerAPI.Playground.csproj", "CommunityServerAPI.Playground/"]
RUN dotnet restore "CommunityServerAPI.Playground/CommunityServerAPI.Playground.csproj"
COPY . .
WORKDIR "/src/CommunityServerAPI.Playground"
RUN dotnet build "CommunityServerAPI.Playground.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "CommunityServerAPI.Playground.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "CommunityServerAPI.Playground.dll"]

View File

@ -69,7 +69,6 @@ class MyGameServer : GameServer<MyPlayer>
args.Killer.IsZombie = true;
args.Killer.SetHeavyGadget(Gadgets.SledgeHammer.ToString(), 0, true);
var position = args.Killer.GetPosition();
}
}

View File

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>netstandard2.1</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<RootNamespace>CommunityServerAPI</RootNamespace>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<None Update="BattleBitAPI.Playground\Dockerfile">
<Link>CommunityServerAPI.Playground\Dockerfile</Link>
</None>
</ItemGroup>
</Project>

View File

@ -12,7 +12,7 @@ namespace BattleBitAPI.Server
{
public class GameServer<TPlayer> : System.IDisposable where TPlayer : Player<TPlayer>
{
// ---- Public Variables ----
// ---- Public Variables ----
public ulong ServerHash => mInternal.ServerHash;
public bool IsConnected => mInternal.IsConnected;
public IPAddress GameIP => mInternal.GameIP;
@ -37,7 +37,7 @@ namespace BattleBitAPI.Server
public string TerminationReason => mInternal.TerminationReason;
public bool ReconnectFlag => mInternal.ReconnectFlag;
// ---- Private Variables ----
// ---- Private Variables ----
private Internal mInternal;
// ---- Tick ----
@ -235,7 +235,7 @@ namespace BattleBitAPI.Server
return false;
}
// ---- Virtual ----
// ---- Virtual ----
public virtual async Task OnConnected()
{
@ -704,9 +704,9 @@ namespace BattleBitAPI.Server
}
// ---- Static ----
public static TGameServer CreateInstance<TGameServer>(Internal @internal) where TGameServer : GameServer<TPlayer>
public static TGameServer CreateInstance<TGameServer>(Internal @internal, GameserverConstructor<TGameServer, TPlayer> constructor) where TGameServer : GameServer<TPlayer>
{
TGameServer gameServer = (TGameServer)Activator.CreateInstance(typeof(TGameServer));
var gameServer = constructor.Create();
gameServer.mInternal = @internal;
return gameServer;
}
@ -714,7 +714,7 @@ namespace BattleBitAPI.Server
// ---- Internal ----
public class Internal
{
// ---- Variables ----
// ---- Variables ----
public ulong ServerHash;
public bool IsConnected;
public IPAddress GameIP;
@ -739,7 +739,7 @@ namespace BattleBitAPI.Server
public string TerminationReason;
public bool ReconnectFlag;
// ---- Private Variables ----
// ---- Private Variables ----
public byte[] mKeepAliveBuffer;
public Common.Serialization.Stream mWriteStream;
public Common.Serialization.Stream mReadStream;
@ -780,26 +780,26 @@ namespace BattleBitAPI.Server
this.RoundSettings = new RoundSettings<TPlayer>(this);
}
// ---- Players In Room ----
// ---- Players In Room ----
public Dictionary<ulong, Player<TPlayer>> Players = new Dictionary<ulong, Player<TPlayer>>(254);
// ---- Room Settings ----
// ---- Room Settings ----
public mRoomSettings _RoomSettings = new mRoomSettings();
public bool IsDirtyRoomSettings;
// ---- Round Settings ----
// ---- Round Settings ----
public mRoundSettings _RoundSettings = new mRoundSettings();
public bool IsDirtyRoundSettings;
// ---- Map Rotation ----
// ---- Map Rotation ----
public HashSet<string> _MapRotation = new HashSet<string>(8);
public bool IsDirtyMapRotation = false;
// ---- Gamemode Rotation ----
// ---- Gamemode Rotation ----
public HashSet<string> _GamemodeRotation = new HashSet<string>(8);
public bool IsDirtyGamemodeRotation = false;
// ---- Public Functions ----
// ---- Public Functions ----
public void Set(Func<GameServer<TPlayer>, Internal, Common.Serialization.Stream, Task> func, TcpClient socket, IPAddress iP, int port, bool isPasswordProtected, string serverName, string gamemode, string map, MapSize mapSize, MapDayNight dayNight, int currentPlayers, int inQueuePlayers, int maxPlayers, string loadingScreenText, string serverRulesText)
{
this.ServerHash = ((ulong)port << 32) | (ulong)iP.ToUInt();

View File

@ -0,0 +1,15 @@
namespace BattleBitAPI.Server;
public class GameserverConstructor<TGameServer, TPlayer>
where TGameServer: GameServer<TPlayer>
where TPlayer: Player<TPlayer>
{
public virtual TGameServer Create()
{
TGameServer gameServer = (TGameServer)Activator.CreateInstance(typeof(TGameServer));
return gameServer;
}
}

View File

@ -12,21 +12,21 @@ namespace BattleBitAPI.Server
{
public class ServerListener<TPlayer, TGameServer> : IDisposable where TPlayer : Player<TPlayer> where TGameServer : GameServer<TPlayer>
{
// --- Public ---
// --- Public ---
public bool IsListening { get; private set; }
public bool IsDisposed { get; private set; }
public int ListeningPort { get; private set; }
// --- Events ---
// --- Events ---
/// <summary>
/// Fired when an attempt made to connect to the server.<br/>
/// Default, any connection attempt will be accepted
/// </summary>
///
///
/// <remarks>
/// IPAddress: IP of incoming connection <br/>
/// </remarks>
///
///
/// <value>
/// Returns: true if allow connection, false if deny the connection.
/// </value>
@ -35,7 +35,7 @@ namespace BattleBitAPI.Server
/// <summary>
/// Fired when a game server connects.
/// </summary>
///
///
/// <remarks>
/// GameServer: Game server that is connecting.<br/>
/// </remarks>
@ -44,7 +44,7 @@ namespace BattleBitAPI.Server
/// <summary>
/// Fired when a game server reconnects. (When game server connects while a socket is already open)
/// </summary>
///
///
/// <remarks>
/// GameServer: Game server that is reconnecting.<br/>
/// </remarks>
@ -53,22 +53,22 @@ namespace BattleBitAPI.Server
/// <summary>
/// Fired when a game server disconnects. Check (GameServer.TerminationReason) to see the reason.
/// </summary>
///
///
/// <remarks>
/// GameServer: Game server that disconnected.<br/>
/// </remarks>
public Func<GameServer<TPlayer>, Task> OnGameServerDisconnected { get; set; }
// --- Private ---
// --- Private ---
private TcpListener mSocket;
private Dictionary<ulong, (TGameServer server, GameServer<TPlayer>.Internal resources)> mActiveConnections;
private mInstances<TPlayer, TGameServer> mInstanceDatabase;
// --- Construction ---
public ServerListener()
// --- Construction ---
public ServerListener(GameserverConstructor<TGameServer, TPlayer> constructor = null)
{
this.mActiveConnections = new Dictionary<ulong, (TGameServer, GameServer<TPlayer>.Internal)>(16);
this.mInstanceDatabase = new mInstances<TPlayer, TGameServer>();
this.mInstanceDatabase = new mInstances<TPlayer, TGameServer>(constructor ?? new GameserverConstructor<TGameServer, TPlayer>());
}
// --- Starting ---
@ -1040,7 +1040,7 @@ namespace BattleBitAPI.Server
return false;
}
// --- Disposing ---
// --- Disposing ---
public void Dispose()
{
//Already disposed?
@ -1052,14 +1052,16 @@ namespace BattleBitAPI.Server
Stop();
}
// --- Classes ---
// --- Classes ---
private class mInstances<TPlayer, TGameServer> where TPlayer : Player<TPlayer> where TGameServer : GameServer<TPlayer>
{
private Dictionary<ulong, (TGameServer, GameServer<TPlayer>.Internal)> mGameServerInstances;
private Dictionary<ulong, TPlayer> mPlayerInstances;
private GameserverConstructor<TGameServer, TPlayer> _constructor;
public mInstances()
public mInstances(GameserverConstructor<TGameServer, TPlayer> constructor)
{
_constructor = constructor;
this.mGameServerInstances = new Dictionary<ulong, (TGameServer, GameServer<TPlayer>.Internal)>(64);
this.mPlayerInstances = new Dictionary<ulong, TPlayer>(1024 * 16);
}
@ -1075,7 +1077,7 @@ namespace BattleBitAPI.Server
}
@internal = new GameServer<TPlayer>.Internal();
TGameServer gameServer = GameServer<TPlayer>.CreateInstance<TGameServer>(@internal);
TGameServer gameServer = GameServer<TPlayer>.CreateInstance<TGameServer>(@internal, _constructor);
mGameServerInstances.Add(hash, (gameServer, @internal));
return gameServer;

View File

@ -1,11 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
</Project>

View File

@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33205.214
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityServerAPI", "CommunityServerAPI.csproj", "{787887A1-8AEE-43E4-AF9B-A3883DE04486}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BattleBitAPI", "BattleBitAPI\BattleBitAPI.csproj", "{787887A1-8AEE-43E4-AF9B-A3883DE04486}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BattleBitAPI.Playground", "BattleBitAPI.Playground\BattleBitAPI.Playground.csproj", "{0A7D7C0C-5B0E-4B50-A2E9-A0B0E1ED486D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -15,6 +17,10 @@ Global
{787887A1-8AEE-43E4-AF9B-A3883DE04486}.Debug|Any CPU.Build.0 = Debug|Any CPU
{787887A1-8AEE-43E4-AF9B-A3883DE04486}.Release|Any CPU.ActiveCfg = Release|Any CPU
{787887A1-8AEE-43E4-AF9B-A3883DE04486}.Release|Any CPU.Build.0 = Release|Any CPU
{0A7D7C0C-5B0E-4B50-A2E9-A0B0E1ED486D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A7D7C0C-5B0E-4B50-A2E9-A0B0E1ED486D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A7D7C0C-5B0E-4B50-A2E9-A0B0E1ED486D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A7D7C0C-5B0E-4B50-A2E9-A0B0E1ED486D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

7
global.json Normal file
View File

@ -0,0 +1,7 @@
{
"sdk": {
"version": "6.0.0",
"rollForward": "latestMajor",
"allowPrerelease": true
}
}