Make NPCLock a readonly struct

Reduces allocation, improves locality of data since the contents take less size than a pointer (can pass byval)
This commit is contained in:
Kurt 2021-08-21 17:44:43 -07:00
parent ae0ca49628
commit 65c5890e1f
3 changed files with 45 additions and 12 deletions

View file

@ -3,7 +3,7 @@ namespace PKHeX.Core
/// <summary>
/// Locks associated to a given NPC PKM that appears before a <see cref="EncounterStaticShadow"/>.
/// </summary>
public sealed class NPCLock
public readonly struct NPCLock
{
public readonly short Species;
public readonly byte Nature;
@ -12,18 +12,26 @@ namespace PKHeX.Core
public readonly bool Shadow;
public readonly bool Seen;
public int FramesConsumed => Seen ? 5 : 7;
// Not-Shadow
public NPCLock(short s, byte n, byte g, byte r)
{
Species = s;
Nature = n;
Gender = g;
Ratio = r;
Shadow = false;
Seen = false;
}
// Shadow
public NPCLock(short s, bool seen = false)
{
Species = s;
Nature = 25;
Nature = 0;
Gender = 0;
Ratio = 0;
Shadow = true;
Seen = seen;
}
@ -39,6 +47,26 @@ namespace PKHeX.Core
return true;
}
internal NPCLock Clone() => (NPCLock)MemberwiseClone();
public override bool Equals(object obj) => false;
public override int GetHashCode() => 0;
public static bool operator ==(NPCLock left, NPCLock right) => left.Equals(right);
public static bool operator !=(NPCLock left, NPCLock right) => !(left == right);
#if DEBUG
public override string ToString()
{
var sb = new System.Text.StringBuilder(64);
sb.Append((Species)Species);
if (Shadow)
sb.Append(" (Shadow)");
if (Seen)
sb.Append(" [Seen]");
sb.Append(" - ");
sb.Append("Nature: ").Append((Nature)Nature);
if (Gender != 2)
sb.Append(", ").Append("Gender: ").Append(Gender);
return sb.ToString();
}
#endif
}
}
}

View file

@ -6,8 +6,6 @@ namespace PKHeX.Core
public readonly string Comment;
public readonly NPCLock[] Locks;
internal TeamLock Clone() => new(Species, Comment, (NPCLock[])Locks.Clone());
public TeamLock(int species, NPCLock[] locks)
{
Species = species;
@ -21,5 +19,12 @@ namespace PKHeX.Core
Locks = locks;
Comment = comment;
}
public override string ToString()
{
if (Comment.Length == 0)
return $"{(Species)Species} [{Locks.Length}]";
return $"{(Species)Species} [{Locks.Length}] - {Comment}";
}
}
}
}

View file

@ -61,7 +61,7 @@ namespace PKHeX.Core
internal TeamLockResult(TeamLock teamSpec, uint originSeed, int tsv)
{
Locks = new Stack<NPCLock>((Specifications = teamSpec).Locks);
Team = new Stack<SeedFrame>();
Team = new Stack<SeedFrame>(Locks.Count);
Cache = new FrameCache(RNG.XDRNG.Reverse(originSeed, 2), RNG.XDRNG.Prev);
TSV = tsv;
@ -107,7 +107,7 @@ namespace PKHeX.Core
if (prior?.Shadow != false)
return GetSingleLock(ctr, current);
return GetAllLocks(ctr, current, prior);
return GetAllLocks(ctr, current, (NPCLock)prior);
}
/// <summary>
@ -120,7 +120,7 @@ namespace PKHeX.Core
{
uint pid = Cache[ctr + 1] << 16 | Cache[ctr];
if (current.MatchesLock(pid))
yield return new SeedFrame(pid, ctr + (current.Seen ? 5 : 7));
yield return new SeedFrame(pid, ctr + current.FramesConsumed);
else
yield break;
@ -156,7 +156,7 @@ namespace PKHeX.Core
yield break; // Since we can't skip this interrupt, we're done.
}
// Yield the final rerolled pid instead of the bad anti-shiny (metadata/validation).
yield return new SeedFrame(pid, start + (current.Seen ? 5 : 7));
yield return new SeedFrame(pid, start + current.FramesConsumed);
start += 2;
}
}
@ -217,7 +217,7 @@ namespace PKHeX.Core
}
uint pid = Cache[ctr + 1] << 16 | Cache[ctr];
if (current.MatchesLock(pid))
yield return new SeedFrame(pid, ctr + (current.Seen ? 5 : 7));
yield return new SeedFrame(pid, ctr + current.FramesConsumed);
ctr += 2;
}