Skip to content

Commit

Permalink
Merge pull request #18 from BigBang1112/dev
Browse files Browse the repository at this point in the history
Randomizer TMF 1.1.3
  • Loading branch information
BigBang1112 committed Jun 23, 2024
2 parents addfe4d + ff5e5db commit 6f979de
Show file tree
Hide file tree
Showing 11 changed files with 678 additions and 29 deletions.
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/BigBang1112/randomizer-tmf?include_prereleases&style=for-the-badge)](https://github.com/BigBang1112/randomizer-tmf/releases)
[![GitHub all releases](https://img.shields.io/github/downloads/BigBang1112/randomizer-tmf/total?style=for-the-badge)](https://github.com/BigBang1112/randomizer-tmf/releases)
[![Code Coverage](https://img.shields.io/badge/Code%20Coverage-65%25-yellow?style=for-the-badge)](https://github.com/BigBang1112/randomizer-tmf)
[![Code Coverage](https://img.shields.io/badge/Code%20Coverage-63%25-yellow?style=for-the-badge)](https://github.com/BigBang1112/randomizer-tmf)

**Randomizer TMF - Random Map Challenge for TMNF/TMUF** is a project (inspired from the Flink's Random Map Challenge) that ports random map picking experience to TMNF and TMUF games.

Expand Down Expand Up @@ -35,6 +35,31 @@ The project combines features of [TMX](https://tm-exchange.com/), autosave Gbx f
- Custom time limit
- Preview of your autosaves

## Hidden settings

Some settings are not available in the UI. They are hidden in the `Config.yml` file. You can find it in the installation directory.

```yml
# {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.
ReplayFileFormat: '{0}_{1}_{2}.Replay.Gbx'
# When replay cannot be accessed due to permissions/corruption, how many times to attempt the parse.
ReplayParseFailRetries: 10
# When replay cannot be accessed due to permissions/corruption, how many milliseconds to wait before next attempt.
ReplayParseFailDelayMs: 50
# If to disable in-depth parse of autosave replays, used for further validation.
DisableAutosaveDetailScan: false
# If to disable automatic skip completely.
DisableAutoSkip: false
# When should automatic skip apply. Options are: AuthorMedal, GoldMedal, SilverMedal, BronzeMedal, Finished
AutoSkipMode: AuthorMedal
# Discord Rich Presence configuration.
DiscordRichPresence:
# Disable Discord Rich Presence entirely.
Disable: false
# Disable map thumbnail in Discord Rich Presence, questionmark icon will be used instead.
DisableMapThumbnail: false
```

## Download goals

[![GitHub all releases](https://img.shields.io/github/downloads/BigBang1112/randomizer-tmf/total?style=for-the-badge)](https://github.com/BigBang1112/randomizer-tmf/releases)
Expand Down
10 changes: 10 additions & 0 deletions Src/RandomizerTMF.Logic/AutoSkipMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace RandomizerTMF.Logic;

public enum AutoSkipMode
{
AuthorMedal,
GoldMedal,
SilverMedal,
BronzeMedal,
Finished
}
7 changes: 6 additions & 1 deletion Src/RandomizerTMF.Logic/DiscordRichPresenceConfig.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
namespace RandomizerTMF.Logic;
using YamlDotNet.Serialization;

namespace RandomizerTMF.Logic;

public class DiscordRichPresenceConfig
{
[YamlMember(Description = "Disable Discord Rich Presence entirely.")]
public bool Disable { get; set; }

[YamlMember(Description = "Disable map thumbnail in Discord Rich Presence, questionmark icon will be used instead.")]
public bool DisableMapThumbnail { get; set; }
}
6 changes: 3 additions & 3 deletions 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.1.2</Version>
<Version>1.1.3</Version>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand All @@ -16,8 +16,8 @@
<PackageReference Include="GBX.NET" Version="2.0.4" />
<PackageReference Include="GBX.NET.LZO" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
<PackageReference Include="System.IO.Abstractions" Version="21.0.2" />
<PackageReference Include="YamlDotNet" Version="15.1.6" />
<PackageReference Include="System.IO.Abstractions" Version="21.0.22" />
<PackageReference Include="YamlDotNet" Version="15.3.0" />
</ItemGroup>

<ItemGroup>
Expand Down
13 changes: 13 additions & 0 deletions Src/RandomizerTMF.Logic/Services/RandomizerConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public interface IRandomizerConfig
RandomizerRules Rules { get; set; }
bool DisableAutosaveDetailScan { get; set; }
bool DisableAutoSkip { get; set; }
AutoSkipMode AutoSkipMode { get; set; }
DiscordRichPresenceConfig DiscordRichPresence { get; set; }
bool TopSessions { get; set; }

Expand All @@ -40,13 +41,25 @@ public class RandomizerConfig : IRandomizerConfig
/// <summary>
/// {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>
[YamlMember(Description = "{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.")]
public string? ReplayFileFormat { get; set; } = Constants.DefaultReplayFileFormat;

[YamlMember(Description = "When replay cannot be accessed due to permissions/corruption, how many times to attempt the parse.")]
public int ReplayParseFailRetries { get; set; } = 10;

[YamlMember(Description = "When replay cannot be accessed due to permissions/corruption, how many milliseconds to wait before next attempt.")]
public int ReplayParseFailDelayMs { get; set; } = 50;

[YamlMember(Description = "If to disable in-depth parse of autosave replays, used for further validation.")]
public bool DisableAutosaveDetailScan { get; set; }

[YamlMember(Description = "If to disable automatic skip completely.")]
public bool DisableAutoSkip { get; set; }

[YamlMember(Description = "When should automatic skip apply. Options are: AuthorMedal, GoldMedal, SilverMedal, BronzeMedal, Finished")]
public AutoSkipMode AutoSkipMode { get; set; }

[YamlMember(Description = "Discord Rich Presence configuration.")]
public DiscordRichPresenceConfig DiscordRichPresence { get; set; } = new();

public bool TopSessions { get; set; }
Expand Down
98 changes: 87 additions & 11 deletions Src/RandomizerTMF.Logic/Session.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ internal void StopTrackingMap()
internal void SkipManually(SessionMap map)
{
// If the player didn't receive a gold/author medal, the skip is counted
if (GoldMaps.ContainsKey(map.MapUid) == false && AuthorMaps.ContainsKey(map.MapUid) == false)
if (!GoldMaps.ContainsKey(map.MapUid) && !AuthorMaps.ContainsKey(map.MapUid))
{
SkippedMaps.TryAdd(map.MapUid, map);
map.LastTimestamp = Watch.Elapsed;
Expand Down Expand Up @@ -385,18 +385,42 @@ internal void EvaluateAutosave(string fullPath, CGameCtnReplayRecord replay)
if (Map.IsAuthorMedal(ghost))
{
AuthorMedalReceived(Map);

if (!config.DisableAutoSkip)
{
SkipTokenSource?.Cancel();
}

return;
}

if (Map.IsGoldMedal(ghost))
{
GoldMedalReceived(Map);
return;
}

if (Map.IsSilverMedal(ghost))
{
SilverMedalReceived(Map);
return;
}

if (Map.IsBronzeMedal(ghost))
{
BronzeMedalReceived(Map);
return;
}

Finished(Map);
}

private void AuthorMedalReceived(SessionMap map)
{
GoldMaps.Remove(map.MapUid);
AuthorMaps.TryAdd(map.MapUid, map);
map.LastTimestamp = Watch.Elapsed;
Data?.SetMapResult(map, Constants.AuthorMedal);

events.OnMedalUpdate();

if (!config.DisableAutoSkip)
{
SkipTokenSource?.Cancel();
}
}

Expand All @@ -407,16 +431,68 @@ private void GoldMedalReceived(SessionMap map)
Data?.SetMapResult(map, Constants.GoldMedal);

events.OnMedalUpdate();

if (!config.DisableAutoSkip && config.AutoSkipMode >= AutoSkipMode.GoldMedal)
{
SkipTokenSource?.Cancel();
}
}

private void AuthorMedalReceived(SessionMap map)
private void SilverMedalReceived(SessionMap map)
{
GoldMaps.Remove(map.MapUid);
AuthorMaps.TryAdd(map.MapUid, map);
if (config.DisableAutoSkip || config.AutoSkipMode < AutoSkipMode.GoldMedal)
{
return;
}

SkippedMaps.TryAdd(map.MapUid, map);
map.LastTimestamp = Watch.Elapsed;
Data?.SetMapResult(map, Constants.AuthorMedal);
Data?.SetMapResult(map, Constants.Skipped);

events.OnMedalUpdate();

SkipTokenSource?.Cancel();

// MapSkip event is thrown to update the UI
events.OnMapSkip();
}

private void BronzeMedalReceived(SessionMap map)
{
if (config.DisableAutoSkip || config.AutoSkipMode < AutoSkipMode.BronzeMedal)
{
return;
}

SkippedMaps.TryAdd(map.MapUid, map);
map.LastTimestamp = Watch.Elapsed;
Data?.SetMapResult(map, Constants.Skipped);

events.OnMedalUpdate();

SkipTokenSource?.Cancel();

// MapSkip event is thrown to update the UI
events.OnMapSkip();
}

private void Finished(SessionMap map)
{
if (config.DisableAutoSkip || config.AutoSkipMode < AutoSkipMode.Finished)
{
return;
}

SkippedMaps.TryAdd(map.MapUid, map);
map.LastTimestamp = Watch.Elapsed;
Data?.SetMapResult(map, Constants.Skipped);

events.OnMedalUpdate();

SkipTokenSource?.Cancel();

// MapSkip event is thrown to update the UI
events.OnMapSkip();
}

public void Stop()
Expand Down
33 changes: 33 additions & 0 deletions Src/RandomizerTMF.Logic/SessionMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,37 @@ internal bool IsGoldMedal(CGameCtnGhost ghost)
_ => throw new NotSupportedException($"Unsupported gamemode {Mode}."),
};
}

internal bool IsSilverMedal(CGameCtnGhost ghost)
{
return Mode switch
{
CGameCtnChallenge.PlayMode.Race or CGameCtnChallenge.PlayMode.Puzzle => ghost.RaceTime <= ChallengeParameters.SilverTime,
CGameCtnChallenge.PlayMode.Platform => ghost.Respawns <= ChallengeParameters.SilverTime.GetValueOrDefault().TotalMilliseconds,
CGameCtnChallenge.PlayMode.Stunts => ghost.StuntScore >= ChallengeParameters.SilverTime.GetValueOrDefault().TotalMilliseconds,
_ => throw new NotSupportedException($"Unsupported gamemode {Mode}."),
};
}

internal bool IsBronzeMedal(CGameCtnGhost ghost)
{
return Mode switch
{
CGameCtnChallenge.PlayMode.Race or CGameCtnChallenge.PlayMode.Puzzle => ghost.RaceTime <= ChallengeParameters.BronzeTime,
CGameCtnChallenge.PlayMode.Platform => ghost.Respawns <= ChallengeParameters.BronzeTime.GetValueOrDefault().TotalMilliseconds,
CGameCtnChallenge.PlayMode.Stunts => ghost.StuntScore >= ChallengeParameters.BronzeTime.GetValueOrDefault().TotalMilliseconds,
_ => throw new NotSupportedException($"Unsupported gamemode {Mode}."),
};
}

internal bool IsFinished(CGameCtnGhost ghost)
{
return Mode switch
{
CGameCtnChallenge.PlayMode.Race or CGameCtnChallenge.PlayMode.Puzzle => ghost.RaceTime > ChallengeParameters.BronzeTime,
CGameCtnChallenge.PlayMode.Platform => ghost.Respawns > ChallengeParameters.BronzeTime.GetValueOrDefault().TotalMilliseconds,
CGameCtnChallenge.PlayMode.Stunts => ghost.StuntScore > ChallengeParameters.BronzeTime.GetValueOrDefault().TotalMilliseconds,
_ => throw new NotSupportedException($"Unsupported gamemode {Mode}."),
};
}
}
22 changes: 11 additions & 11 deletions Src/RandomizerTMF/RandomizerTMF.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">


<PropertyGroup>
<Company>BigBang1112</Company>
</PropertyGroup>

<PropertyGroup>
<Version>1.1.3</Version>
<PublishSingleFile>true</PublishSingleFile>
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
</PropertyGroup>

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
Expand All @@ -14,16 +24,6 @@

<ApplicationIcon>Assets/icon.ico</ApplicationIcon>
</PropertyGroup>

<PropertyGroup>
<Company>BigBang1112</Company>
</PropertyGroup>

<PropertyGroup>
<Version>1.1.2</Version>
<PublishSingleFile>true</PublishSingleFile>
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
</PropertyGroup>

<ItemGroup>
<AvaloniaResource Include="Assets\**" />
Expand Down
13 changes: 12 additions & 1 deletion Src/RandomizerTMF/ViewModels/DashboardWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@ private async Task ScanSessionsAsync(bool top)
sessionBinExists = true;
}

if (sessionYmlExists)
{
var backupDir = FilePathManager.SessionsDirectoryPath + "_Backup";
Directory.CreateDirectory(backupDir);

var backupSessionYml = Path.Combine(backupDir, Path.GetFileName(dir) + ".yml");
File.Move(sessionYml, backupSessionYml, true);
}

try
{
if (sessionBinExists)
Expand Down Expand Up @@ -257,7 +266,9 @@ private async Task UpdateAutosavesWithFullParseAsync()

private IEnumerable<AutosaveModel> GetAutosaveModels()
{
return autosaveScanner.AutosaveDetails.Select(x => new AutosaveModel(x.Key, x.Value)).OrderBy(x => x.Autosave.MapName);
return autosaveScanner.AutosaveDetails
.Select(x => new AutosaveModel(x.Key, x.Value))
.OrderBy(x => x.Autosave.MapName);
}

protected override void CloseClick()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="RichardSzalay.MockHttp" Version="7.0.0" />
<PackageReference Include="System.IO.Abstractions.TestingHelpers" Version="21.0.2" />
<PackageReference Include="System.IO.Abstractions.TestingHelpers" Version="21.0.22" />
<PackageReference Include="xunit" Version="2.8.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
Loading

0 comments on commit 6f979de

Please sign in to comment.