Skip to content

Commit

Permalink
Merge pull request #4 from BigBang1112/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
BigBang1112 authored Dec 13, 2022
2 parents 378468a + 514cc62 commit be239dc
Show file tree
Hide file tree
Showing 9 changed files with 249 additions and 91 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ The project combines features of [TMX](https://tm-exchange.com/), autosave Gbx f
[![GitHub all releases](https://img.shields.io/github/downloads/BigBang1112/randomizer-tmf/total?style=for-the-badge)](https://github.com/BigBang1112/randomizer-tmf/releases)

- ✔️ **50 downloads within 1 week** - Guaranteed support throughout 2023
- **100 downloads** - Discord Rich Presence integration
- ✔️ **100 downloads** - Discord Rich Presence integration **(coming right after refactoring)**
- **300 downloads** - TMUF theme
- **500 downloads** - Profile management (fresh account randomization)
- **2000 downloads** - Automated RMC leaderboards
Expand Down
3 changes: 3 additions & 0 deletions Src/RandomizerTMF.Logic/RandomizerConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ public class RandomizerConfig
/// {0} is the map name, {1} is the replay score (example: 9'59''59 in Race/Puzzle or 999_9'59''59 in Platform/Stunts), {2} is the player login.
/// </summary>
public string? ReplayFileFormat { get; set; } = Constants.DefaultReplayFileFormat;

public int ReplayParseFailRetries { get; set; } = 10;
public int ReplayParseFailDelayMs { get; set; } = 50;
}
162 changes: 113 additions & 49 deletions Src/RandomizerTMF.Logic/RandomizerEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ private set
public static StreamWriter LogWriter { get; private set; }
public static StreamWriter? CurrentSessionLogWriter { get; private set; }
public static bool SessionEnding { get; private set; }


public static string? Version { get; } = typeof(RandomizerEngine).Assembly.GetName().Version?.ToString(3);

[GeneratedRegex("[^a-zA-Z0-9_.]+")]
private static partial Regex SpecialCharRegex();

Expand Down Expand Up @@ -148,7 +150,7 @@ static RandomizerEngine()
};

Http = new HttpClient(socketHandler);
Http.DefaultRequestHeaders.UserAgent.TryParseAdd($"Randomizer TMF {typeof(RandomizerEngine).Assembly.GetName().Version}");
Http.DefaultRequestHeaders.UserAgent.TryParseAdd($"Randomizer TMF {Version}");

Logger.LogInformation("Preparing general events...");

Expand Down Expand Up @@ -187,34 +189,52 @@ private static void AutosaveCreatedOrChanged(object sender, FileSystemEventArgs
lastAutosaveUpdate = lastWriteTime;
//

var retryCounter = 0;

CGameCtnReplayRecord replay;

try
while (true)
{
// Any kind of autosave update section

Logger.LogInformation("Analyzing a new file {autosavePath} in autosaves folder...", e.FullPath);

if (GameBox.ParseNode(e.FullPath) is not CGameCtnReplayRecord r)
try
{
Logger.LogWarning("Found file {file} that is not a replay.", e.FullPath);
return;
}
// Any kind of autosave update section

if (r.MapInfo is null)
{
Logger.LogWarning("Found replay {file} that has no map info.", e.FullPath);
return;
Logger.LogInformation("Analyzing a new file {autosavePath} in autosaves folder...", e.FullPath);

if (GameBox.ParseNode(e.FullPath) is not CGameCtnReplayRecord r)
{
Logger.LogWarning("Found file {file} that is not a replay.", e.FullPath);
return;
}

if (r.MapInfo is null)
{
Logger.LogWarning("Found replay {file} that has no map info.", e.FullPath);
return;
}

AutosaveHeaders.TryAdd(r.MapInfo.Id, new AutosaveHeader(Path.GetFileName(e.FullPath), r));

replay = r;
}
catch (Exception ex)
{
retryCounter++;

Logger.LogError(ex, "Error while analyzing a new file {autosavePath} in autosaves folder (retry {counter}/{maxRetries}).",
e.FullPath, retryCounter, Config.ReplayParseFailRetries);

AutosaveHeaders.TryAdd(r.MapInfo.Id, new AutosaveHeader(Path.GetFileName(e.FullPath), r));
if (retryCounter >= Config.ReplayParseFailRetries)
{
return;
}

replay = r;
}
catch (Exception ex)
{
Logger.LogError(ex, "Error while analyzing a new file {autosavePath} in autosaves folder.", e.FullPath);
return;
Thread.Sleep(Config.ReplayParseFailDelayMs);

continue;
}

break;
}

try
Expand Down Expand Up @@ -749,7 +769,7 @@ private static void InitializeSessionData()
{
var startedAt = DateTimeOffset.Now;

CurrentSessionData = new SessionData(startedAt, Config.Rules);
CurrentSessionData = new SessionData(Version, startedAt, Config.Rules);

if (CurrentSessionDataDirectoryPath is null)
{
Expand All @@ -776,12 +796,12 @@ public static void ValidateRules()
{
if (Config.Rules.TimeLimit == TimeSpan.Zero)
{
throw new RuleValidationException("Time limit cannot be 0:00:00");
throw new RuleValidationException("Time limit cannot be 0:00:00.");
}

if (Config.Rules.TimeLimit > new TimeSpan(9, 59, 59))
{
throw new RuleValidationException("Time limit cannot be above 9:59:59");
throw new RuleValidationException("Time limit cannot be above 9:59:59.");
}

foreach (var primaryType in Enum.GetValues<EPrimaryType>())
Expand All @@ -790,51 +810,95 @@ public static void ValidateRules()
{
continue;
}

if (Config.Rules.RequestRules.PrimaryType == primaryType
&& (Config.Rules.RequestRules.Site == ESite.Any
&& (Config.Rules.RequestRules.Site is ESite.Any
|| Config.Rules.RequestRules.Site.HasFlag(ESite.TMNF) || Config.Rules.RequestRules.Site.HasFlag(ESite.Nations)))
{
throw new RuleValidationException($"{primaryType} is not valid with TMNF or Nations Exchange");
throw new RuleValidationException($"{primaryType} cannot be specifically selected with TMNF or Nations Exchange.");
}
}

if (Config.Rules.RequestRules.Environment is not null || Config.Rules.RequestRules.Vehicle is not null)
if (Config.Rules.RequestRules.Environment?.Count > 0)
{
foreach (var env in Enum.GetValues<EEnvironment>())
if (Config.Rules.RequestRules.Site.HasFlag(ESite.Sunrise)
&& !Config.Rules.RequestRules.Environment.Contains(EEnvironment.Island)
&& !Config.Rules.RequestRules.Environment.Contains(EEnvironment.Coast)
&& !Config.Rules.RequestRules.Environment.Contains(EEnvironment.Bay))
{
if (env is EEnvironment.Stadium)
{
continue;
}
throw new RuleValidationException("Island, Coast, or Bay has to be selected when environments are specified and Sunrise Exchange is selected.");
}

if (Config.Rules.RequestRules.Site != ESite.Any && !Config.Rules.RequestRules.Site.HasFlag(ESite.TMNF) && !Config.Rules.RequestRules.Site.HasFlag(ESite.Nations))
{
continue;
}

if (Config.Rules.RequestRules.Environment?.Contains(env) == true)
{
throw new RuleValidationException($"{env} is not valid with TMNF or Nations Exchange");
}
if (Config.Rules.RequestRules.Site.HasFlag(ESite.Original)
&& !Config.Rules.RequestRules.Environment.Contains(EEnvironment.Snow)
&& !Config.Rules.RequestRules.Environment.Contains(EEnvironment.Desert)
&& !Config.Rules.RequestRules.Environment.Contains(EEnvironment.Rally))
{
throw new RuleValidationException("Snow, Desert, or Rally has to be selected when environments are specified and Original Exchange is selected.");
}

if (Config.Rules.RequestRules.Vehicle?.Contains(env) == true)
if (!Config.Rules.RequestRules.Environment.Contains(EEnvironment.Stadium)
&& (Config.Rules.RequestRules.Site.HasFlag(ESite.TMNF) || Config.Rules.RequestRules.Site.HasFlag(ESite.Nations)))
{
throw new RuleValidationException("Stadium has to be selected when environments are specified and TMNF or Nations Exchange is selected.");
}

if (Config.Rules.RequestRules.Site.HasFlag(ESite.Sunrise) || Config.Rules.RequestRules.Site.HasFlag(ESite.Original))
{
foreach (var env in Config.Rules.RequestRules.Environment)
{
throw new RuleValidationException($"{env}Car is not valid with TMNF or Nations Exchange");
if (Config.Rules.RequestRules.Vehicle?.Contains(env) == false)
{
throw new RuleValidationException("Envimix randomization is not allowed when Sunrise or Original Exchange is selected.");
}
}
}
}

if (Config.Rules.RequestRules.Vehicle?.Count > 0)
{
if (!Config.Rules.RequestRules.Vehicle.Contains(EEnvironment.Island)
&& !Config.Rules.RequestRules.Vehicle.Contains(EEnvironment.Coast)
&& !Config.Rules.RequestRules.Vehicle.Contains(EEnvironment.Bay)
&& Config.Rules.RequestRules.Site.HasFlag(ESite.Sunrise))
{
throw new RuleValidationException("IslandCar, CoastCar, or BayCar has to be selected when cars are specified and Sunrise Exchange is selected.");
}

if (!Config.Rules.RequestRules.Vehicle.Contains(EEnvironment.Snow)
&& !Config.Rules.RequestRules.Vehicle.Contains(EEnvironment.Desert)
&& !Config.Rules.RequestRules.Vehicle.Contains(EEnvironment.Rally)
&& Config.Rules.RequestRules.Site.HasFlag(ESite.Original))
{
throw new RuleValidationException("SnowCar, DesertCar, or RallyCar has to be selected when cars are specified and Original Exchange is selected.");
}

if (!Config.Rules.RequestRules.Vehicle.Contains(EEnvironment.Stadium)
&& (Config.Rules.RequestRules.Site.HasFlag(ESite.TMNF) || Config.Rules.RequestRules.Site.HasFlag(ESite.Nations)))
{
throw new RuleValidationException("StadiumCar has to be selected when cars are specified and TMNF or Nations Exchange is selected.");
}
}

if (Config.Rules.RequestRules.EqualEnvironmentDistribution
&& Config.Rules.RequestRules.EqualVehicleDistribution
&& Config.Rules.RequestRules.Site is not ESite.TMUF)
{
throw new RuleValidationException("Equal environment and car distribution combined is only valid with TMUF Exchange.");
}

if (Config.Rules.RequestRules.EqualEnvironmentDistribution
&& Config.Rules.RequestRules.Site.HasFlag(ESite.TMNF) || Config.Rules.RequestRules.Site.HasFlag(ESite.Nations))
&& (Config.Rules.RequestRules.Site is ESite.Any
|| Config.Rules.RequestRules.Site.HasFlag(ESite.TMNF) || Config.Rules.RequestRules.Site.HasFlag(ESite.Nations)))
{
throw new RuleValidationException($"Equal environment distribution is not valid with TMNF or Nations Exchange");
throw new RuleValidationException("Equal environment distribution is not valid with TMNF or Nations Exchange.");
}

if (Config.Rules.RequestRules.EqualVehicleDistribution
&& Config.Rules.RequestRules.Site.HasFlag(ESite.TMNF) || Config.Rules.RequestRules.Site.HasFlag(ESite.Nations))
&& (Config.Rules.RequestRules.Site is ESite.Any
|| Config.Rules.RequestRules.Site.HasFlag(ESite.TMNF) || Config.Rules.RequestRules.Site.HasFlag(ESite.Nations)))
{
throw new RuleValidationException($"Equal vehicle distribution is not valid with TMNF or Nations Exchange");
throw new RuleValidationException("Equal vehicle distribution is not valid with TMNF or Nations Exchange.");
}
}

Expand Down
2 changes: 1 addition & 1 deletion Src/RandomizerTMF.Logic/RandomizerTMF.Logic.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Version>1.0.2</Version>
<Version>1.0.3</Version>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand Down
Loading

0 comments on commit be239dc

Please sign in to comment.