Skip to content

Commit

Permalink
Allow Admins to create match config ( #43 #44)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheR00st3r committed Nov 19, 2023
1 parent c519ef6 commit 1ae837f
Show file tree
Hide file tree
Showing 12 changed files with 262 additions and 14 deletions.
25 changes: 25 additions & 0 deletions PugSharp.Config/ConfigCreator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace PugSharp.Config;

public class ConfigCreator
{
public ConfigCreator()
{
Config = new MatchConfig
{
// TODO Maybe use guid for demo, ...
MatchId = "CustomMatch",
Team1 = new Team
{
Name = "Team 1",

},
Team2 = new Team
{
Name = "Team 2",
},
TeamMode = TeamMode.Scramble,
};
}

public MatchConfig Config { get; }
}
5 changes: 4 additions & 1 deletion PugSharp.Config/MatchConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace PugSharp.Config;
public class MatchConfig
{
[JsonPropertyName("maplist")]
public required string[] Maplist { get; init; }
public IList<string> Maplist { get; } = new List<string>();

[JsonPropertyName("team1")]
public required Team Team1 { get; init; }
Expand Down Expand Up @@ -60,4 +60,7 @@ public class MatchConfig

[JsonPropertyName("server_locale")]
public string ServerLocale { get; init; } = "en";

[JsonPropertyName("team_mode")]
public TeamMode TeamMode { get; set; }
}
4 changes: 2 additions & 2 deletions PugSharp.Config/Team.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace PugSharp.Config;
public class Team
{
[JsonPropertyName("name")]
public required string Name { get; init; }
public required string Name { get; set; }

[JsonPropertyName("tag")]
public string Tag { get; init; } = string.Empty;
Expand All @@ -14,5 +14,5 @@ public class Team
public string Flag { get; init; } = string.Empty;

[JsonPropertyName("players")]
public required IDictionary<ulong, string> Players { get; init; }
public IDictionary<ulong, string> Players { get; init; } = new Dictionary<ulong, string>();
}
10 changes: 10 additions & 0 deletions PugSharp.Config/TeamMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace PugSharp.Config;

public enum TeamMode
{
// Take Teams as they are
Default,

// Scramble Teams afte all players are joined
Scramble,
}
1 change: 1 addition & 0 deletions PugSharp.Match.Contract/MatchCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ public enum MatchCommand
CompleteMap,
Pause,
Unpause,
TeamsDefined,
}
1 change: 1 addition & 0 deletions PugSharp.Match.Contract/MatchState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ public enum MatchState
MapCompleted,
MatchCompleted,
RestoreMatch,
DefineTeams,
}
12 changes: 9 additions & 3 deletions PugSharp.Match.Tests/MatchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ private static async Task VoteTeam(ICsServer csServer, MatchConfig config, Match

private static IPlayer VoteForMap(MatchConfig config, Match match, IPlayer player1, IPlayer player2)
{
var matchCount = config.Maplist.Length;
var matchCount = config.Maplist.Count;
var votePlayer = player1;

Assert.False(match.BanMap(votePlayer, matchCount));
Expand Down Expand Up @@ -210,7 +210,7 @@ private static MatchConfig CreateExampleConfig(IEnumerable<string>? mapList = nu
mapListInternal = mapList;
}

return new MatchConfig
var matchConfig = new MatchConfig
{
MatchId = "1337",
PlayersPerTeam = 1,
Expand All @@ -232,8 +232,14 @@ private static MatchConfig CreateExampleConfig(IEnumerable<string>? mapList = nu
{ 1,"Def" },
},
},
Maplist = mapListInternal.ToArray(),
};

foreach (var map in mapListInternal)
{
matchConfig.Maplist.Add(map);
}

return matchConfig;
}

private static IPlayer CreatePlayerSub(ulong steamId, int playerId)
Expand Down
52 changes: 47 additions & 5 deletions PugSharp.Match/Match.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using PugSharp.ApiStats;
using PugSharp.Match.Contract;
using PugSharp.Server.Contract;
using PugSharp.Shared;
using PugSharp.Translation;
using PugSharp.Translation.Properties;

Expand Down Expand Up @@ -85,7 +86,7 @@ private void Initialize(MatchInfo matchInfo)
throw new NotSupportedException("Initialize can onyl be called once!");
}

if (matchInfo.Config.Maplist.Length < matchInfo.Config.NumMaps)
if (matchInfo.Config.Maplist.Count < matchInfo.Config.NumMaps)
{
throw new NotSupportedException($"Can not create Match without the required number of maps! At lease {matchInfo.Config.NumMaps} are required!");
}
Expand Down Expand Up @@ -129,12 +130,17 @@ private void InitializeStateMachine()
.PermitDynamicIf(MatchCommand.LoadMatch, () => HasRestoredMatch() ? MatchState.RestoreMatch : MatchState.WaitingForPlayersConnectedReady);

_MatchStateMachine.Configure(MatchState.WaitingForPlayersConnectedReady)
.PermitDynamicIf(MatchCommand.PlayerReady, () => HasRestoredMatch() ? MatchState.MatchRunning : MatchState.MapVote, AllPlayersAreReady)
.PermitDynamicIf(MatchCommand.PlayerReady, () => HasRestoredMatch() ? MatchState.MatchRunning : MatchState.DefineTeams, AllPlayersAreReady)
.OnEntry(StartWarmup)
.OnEntry(SetAllPlayersNotReady)
.OnEntry(StartReadyReminder)
.OnExit(StopReadyReminder);

_MatchStateMachine.Configure(MatchState.DefineTeams)
.Permit(MatchCommand.TeamsDefined, MatchState.MapVote)
.OnEntry(ContinueIfDefault)
.OnEntry(ScrambleTeams);

_MatchStateMachine.Configure(MatchState.MapVote)
.PermitReentryIf(MatchCommand.VoteMap, MapIsNotSelected)
.PermitIf(MatchCommand.VoteMap, MatchState.TeamVote, MapIsSelected)
Expand Down Expand Up @@ -200,6 +206,30 @@ private void InitializeStateMachine()
_MatchStateMachine.Fire(MatchCommand.LoadMatch);
}

private void ScrambleTeams()
{
if (MatchInfo.Config.TeamMode == Config.TeamMode.Scramble)
{
var randomizedPlayers = AllMatchPlayers.Randomize().ToList();

MatchInfo.MatchTeam1.Players.Clear();
MatchInfo.MatchTeam1.Players.AddRange(randomizedPlayers.Take(randomizedPlayers.Count.Half()));

MatchInfo.MatchTeam2.Players.Clear();
MatchInfo.MatchTeam2.Players.AddRange(randomizedPlayers.Skip(randomizedPlayers.Count.Half()));

TryFireState(MatchCommand.TeamsDefined);
}
}

private void ContinueIfDefault()
{
if (MatchInfo.Config.TeamMode == Config.TeamMode.Default)
{
TryFireState(MatchCommand.TeamsDefined);
}
}

private void StartWarmup()
{
_CsServer.LoadAndExecuteConfig("warmup.cfg");
Expand Down Expand Up @@ -664,7 +694,7 @@ private void SendRemainingMapsToVotingTeam()
}

// If only one map is configured
if (MatchInfo.Config.Maplist.Length == 1)
if (MatchInfo.Config.Maplist.Count == 1)
{
_MapsToSelect = MatchInfo.Config.Maplist.Select(x => new Vote(x)).ToList();
TryFireState(MatchCommand.VoteMap);
Expand Down Expand Up @@ -900,12 +930,18 @@ private MatchPlayer GetMatchPlayer(ulong steamID)

public bool TryAddPlayer(IPlayer player)
{
if (!PlayerBelongsToMatch(player.SteamID))
{
_Logger.LogInformation("Player with steam id {steamId} is no member of this match!", player.SteamID);
return false;
}

var isTeam1 = MatchInfo.Config.Team1.Players.ContainsKey(player.SteamID);
var isTeam2 = !isTeam1 && MatchInfo.Config.Team2.Players.ContainsKey(player.SteamID);
if (!isTeam1 && !isTeam2)
{
_Logger.LogInformation("Player with steam id {steamId} is no member of this match!", player.SteamID);
return false;
// if no team is configured add player to team with less players
isTeam1 = MatchInfo.MatchTeam1.Players.Count < MatchInfo.MatchTeam2.Players.Count;
}

var team = isTeam1 ? MatchInfo.MatchTeam1 : MatchInfo.MatchTeam2;
Expand Down Expand Up @@ -1205,6 +1241,12 @@ public void CompleteMap(int tPoints, int ctPoints)

public bool PlayerBelongsToMatch(ulong steamId)
{
if (MatchInfo.Config.Team1.Players.Count == 0 && MatchInfo.Config.Team2.Players.Count == 0)
{
// Allow matches without player configuration wait for the first 10 players
return true;
}

return MatchInfo.Config.Team1.Players.Any(x => x.Key.Equals(steamId))
|| MatchInfo.Config.Team2.Players.Any(x => x.Key.Equals(steamId));
}
Expand Down
1 change: 1 addition & 0 deletions PugSharp.Match/PugSharp.Match.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<ProjectReference Include="..\PugSharp.Config\PugSharp.Config.csproj" />
<ProjectReference Include="..\PugSharp.Match.Contract\PugSharp.Match.Contract.csproj" />
<ProjectReference Include="..\PugSharp.Server.Contract\PugSharp.Server.Contract.csproj" />
<ProjectReference Include="..\PugSharp.Shared\PugSharp.Shared.csproj" />
<ProjectReference Include="..\PugSharp.Translation\PugSharp.Translation.csproj" />
</ItemGroup>

Expand Down
33 changes: 33 additions & 0 deletions PugSharp.Shared/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace PugSharp.Shared
{
public static class EnumerableExtensions
{
public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
{
if (source == null) throw new ArgumentNullException(nameof(source));

return source.RandomizeInternal();
}

private static IEnumerable<T> RandomizeInternal<T>(
this IEnumerable<T> source)
{
var buffer = source.ToList();
for (int i = 0; i < buffer.Count; i++)
{
int j = Random.Shared.Next(i, buffer.Count);
yield return buffer[j];

buffer[j] = buffer[i];
}
}

public static void AddRange<T>(this IList<T> items, IEnumerable<T> itemsToAdd)
{
foreach (var item in itemsToAdd)
{
items.Add(item);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace PugSharp
namespace PugSharp.Shared
{
internal static class NumericExtensions
public static class NumericExtensions
{
private const double _HalfFactor = 0.5;
public static int Half(this int value)
Expand Down
Loading

0 comments on commit 1ae837f

Please sign in to comment.