Skip to content

Commit

Permalink
Merge pull request #34 from MrDave1999/feat/Maps
Browse files Browse the repository at this point in the history
feat: Create the Maps module
  • Loading branch information
MrDave1999 authored Aug 25, 2024
2 parents 85fc381 + 49182fb commit 8fead27
Show file tree
Hide file tree
Showing 54 changed files with 1,471 additions and 23 deletions.
7 changes: 6 additions & 1 deletion src/Application/CTF.Application.csproj
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>

<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
<PackageReference Include="SampSharp.CTF.Entities" />
<PackageReference Include="seztion-parser" />
<PackageReference Include="SmartFormat" />
</ItemGroup>

Expand All @@ -29,4 +30,8 @@
</EmbeddedResource>
</ItemGroup>

<ItemGroup>
<Content Include="Maps\Files\*.ini" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

</Project>
45 changes: 45 additions & 0 deletions src/Application/Common/Resources/Messages.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions src/Application/Common/Resources/Messages.resx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@
<data name="EmptyWeaponPackage" xml:space="preserve">
<value>You have no items in your weapon package</value>
</data>
<data name="InvalidInterval" xml:space="preserve">
<value>The interval must be between 0 to {Max}</value>
</data>
<data name="InvalidMap" xml:space="preserve">
<value>Invalid map id has been passed</value>
</data>
<data name="InvalidNickName" xml:space="preserve">
<value>Must be 3-20 characters long and only contain valid characters (0-9, a-z, A-Z, [], (), $, @ . _ and = only)</value>
</data>
Expand All @@ -141,6 +147,12 @@
<data name="InvalidWeapon" xml:space="preserve">
<value>Invalid weapon has been passed</value>
</data>
<data name="LocationListCannotBeEmpty" xml:space="preserve">
<value>The spawn location list cannot be empty</value>
</data>
<data name="MapNotFound" xml:space="preserve">
<value>Map has not been found</value>
</data>
<data name="MemberAlreadyExists" xml:space="preserve">
<value>Player '{Name}' is a member that already exists</value>
</data>
Expand All @@ -159,6 +171,9 @@
<data name="PlayerNotFound" xml:space="preserve">
<value>Player '{Name}' is not found</value>
</data>
<data name="SpawnLocationFailure" xml:space="preserve">
<value>A spawn location can only be obtained for the alpha or beta team</value>
</data>
<data name="SubtractPoints" xml:space="preserve">
<value>Points must be between -1 to -100</value>
</data>
Expand Down
22 changes: 11 additions & 11 deletions src/Application/Common/Result.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,32 @@
/// <summary>
/// Represents the result of an operation that does not return a value.
/// </summary>
public readonly ref struct Result
public ref struct Result
{
public Result() { }

/// <summary>
/// Gets the description of a result.
/// </summary>
public string Message { get; init; } = string.Empty;
public string Message { get; private set; } = string.Empty;

/// <summary>
/// A value indicating that the result was successful.
/// </summary>
public bool IsSuccess { get; init; } = true;
public bool IsSuccess { get; private set; } = false;

/// <summary>
/// A value that indicates that the result was a failure.
/// </summary>
public bool IsFailed => !IsSuccess;

public static Result Success() => new();
public static Result Success(string message) => new() { Message = message };

public static Result Failure() => new() { IsSuccess = false };
public static Result Failure(string message) => new()
{
IsSuccess = false,
Message = message
public static Result Success() => new() { IsSuccess = true };
public static Result Success(string message) => new()
{
IsSuccess = true,
Message = message
};

public static Result Failure() => new();
public static Result Failure(string message) => new() { Message = message };
}
40 changes: 29 additions & 11 deletions src/Application/Common/ResultOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,59 @@
/// Represents the result of an operation that returns a value.
/// </summary>
/// <typeparam name="TValue">A value associated to the result.</typeparam>
public readonly ref struct Result<TValue>
public ref struct Result<TValue>
{
private TValue _value;
public Result() { }

/// <summary>
/// Gets the value associated with the result.
/// </summary>
public TValue Value { get; init; } = default;
/// <exception cref="InvalidOperationException">
/// when <see cref="Result.IsFailed"/> is true.
/// </exception>
public TValue Value
{
get
{
return IsSuccess ?
_value :
throw new InvalidOperationException("The value of a failure result can not be accessed.");
}
private set
{
_value = value;
}
}

/// <summary>
/// Gets the description of a result.
/// </summary>
public string Message { get; init; } = string.Empty;
public string Message { get; private set; } = string.Empty;

/// <summary>
/// A value indicating that the result was successful.
/// </summary>
public bool IsSuccess { get; init; } = true;
public bool IsSuccess { get; private set; } = false;

/// <summary>
/// A value that indicates that the result was a failure.
/// </summary>
public bool IsFailed => !IsSuccess;

public static Result<TValue> Success(TValue value) => new() { Value = value };
public static Result<TValue> Success(TValue value) => new()
{
IsSuccess = true,
Value = value
};

public static Result<TValue> Success(TValue value, string message) => new()
{
IsSuccess = true,
Value = value,
Message = message
};

public static Result<TValue> Failure() => new() { IsSuccess = false };
public static Result<TValue> Failure(string message) => new()
{
IsSuccess = false,
Message = message
};
public static Result<TValue> Failure() => new();
public static Result<TValue> Failure(string message) => new() { Message = message };
}
65 changes: 65 additions & 0 deletions src/Application/Maps/CurrentMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
namespace CTF.Application.Maps;

/// <summary>
/// Represents the current information of a map.
/// </summary>
public class CurrentMap
{
private IMap _nextMap;
private readonly Random _random = new();
public const int DefaultInterior = 0;
public const int DefaultWeather = 10;
public const int DefaultWorldTime = 12;
public int Id { get; }
public string Name { get; }
public IReadOnlyList<SpawnLocation> AlphaTeamLocations { get; }
public IReadOnlyList<SpawnLocation> BetaTeamLocations { get; }
public int Interior { get; }
public int Weather { get; }
public int WorldTime { get; }
public IMap NextMap => _nextMap;
public int IsLoading { get; set; }

public CurrentMap(
IMap map,
IReadOnlyList<SpawnLocation> alphaTeamLocations,
IReadOnlyList<SpawnLocation> betaTeamLocations,
int interior = DefaultInterior,
int weather = DefaultWeather,
int worldTime = DefaultWorldTime)
{
ArgumentNullException.ThrowIfNull(map);
ArgumentNullException.ThrowIfNull(alphaTeamLocations);
ArgumentNullException.ThrowIfNull(betaTeamLocations);

if (alphaTeamLocations.Count == 0)
throw new ArgumentException(Messages.LocationListCannotBeEmpty, nameof(alphaTeamLocations));

if (betaTeamLocations.Count == 0)
throw new ArgumentException(Messages.LocationListCannotBeEmpty, nameof(betaTeamLocations));

Id = map.Id;
Name = map.Name;
AlphaTeamLocations = alphaTeamLocations;
BetaTeamLocations = betaTeamLocations;
Interior = interior;
Weather = weather;
WorldTime = worldTime;
int nextMapId = (Id + 1) % MapCollection.Count;
_nextMap = MapCollection.GetById(nextMapId).Value;
}

public string GetMapNameAsText() => $"Map: ~w~{Name}";
public void SetNextMap(IMap nextMap)
{
ArgumentNullException.ThrowIfNull(nextMap);
_nextMap = nextMap;
}

public SpawnLocation GetRandomSpawnLocation(TeamId team) => team switch
{
TeamId.Alpha => AlphaTeamLocations[_random.Next(AlphaTeamLocations.Count)],
TeamId.Beta => BetaTeamLocations[_random.Next(BetaTeamLocations.Count)],
_ => throw new NotSupportedException(Messages.SpawnLocationFailure)
};
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
7 changes: 7 additions & 0 deletions src/Application/Maps/IMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace CTF.Application.Maps;

public interface IMap
{
int Id { get; }
string Name { get; }
}
58 changes: 58 additions & 0 deletions src/Application/Maps/LoadTime.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
namespace CTF.Application.Maps;

/// <summary>
/// Represents the total wait time for the new map to load.
/// </summary>
public class LoadTime
{
private readonly Action _onLoadingMap;
private readonly Action _onLoadedMap;
private int _interval = MaxLoadTime;
public const int MaxLoadTime = 6;

/// <summary>
/// Displays the load time in the game.
/// </summary>
public string GameText { get; private set; } = string.Empty;

/// <summary>
/// Represents the interval in seconds.
/// </summary>
public int Interval => _interval;

public LoadTime(Action onLoadingMap, Action onLoadedMap)
{
ArgumentNullException.ThrowIfNull(onLoadingMap);
ArgumentNullException.ThrowIfNull(onLoadedMap);
_onLoadingMap = onLoadingMap;
_onLoadedMap = onLoadedMap;
}

/// <summary>
/// Reduces the load time until it reaches zero.
/// </summary>
public void Decrease()
{
if (_interval == 0)
{
Reset();
_onLoadedMap();
return;
}

if (_interval == MaxLoadTime)
{
_onLoadingMap();
}

_interval--;
UpdateGameText();
}

private void UpdateGameText() => GameText = $"Loading map... ({_interval})";
private void Reset()
{
_interval = MaxLoadTime;
GameText = string.Empty;
}
}
Loading

0 comments on commit 8fead27

Please sign in to comment.