Skip to content

Commit f18b280

Browse files
committed
Refactor RotatingRaidBotSV for better performance and readability
- Cache den locations using Lazy<> to avoid repeated JSON parsing - Add region boundary constants (PaldeaRaidCount, KitakamiStartIndex, etc.) - Simplify WriteProgressLive by consolidating duplicate read/write blocks - Make TypeAdvantages dictionary static readonly - Use Raid.SIZE constant instead of magic number 0x20 - Remove unused variable assignment
1 parent 5b2e314 commit f18b280

1 file changed

Lines changed: 63 additions & 74 deletions

File tree

SysBot.Pokemon/SV/BotRaid/RotatingRaidBotSV.cs

Lines changed: 63 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,20 @@ public record PlayerInfo
117117
private const string MysteryRaidTitle = "Mystery Shiny Raid";
118118
private const string UserRequestedRaidSuffix = "'s Requested Raid";
119119

120+
// Region boundary constants for raid index calculations
121+
private const int PaldeaRaidCount = 69;
122+
private const int KitakamiRaidCount = 25;
123+
private const int KitakamiStartIndex = PaldeaRaidCount;
124+
private const int BlueberryStartIndex = PaldeaRaidCount + KitakamiRaidCount;
125+
126+
// Cached den locations to avoid repeated JSON loading
127+
private static readonly Lazy<Dictionary<string, float[]>> CachedPaldeaDenLocations = new(() =>
128+
LoadDenLocations("SysBot.Pokemon.SV.BotRaid.DenLocations.den_locations_base.json"));
129+
private static readonly Lazy<Dictionary<string, float[]>> CachedKitakamiDenLocations = new(() =>
130+
LoadDenLocations("SysBot.Pokemon.SV.BotRaid.DenLocations.den_locations_kitakami.json"));
131+
private static readonly Lazy<Dictionary<string, float[]>> CachedBlueberryDenLocations = new(() =>
132+
LoadDenLocations("SysBot.Pokemon.SV.BotRaid.DenLocations.den_locations_blueberry.json"));
133+
120134
/// <summary>
121135
/// Main execution loop for the raid bot
122136
/// </summary>
@@ -2381,7 +2395,6 @@ private async Task<int> PrepareForRaid(CancellationToken token)
23812395
return 2;
23822396
}
23832397

2384-
_ = _settings.ActiveRaids[_currentRaidIndex];
23852398
var currentSeed = _settings.ActiveRaids[_currentRaidIndex].Seed.ToUpper();
23862399

23872400
if (!_denHexSeed.Equals(currentSeed, StringComparison.CurrentCultureIgnoreCase))
@@ -3060,7 +3073,7 @@ private static async Task<bool> IsValidImageUrlAsync(string url)
30603073
}
30613074
}
30623075

3063-
private readonly Dictionary<string, string> _typeAdvantages = new()
3076+
private static readonly Dictionary<string, string> TypeAdvantages = new()
30643077
{
30653078
{ "normal", "Fighting" },
30663079
{ "fire", "Water, Ground, Rock" },
@@ -3089,7 +3102,7 @@ private string GetTypeAdvantage(string teraType)
30893102
{
30903103
string englishTypeName = GetEnglishTypeNameFromLocalized(teraType);
30913104

3092-
if (_typeAdvantages.TryGetValue(englishTypeName.ToLower(), out string advantage))
3105+
if (TypeAdvantages.TryGetValue(englishTypeName.ToLower(), out string? advantage))
30933106
{
30943107
return advantage;
30953108
}
@@ -3101,7 +3114,7 @@ private string GetTypeAdvantage(string teraType)
31013114
/// </summary>
31023115
private string GetEnglishTypeNameFromLocalized(string teraType)
31033116
{
3104-
if (_typeAdvantages.ContainsKey(teraType.ToLower()))
3117+
if (TypeAdvantages.ContainsKey(teraType.ToLower()))
31053118
return teraType.ToLower();
31063119
var englishStrings = GameInfo.GetStrings(2);
31073120
var localizedStrings = GameInfo.GetStrings((int)_settings.EmbedToggles.EmbedLanguage);
@@ -4253,6 +4266,20 @@ private static Dictionary<string, float[]> LoadDenLocations(string resourceName)
42534266
return denLocations;
42544267
}
42554268

4269+
/// <summary>
4270+
/// Gets cached den locations for the specified map type
4271+
/// </summary>
4272+
private static Dictionary<string, float[]> GetCachedDenLocations(TeraRaidMapParent mapType)
4273+
{
4274+
return mapType switch
4275+
{
4276+
TeraRaidMapParent.Paldea => CachedPaldeaDenLocations.Value,
4277+
TeraRaidMapParent.Kitakami => CachedKitakamiDenLocations.Value,
4278+
TeraRaidMapParent.Blueberry => CachedBlueberryDenLocations.Value,
4279+
_ => throw new ArgumentException("Invalid map type", nameof(mapType))
4280+
};
4281+
}
4282+
42564283
/// <summary>
42574284
/// Finds the nearest den location to the player
42584285
/// </summary>
@@ -4377,10 +4404,10 @@ private async Task LogPlayerLocation(CancellationToken token)
43774404
{
43784405
var playerLocation = await GetPlayersLocation(token);
43794406

4380-
// Load den locations for all regions
4381-
var blueberryLocations = LoadDenLocations("SysBot.Pokemon.SV.BotRaid.DenLocations.den_locations_blueberry.json");
4382-
var kitakamiLocations = LoadDenLocations("SysBot.Pokemon.SV.BotRaid.DenLocations.den_locations_kitakami.json");
4383-
var baseLocations = LoadDenLocations("SysBot.Pokemon.SV.BotRaid.DenLocations.den_locations_base.json");
4407+
// Use cached den locations for all regions
4408+
var blueberryLocations = GetCachedDenLocations(TeraRaidMapParent.Blueberry);
4409+
var kitakamiLocations = GetCachedDenLocations(TeraRaidMapParent.Kitakami);
4410+
var baseLocations = GetCachedDenLocations(TeraRaidMapParent.Paldea);
43844411

43854412
// Find the nearest location for each set and keep track of the overall nearest
43864413
var nearestDen = new Dictionary<string, string>
@@ -4394,15 +4421,15 @@ private async Task LogPlayerLocation(CancellationToken token)
43944421
.Where(kv => !string.IsNullOrEmpty(kv.Value))
43954422
.Select(kv =>
43964423
{
4397-
Dictionary<string, float[]>? denLocations = kv.Key switch
4424+
var denLocations = GetCachedDenLocations(kv.Key switch
43984425
{
4399-
"Blueberry" => blueberryLocations,
4400-
"Kitakami" => kitakamiLocations,
4401-
"Paldea" => baseLocations,
4402-
_ => null
4403-
};
4426+
"Blueberry" => TeraRaidMapParent.Blueberry,
4427+
"Kitakami" => TeraRaidMapParent.Kitakami,
4428+
"Paldea" => TeraRaidMapParent.Paldea,
4429+
_ => TeraRaidMapParent.Paldea
4430+
});
44044431

4405-
if (denLocations == null || !denLocations.TryGetValue(kv.Value, out var denLocationArray))
4432+
if (!denLocations.TryGetValue(kv.Value, out var denLocationArray))
44064433
return null;
44074434

44084435
var denLocationTuple = (denLocationArray[0], denLocationArray[1], denLocationArray[2]);
@@ -4479,22 +4506,17 @@ private async Task LogPlayerLocation(CancellationToken token)
44794506
// Read the raw raid data for the region
44804507
byte[] raidData = await ReadRaidsForRegion(mapType, token);
44814508

4482-
Dictionary<string, float[]> denLocations = mapType switch
4483-
{
4484-
TeraRaidMapParent.Paldea => LoadDenLocations("SysBot.Pokemon.SV.BotRaid.DenLocations.den_locations_base.json"),
4485-
TeraRaidMapParent.Kitakami => LoadDenLocations("SysBot.Pokemon.SV.BotRaid.DenLocations.den_locations_kitakami.json"),
4486-
TeraRaidMapParent.Blueberry => LoadDenLocations("SysBot.Pokemon.SV.BotRaid.DenLocations.den_locations_blueberry.json"),
4487-
_ => throw new InvalidOperationException("Invalid region")
4488-
};
4509+
// Use cached den locations
4510+
var denLocations = GetCachedDenLocations(mapType);
44894511

44904512
var activeRaids = new List<(string DenIdentifier, float[] Coordinates, int Index, uint Seed, uint Flags, bool IsEvent)>();
44914513

44924514
// Calculate the starting index offset based on the map type
44934515
int startingIndex = mapType switch
44944516
{
44954517
TeraRaidMapParent.Paldea => 0,
4496-
TeraRaidMapParent.Kitakami => 69,
4497-
TeraRaidMapParent.Blueberry => 94,
4518+
TeraRaidMapParent.Kitakami => KitakamiStartIndex,
4519+
TeraRaidMapParent.Blueberry => BlueberryStartIndex,
44984520
_ => 0
44994521
};
45004522

@@ -4533,48 +4555,19 @@ private async Task WriteProgressLive(GameProgress progress)
45334555
if (Connection is null)
45344556
return;
45354557

4536-
if (progress >= GameProgress.Unlocked3Stars)
4537-
{
4538-
var toexpect = (bool?)await ReadBlock(RaidDataBlocks.KUnlockedRaidDifficulty3, CancellationToken.None);
4539-
await WriteBlock(true, RaidDataBlocks.KUnlockedRaidDifficulty3, CancellationToken.None, toexpect);
4540-
}
4541-
else
4542-
{
4543-
var toexpect = (bool?)await ReadBlock(RaidDataBlocks.KUnlockedRaidDifficulty3, CancellationToken.None);
4544-
await WriteBlock(false, RaidDataBlocks.KUnlockedRaidDifficulty3, CancellationToken.None, toexpect);
4545-
}
4546-
4547-
if (progress >= GameProgress.Unlocked4Stars)
4548-
{
4549-
var toexpect = (bool?)await ReadBlock(RaidDataBlocks.KUnlockedRaidDifficulty4, CancellationToken.None);
4550-
await WriteBlock(true, RaidDataBlocks.KUnlockedRaidDifficulty4, CancellationToken.None, toexpect);
4551-
}
4552-
else
4558+
var difficultyBlocks = new[]
45534559
{
4554-
var toexpect = (bool?)await ReadBlock(RaidDataBlocks.KUnlockedRaidDifficulty4, CancellationToken.None);
4555-
await WriteBlock(false, RaidDataBlocks.KUnlockedRaidDifficulty4, CancellationToken.None, toexpect);
4556-
}
4557-
4558-
if (progress >= GameProgress.Unlocked5Stars)
4559-
{
4560-
var toexpect = (bool?)await ReadBlock(RaidDataBlocks.KUnlockedRaidDifficulty5, CancellationToken.None);
4561-
await WriteBlock(true, RaidDataBlocks.KUnlockedRaidDifficulty5, CancellationToken.None, toexpect);
4562-
}
4563-
else
4564-
{
4565-
var toexpect = (bool?)await ReadBlock(RaidDataBlocks.KUnlockedRaidDifficulty5, CancellationToken.None);
4566-
await WriteBlock(false, RaidDataBlocks.KUnlockedRaidDifficulty5, CancellationToken.None, toexpect);
4567-
}
4560+
(GameProgress.Unlocked3Stars, RaidDataBlocks.KUnlockedRaidDifficulty3),
4561+
(GameProgress.Unlocked4Stars, RaidDataBlocks.KUnlockedRaidDifficulty4),
4562+
(GameProgress.Unlocked5Stars, RaidDataBlocks.KUnlockedRaidDifficulty5),
4563+
(GameProgress.Unlocked6Stars, RaidDataBlocks.KUnlockedRaidDifficulty6),
4564+
};
45684565

4569-
if (progress >= GameProgress.Unlocked6Stars)
4566+
foreach (var (requiredProgress, block) in difficultyBlocks)
45704567
{
4571-
var toexpect = (bool?)await ReadBlock(RaidDataBlocks.KUnlockedRaidDifficulty6, CancellationToken.None);
4572-
await WriteBlock(true, RaidDataBlocks.KUnlockedRaidDifficulty6, CancellationToken.None, toexpect);
4573-
}
4574-
else
4575-
{
4576-
var toexpect = (bool?)await ReadBlock(RaidDataBlocks.KUnlockedRaidDifficulty6, CancellationToken.None);
4577-
await WriteBlock(false, RaidDataBlocks.KUnlockedRaidDifficulty6, CancellationToken.None, toexpect);
4568+
bool shouldUnlock = progress >= requiredProgress;
4569+
var toexpect = (bool?)await ReadBlock(block, CancellationToken.None);
4570+
await WriteBlock(shouldUnlock, block, CancellationToken.None, toexpect);
45784571
}
45794572
}
45804573

@@ -4919,15 +4912,11 @@ private static (PK9, uint) IsSeedReturned(ITeraRaid encounter, Raid raid)
49194912
/// </summary>
49204913
private async Task FindSeedIndexInRaids(uint denHexSeedUInt, CancellationToken token)
49214914
{
4922-
const int kitakamiDensCount = 25;
4923-
int upperBound = kitakamiDensCount == 25 ? 94 : 95;
4924-
int startIndex = kitakamiDensCount == 25 ? 94 : 95;
4925-
49264915
// Search in Paldea region
49274916
var dataP = await SwitchConnection.ReadBytesAbsoluteAsync(_raidBlockPointerP, 2304, token).ConfigureAwait(false);
4928-
for (int i = 0; i < 69; i++)
4917+
for (int i = 0; i < PaldeaRaidCount; i++)
49294918
{
4930-
var seed = BitConverter.ToUInt32(dataP.AsSpan(0x20 + i * 0x20, 4));
4919+
var seed = BitConverter.ToUInt32(dataP.AsSpan(Raid.SIZE + i * Raid.SIZE, 4));
49314920
if (seed == denHexSeedUInt)
49324921
{
49334922
_seedIndexToReplace = i;
@@ -4937,21 +4926,21 @@ private async Task FindSeedIndexInRaids(uint denHexSeedUInt, CancellationToken t
49374926

49384927
// Search in Kitakami region
49394928
var dataK = await SwitchConnection.ReadBytesAbsoluteAsync(_raidBlockPointerK + 0x10, 0xC80, token).ConfigureAwait(false);
4940-
for (int i = 0; i < upperBound; i++)
4929+
for (int i = 0; i < BlueberryStartIndex; i++)
49414930
{
4942-
var seed = BitConverter.ToUInt32(dataK.AsSpan(i * 0x20, 4));
4931+
var seed = BitConverter.ToUInt32(dataK.AsSpan(i * Raid.SIZE, 4));
49434932
if (seed == denHexSeedUInt)
49444933
{
4945-
_seedIndexToReplace = i + 69;
4934+
_seedIndexToReplace = i + KitakamiStartIndex;
49464935
return;
49474936
}
49484937
}
49494938

49504939
// Search in Blueberry region
49514940
var dataB = await SwitchConnection.ReadBytesAbsoluteAsync(_raidBlockPointerB + 0x10, 0xA00, token).ConfigureAwait(false);
4952-
for (int i = startIndex; i < 118; i++)
4941+
for (int i = BlueberryStartIndex; i < 118; i++)
49534942
{
4954-
var seed = BitConverter.ToUInt32(dataB.AsSpan((i - startIndex) * 0x20, 4));
4943+
var seed = BitConverter.ToUInt32(dataB.AsSpan((i - BlueberryStartIndex) * Raid.SIZE, 4));
49554944
if (seed == denHexSeedUInt)
49564945
{
49574946
_seedIndexToReplace = i - 1;

0 commit comments

Comments
 (0)