Style cleanup

This commit is contained in:
2025-03-02 17:19:57 +01:00
parent c0bc905c46
commit 284ab3079c
175 changed files with 588 additions and 650 deletions

View File

@@ -64,13 +64,14 @@ public class LookupGrowthRate : IGrowthRate
}
}
return (LevelInt)(_experienceTable.Length);
return (LevelInt)_experienceTable.Length;
}
/// <inheritdoc />
public uint CalculateExperience(LevelInt level)
{
if (level < 1) level = 1;
if (level < 1)
level = 1;
return level >= _experienceTable.Length ? _experienceTable[^1] : _experienceTable[level - 1];
}
}

View File

@@ -105,10 +105,10 @@ public interface IItem : INamedValue
/// A set of arbitrary flags that can be set on the item.
/// </summary>
ImmutableHashSet<StringKey> Flags { get; }
ISecondaryEffect? Effect { get; }
ISecondaryEffect? BattleEffect { get; }
byte FlingPower { get; }
/// <summary>
@@ -160,10 +160,6 @@ public class ItemImpl : IItem
/// <inheritdoc />
public byte FlingPower { get; }
/// <inheritdoc />
public bool HasFlag(string key)
{
return Flags.Contains(key);
}
public bool HasFlag(string key) => Flags.Contains(key);
}

View File

@@ -7,13 +7,13 @@ namespace PkmnLib.Static.Libraries;
/// <summary>
/// A basic library for data types. Stores data both by name and by index.
/// </summary>
public abstract class DataLibrary<T> : IEnumerable<T>
where T : INamedValue
public abstract class DataLibrary<T> : IEnumerable<T> where T : INamedValue
{
/// <summary>
/// The underlying data storage.
/// </summary>
protected readonly Dictionary<StringKey, T> Data = new();
private readonly List<T> _values = [];
/// <summary>

View File

@@ -12,24 +12,27 @@ public interface IReadOnlyGrowthRateLibrary : IEnumerable<IGrowthRate>
/// Tries to get a growth rate from the library. Returns false if the growth rate is not found.
/// </summary>
bool TryGet(StringKey key, [MaybeNullWhen(false)] out IGrowthRate value);
/// <summary>
/// Gets a random growth rate from the library.
/// </summary>
IGrowthRate GetRandom(IRandom random);
/// <summary>
/// Gets the amount of growth rates in the library.
/// </summary>
int Count { get; }
/// <summary>
/// Whether the library is empty.
/// </summary>
bool IsEmpty { get; }
/// <summary>
/// Calculates the experience for a given growth key name and a certain level.
/// </summary>
uint CalculateExperience(StringKey key, LevelInt level);
/// <summary>
/// Calculates the level for a given growth key name and a certain experience.
/// </summary>

View File

@@ -6,7 +6,7 @@ namespace PkmnLib.Static.Libraries;
/// <summary>
/// The library for all items in the game.
/// </summary>
public interface IReadOnlyItemLibrary : IEnumerable<IItem>
public interface IReadOnlyItemLibrary : IEnumerable<IItem>
{
/// <summary>
/// Tries to get an item from the library. Returns false if the item is not found.

View File

@@ -9,7 +9,7 @@ public record LibrarySettings
/// The maximum level a Pokémon can reach.
/// </summary>
public required LevelInt MaxLevel { get; init; }
/// <summary>
/// The chance of a Pokémon being shiny, as the denominator of a fraction, where the nominator
/// is 1. For example, if this is 1000, then the chance of a Pokémon being shiny is 1/1000.

View File

@@ -13,14 +13,17 @@ public interface IReadOnlyMoveLibrary : IEnumerable<IMoveData>
/// Tries to get a move from the library. Returns false if the move is not found.
/// </summary>
bool TryGet(StringKey key, [MaybeNullWhen(false)] out IMoveData value);
/// <summary>
/// Gets a random move from the library.
/// </summary>
IMoveData GetRandom(IRandom random);
/// <summary>
/// The amount of moves in the library.
/// </summary>
int Count { get; }
/// <summary>
/// Whether the library is empty.
/// </summary>

View File

@@ -13,7 +13,7 @@ public interface IReadOnlySpeciesLibrary : IEnumerable<ISpecies>
/// Tries to get a species from the library. Returns false if the species is not found.
/// </summary>
bool TryGet(StringKey key, [MaybeNullWhen(false)] out ISpecies value);
/// <summary>
/// Tried to get a species from the library by its national dex number. Returns false if the species is not found.
/// </summary>
@@ -45,7 +45,7 @@ public interface IReadOnlySpeciesLibrary : IEnumerable<ISpecies>
public class SpeciesLibrary : DataLibrary<ISpecies>, IReadOnlySpeciesLibrary
{
private Dictionary<ISpecies, ISpecies> _preEvolutionCache = new();
/// <inheritdoc />
public bool TryGetById(int id, [MaybeNullWhen(false)] out ISpecies value)
{
@@ -61,7 +61,7 @@ public class SpeciesLibrary : DataLibrary<ISpecies>, IReadOnlySpeciesLibrary
return preEvolution;
foreach (var s in this)
{
if (s.EvolutionData.All(e => e.ToSpecies != species.Name))
if (s.EvolutionData.All(e => e.ToSpecies != species.Name))
continue;
_preEvolutionCache[species] = s;
return s;

View File

@@ -9,32 +9,37 @@ public interface IStaticLibrary
/// The miscellaneous settings for the library.
/// </summary>
LibrarySettings Settings { get; }
/// <summary>
/// All data for Pokémon species.
/// </summary>
IReadOnlySpeciesLibrary Species { get; }
/// <summary>
/// All data for Pokémon moves.
/// </summary>
IReadOnlyMoveLibrary Moves { get; }
/// <summary>
/// All data for Pokémon abilities.
/// </summary>
IReadOnlyAbilityLibrary Abilities { get; }
/// <summary>
/// All data for Pokémon types and their effectiveness.
/// </summary>
IReadOnlyTypeLibrary Types { get; }
/// <summary>
/// All data for Pokémon natures.
/// </summary>
IReadOnlyNatureLibrary Natures { get; }
/// <summary>
/// All data for Pokémon growth rates.
/// </summary>
IReadOnlyGrowthRateLibrary GrowthRates { get; }
/// <summary>
/// All data for Pokémon items.
/// </summary>
@@ -45,7 +50,9 @@ public interface IStaticLibrary
public class StaticLibraryImpl : IStaticLibrary
{
/// <inheritdoc cref="StaticLibraryImpl" />
public StaticLibraryImpl(LibrarySettings settings, IReadOnlySpeciesLibrary species, IReadOnlyMoveLibrary moves, IReadOnlyAbilityLibrary abilities, IReadOnlyTypeLibrary types, IReadOnlyNatureLibrary natures, IReadOnlyGrowthRateLibrary growthRates, IReadOnlyItemLibrary items)
public StaticLibraryImpl(LibrarySettings settings, IReadOnlySpeciesLibrary species, IReadOnlyMoveLibrary moves,
IReadOnlyAbilityLibrary abilities, IReadOnlyTypeLibrary types, IReadOnlyNatureLibrary natures,
IReadOnlyGrowthRateLibrary growthRates, IReadOnlyItemLibrary items)
{
Settings = settings;
Species = species;

View File

@@ -88,7 +88,7 @@ public class TypeLibrary : IReadOnlyTypeLibrary
/// </summary>
public TypeIdentifier RegisterType(StringKey name)
{
var id = new TypeIdentifier((byte)( _types.Count + 1));
var id = new TypeIdentifier((byte)(_types.Count + 1));
_types.Add(name, id);
_effectiveness.Add(Enumerable.Repeat(1.0f, _effectiveness.Count).ToList());
foreach (var list in _effectiveness)

View File

@@ -11,12 +11,12 @@ public interface ISecondaryEffect
/// The chance in percentages that the effect triggers. When less than 0, the effect is always active.
/// </summary>
public float Chance { get; }
/// <summary>
/// The name of the effect.
/// </summary>
public StringKey Name { get; }
/// <summary>
/// Parameters for the effect.
/// </summary>

View File

@@ -50,8 +50,7 @@ public class Nature(
Statistic increaseStat,
Statistic decreaseStat,
float increaseModifier,
float decreaseModifier)
: INature
float decreaseModifier) : INature
{
/// <inheritdoc />
public StringKey Name { get; } = name;
@@ -79,8 +78,6 @@ public class Nature(
}
/// <inheritdoc />
public bool Equals(INature? other)
{
return other is not null && StringComparer.InvariantCultureIgnoreCase.Equals(Name, other.Name);
}
public bool Equals(INature? other) =>
other is not null && StringComparer.InvariantCultureIgnoreCase.Equals(Name, other.Name);
}

View File

@@ -18,7 +18,7 @@ public interface IAbility : INamedValue
/// The parameters for the script effect of the ability.
/// </summary>
IReadOnlyDictionary<StringKey, object?> Parameters { get; }
bool HasFlag(StringKey key);
}
@@ -26,7 +26,8 @@ public interface IAbility : INamedValue
public class AbilityImpl : IAbility
{
/// <inheritdoc cref="AbilityImpl" />
public AbilityImpl(StringKey name, StringKey? effect, IReadOnlyDictionary<StringKey, object?> parameters, ImmutableHashSet<StringKey> flags)
public AbilityImpl(StringKey name, StringKey? effect, IReadOnlyDictionary<StringKey, object?> parameters,
ImmutableHashSet<StringKey> flags)
{
Name = name;
Effect = effect;
@@ -46,10 +47,7 @@ public class AbilityImpl : IAbility
public ImmutableHashSet<StringKey> Flags;
/// <inheritdoc />
public bool HasFlag(StringKey key)
{
return Flags.Contains(key);
}
public bool HasFlag(StringKey key) => Flags.Contains(key);
}
/// <summary>

View File

@@ -95,8 +95,8 @@ public interface IForm : INamedValue
public class FormImpl : IForm
{
/// <inheritdoc cref="FormImpl" />
public FormImpl(StringKey name, float height, float weight, uint baseExperience,
IEnumerable<TypeIdentifier> types, ImmutableStatisticSet<ushort> baseStats, IEnumerable<StringKey> abilities,
public FormImpl(StringKey name, float height, float weight, uint baseExperience, IEnumerable<TypeIdentifier> types,
ImmutableStatisticSet<ushort> baseStats, IEnumerable<StringKey> abilities,
IEnumerable<StringKey> hiddenAbilities, ILearnableMoves moves, ImmutableHashSet<StringKey> flags)
{
Name = name;
@@ -109,7 +109,7 @@ public class FormImpl : IForm
HiddenAbilities = [..hiddenAbilities];
Moves = moves;
Flags = flags;
if (Types.Count == 0)
throw new ArgumentException("A form must have at least one type.");
if (Abilities.Count == 0)
@@ -163,20 +163,24 @@ public class FormImpl : IForm
for (var i = 0; i < Abilities.Count && i < 255; i++)
{
if (Abilities[i] == ability.Name)
{
return new AbilityIndex
{
IsHidden = false,
Index = (byte)i,
};
}
}
for (var i = 0; i < HiddenAbilities.Count && i < 255; i++)
{
if (HiddenAbilities[i] == ability.Name)
{
return new AbilityIndex
{
IsHidden = true,
Index = (byte)i,
};
}
}
return null;
}
@@ -191,20 +195,11 @@ public class FormImpl : IForm
}
/// <inheritdoc />
public StringKey GetRandomAbility(IRandom rand)
{
return Abilities[rand.GetInt(Abilities.Count)];
}
public StringKey GetRandomAbility(IRandom rand) => Abilities[rand.GetInt(Abilities.Count)];
/// <inheritdoc />
public StringKey GetRandomHiddenAbility(IRandom rand)
{
return HiddenAbilities[rand.GetInt(HiddenAbilities.Count)];
}
public StringKey GetRandomHiddenAbility(IRandom rand) => HiddenAbilities[rand.GetInt(HiddenAbilities.Count)];
/// <inheritdoc />
public bool HasFlag(string key)
{
return Flags.Contains(key);
}
public bool HasFlag(string key) => Flags.Contains(key);
}

View File

@@ -10,10 +10,12 @@ public enum Gender : byte
{
/// The Pokémon has no gender.
Genderless,
/// <summary>
/// The Pokémon is male.
/// </summary>
Male,
/// <summary>
/// The Pokémon is female.
/// </summary>

View File

@@ -14,7 +14,7 @@ public interface ILearnableMoves
/// <param name="move">The move the Pokémon learns.</param>
/// <returns>Whether the move was added successfully.</returns>
void AddLevelMove(LevelInt level, StringKey move);
/// <summary>
/// Adds a new egg move the Pokémon can learn.
/// </summary>
@@ -38,7 +38,7 @@ public interface ILearnableMoves
/// Gets a list of all moves a Pokémon can learn up to a specific level.
/// </summary>
IReadOnlyList<StringKey> GetLearnableMovesUpToLevel(LevelInt level);
/// <summary>
/// Gets all moves a Pokémon can learn by breeding.
/// </summary>
@@ -50,9 +50,8 @@ public class LearnableMovesImpl : ILearnableMoves
{
private readonly Dictionary<LevelInt, List<StringKey>> _learnedByLevel = new();
private readonly HashSet<StringKey> _distinctLevelMoves = new();
private readonly List<StringKey> _eggMoves = new();
private readonly List<StringKey> _eggMoves = new();
/// <inheritdoc />
public void AddLevelMove(LevelInt level, StringKey move)
@@ -81,10 +80,7 @@ public class LearnableMovesImpl : ILearnableMoves
}
/// <inheritdoc />
public IReadOnlyList<StringKey> GetDistinctLevelMoves()
{
return _distinctLevelMoves.ToList();
}
public IReadOnlyList<StringKey> GetDistinctLevelMoves() => _distinctLevelMoves.ToList();
/// <inheritdoc />
public IReadOnlyList<StringKey> GetLearnableMovesUpToLevel(LevelInt level)

View File

@@ -50,7 +50,7 @@ public interface ISpecies : INamedValue
/// Gets a form by name.
/// </summary>
bool TryGetForm(StringKey id, [MaybeNullWhen(false)] out IForm form);
/// <summary>
/// Gets the form the Pokémon will have by default, if no other form is specified.
/// </summary>
@@ -70,7 +70,7 @@ public interface ISpecies : INamedValue
/// The data regarding into which Pokémon this species can evolve, and how.
/// </summary>
IReadOnlyList<IEvolution> EvolutionData { get; }
/// <summary>
/// The egg groups the Pokémon belongs to.
/// </summary>
@@ -124,14 +124,13 @@ public class SpeciesImpl : ISpecies
/// <inheritdoc />
public ImmutableHashSet<StringKey> Flags { get; }
/// <inheritdoc />
public IReadOnlyList<IEvolution> EvolutionData { get; }
/// <inheritdoc />
public ICollection<StringKey> EggGroups { get; }
/// <inheritdoc />
public bool TryGetForm(StringKey id, [MaybeNullWhen(false)] out IForm form) => Forms.TryGetValue(id, out form);

View File

@@ -9,33 +9,38 @@ public enum Statistic : byte
/// Health Points determine how much damage a Pokémon can receive before fainting.
/// </summary>
Hp,
/// <summary>
/// Attack determines how much damage a Pokémon deals when using a physical attack.
/// </summary>
Attack,
/// <summary>
/// Defense determines how much damage a Pokémon receives when it is hit by a physical attack.
/// </summary>
Defense,
/// <summary>
/// Special Attack determines how much damage a Pokémon deals when using a special attack.
/// </summary>
SpecialAttack,
/// <summary>
/// Special Defense determines how much damage a Pokémon receives when it is hit by a special attack.
/// </summary>
SpecialDefense,
/// <summary>
/// Speed determines the order that a Pokémon can act in battle.
/// </summary>
Speed,
/// <summary>
/// Evasion determines the likelihood that a Pokémon will dodge an attack.
/// This is not part of base stats, but is a temporary stat boost.
/// </summary>
Evasion,
/// <summary>
/// Accuracy determines the likelihood that a Pokémon will hit an attack.
/// This is not part of base stats, but is a temporary stat boost.

View File

@@ -8,8 +8,7 @@ namespace PkmnLib.Static;
/// A set of statistics that cannot be changed.
/// </summary>
/// <typeparam name="T">The size of the integer to be used</typeparam>
public record ImmutableStatisticSet<T>
where T : struct
public record ImmutableStatisticSet<T> where T : struct
{
/// <summary>
/// The health points stat value.
@@ -51,7 +50,7 @@ public record ImmutableStatisticSet<T>
SpecialDefense = specialDefense;
Speed = speed;
}
public ImmutableStatisticSet(ImmutableStatisticSet<T> set)
{
Hp = set.Hp;
@@ -84,8 +83,7 @@ public record ImmutableStatisticSet<T>
/// A set of statistics that can be changed.
/// </summary>
/// <typeparam name="T"></typeparam>
public record StatisticSet<T> : ImmutableStatisticSet<T>, IEnumerable<T>, IDeepCloneable
where T : struct
public record StatisticSet<T> : ImmutableStatisticSet<T>, IEnumerable<T>, IDeepCloneable where T : struct
{
/// <inheritdoc cref="StatisticSet{T}"/>
public StatisticSet() : base(default, default, default, default, default, default)
@@ -97,7 +95,7 @@ public record StatisticSet<T> : ImmutableStatisticSet<T>, IEnumerable<T>, IDeepC
defense, specialAttack, specialDefense, speed)
{
}
public StatisticSet(StatisticSet<T> set) : base(set)
{
}
@@ -175,16 +173,12 @@ public record StatisticSet<T> : ImmutableStatisticSet<T>, IEnumerable<T>, IDeepC
return true;
}
protected virtual T GetUnknownStat(Statistic stat)
{
throw new ArgumentException($"Invalid statistic {stat}");
}
protected virtual T GetUnknownStat(Statistic stat) => throw new ArgumentException($"Invalid statistic {stat}");
protected virtual void SetUnknownStat(Statistic stat, T value)
{
throw new ArgumentException($"Invalid statistic {stat}");
}
/// <summary>
/// Decreases a statistic in the set by a value.
@@ -231,17 +225,13 @@ public record StatisticSet<T> : ImmutableStatisticSet<T>, IEnumerable<T>, IDeepC
}
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
/// <summary>
/// A set of statistics that can be changed, but are clamped to a minimum and maximum value.
/// </summary>
public abstract record ClampedStatisticSet<T> : StatisticSet<T>
where T : struct, IComparable<T>
public abstract record ClampedStatisticSet<T> : StatisticSet<T> where T : struct, IComparable<T>
{
/// <inheritdoc />
[SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")]
@@ -257,7 +247,7 @@ public abstract record ClampedStatisticSet<T> : StatisticSet<T>
SpecialDefense = Clamp(SpecialDefense, Min, Max);
Speed = Clamp(Speed, Min, Max);
}
protected ClampedStatisticSet(ClampedStatisticSet<T> set) : base(set)
{
}
@@ -322,13 +312,15 @@ public record StatBoostStatisticSet : ClampedStatisticSet<sbyte>
protected override sbyte Max => 6;
private sbyte _evasion;
public sbyte Evasion
{
get => _evasion;
set => _evasion = Clamp(value, Min, Max);
}
private sbyte _accuracy;
public sbyte Accuracy
{
get => _accuracy;
@@ -403,13 +395,13 @@ public record IndividualValueStatisticSet : ClampedStatisticSet<byte>
public IndividualValueStatisticSet() : base(0, 0, 0, 0, 0, 0)
{
}
/// <inheritdoc cref="IndividualValueStatisticSet"/>
public IndividualValueStatisticSet(byte hp, byte attack, byte defense, byte specialAttack, byte specialDefense,
byte speed) : base(hp, attack, defense, specialAttack, specialDefense, speed)
{
}
public IndividualValueStatisticSet(IndividualValueStatisticSet ivs) : base(ivs)
{
}
@@ -436,7 +428,7 @@ public record EffortValueStatisticSet : ClampedStatisticSet<byte>
byte speed) : base(hp, attack, defense, specialAttack, specialDefense, speed)
{
}
public EffortValueStatisticSet(EffortValueStatisticSet evs) : base(evs)
{
}

View File

@@ -25,11 +25,9 @@ public static class DeepCloneHandler
/// Recursive references will be handled correctly, and will only be cloned once, to prevent infinite loops and invalid
/// references.
/// </summary>
public static T DeepClone<T>(this T? obj, Dictionary<(Type, int), object>? objects = null) where T : IDeepCloneable
{
return (T)DeepClone((object?)obj, objects)!;
}
public static T DeepClone<T>(this T? obj, Dictionary<(Type, int), object>? objects = null)
where T : IDeepCloneable => (T)DeepClone((object?)obj, objects)!;
private static object? DeepClone(this object? obj, Dictionary<(Type, int), object>? objects = null)
{
if (obj == null)
@@ -41,7 +39,7 @@ public static class DeepCloneHandler
// We use GetUninitializedObject to create an object without calling the constructor. This is necessary to prevent
// side effects from the constructor, and to not require a parameterless constructor.
var newObj = FormatterServices.GetUninitializedObject(type)!;
// If the objects dictionary is null, we create a new one. We use this dictionary to keep track of objects that have
// already been cloned, so we can re-use them instead of cloning them again. This is necessary to prevent infinite
// loops and invalid references.
@@ -74,7 +72,7 @@ public static class DeepCloneHandler
// If the object is a value type or a string, we can just return it.
if (type.IsValueType || type == typeof(string))
return obj;
// If the object is marked as deep cloneable, we will clone it.
if (type.GetInterface(nameof(IDeepCloneable)) != null || ExternalDeepCloneTypes.Contains(type))
{
@@ -91,8 +89,9 @@ public static class DeepCloneHandler
var array = (Array)obj;
var newArray = Array.CreateInstance(type.GetElementType()!, array.Length);
for (var i = 0; i < array.Length; i++)
newArray.SetValue(DeepCloneInternal(array.GetValue(i), type.GetElementType()!, objects),
i);
{
newArray.SetValue(DeepCloneInternal(array.GetValue(i), type.GetElementType()!, objects), i);
}
return newArray;
}
@@ -115,9 +114,10 @@ public static class DeepCloneHandler
var dictionary = (IDictionary)obj;
var newDictionary = (IDictionary)Activator.CreateInstance(type);
foreach (DictionaryEntry entry in dictionary)
newDictionary.Add(
DeepCloneInternal(entry.Key, type.GetGenericArguments()[0], objects)!,
{
newDictionary.Add(DeepCloneInternal(entry.Key, type.GetGenericArguments()[0], objects)!,
DeepCloneInternal(entry.Value, type.GetGenericArguments()[1], objects));
}
return newDictionary;
}
}
@@ -133,8 +133,7 @@ public static class DeepCloneHandler
/// This method is thread safe, and will only create the expressions once for each type. It returns compiled expressions for
/// each field in the type, so that we can get high performance deep cloning.
/// </remarks>
private static (Func<object, object?> getter, Action<object, object?> setter)[]
GetDeepCloneExpressions(Type type)
private static (Func<object, object?> getter, Action<object, object?> setter)[] GetDeepCloneExpressions(Type type)
{
// We use a lock here to prevent multiple threads from trying to create the expressions at the same time.
lock (DeepCloneExpressions)

View File

@@ -2,7 +2,8 @@ namespace PkmnLib.Static.Utils;
public static class DictionaryHelpers
{
public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key,
TValue defaultValue)
{
if (dictionary.TryGetValue(key, out var value))
return value;

View File

@@ -10,7 +10,7 @@ public static class EnumerableHelpers
/// </summary>
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> enumerable) where T : class =>
enumerable.Where(x => x is not null)!;
/// <summary>
/// Finds the index of a value in an enumerable. Returns -1 if the value is not found.
/// </summary>

View File

@@ -1,4 +1,3 @@
namespace PkmnLib.Static.Utils.Errors;
/// <summary>

View File

@@ -13,7 +13,7 @@ public static class NumericHelpers
var result = value * multiplier;
return result > byte.MaxValue ? byte.MaxValue : (byte)result;
}
/// <summary>
/// Multiplies two values. If this overflows, returns <see cref="byte.MaxValue"/>.
/// </summary>
@@ -22,7 +22,7 @@ public static class NumericHelpers
var result = value * multiplier;
return result > byte.MaxValue ? byte.MaxValue : (byte)result;
}
/// <summary>
/// Multiplies two values. If this overflows, returns <see cref="sbyte.MaxValue"/>.
/// </summary>
@@ -31,7 +31,7 @@ public static class NumericHelpers
var result = value * multiplier;
return result > sbyte.MaxValue ? sbyte.MaxValue : (sbyte)result;
}
/// <summary>
/// Multiplies two values. If this overflows, returns <see cref="ushort.MaxValue"/>.
/// </summary>
@@ -40,7 +40,7 @@ public static class NumericHelpers
var result = value * multiplier;
return result > ushort.MaxValue ? ushort.MaxValue : (ushort)result;
}
/// <summary>
/// Multiplies two values. If this overflows, returns <see cref="short.MaxValue"/>.
/// </summary>
@@ -49,11 +49,10 @@ public static class NumericHelpers
var result = value * multiplier;
return result > short.MaxValue ? short.MaxValue : (short)result;
}
public static uint MultiplyOrMax(this uint value, uint multiplier)
{
var result = (ulong)value * multiplier;
return result > uint.MaxValue ? uint.MaxValue : (uint)result;
}
}

View File

@@ -21,19 +21,19 @@ public interface IRandom
/// <param name="max">The maximum value (exclusive).</param>
/// <returns>A random integer that is greater than or equal to 0 and less than max.</returns>
public int GetInt(int max);
/// <summary>
/// Get a random integer between 0 and <see cref="int.MaxValue"/>.
/// </summary>
/// <returns>A random integer that is greater than or equal to 0 and less than <see cref="int.MaxValue"/>.</returns>
public int GetInt();
/// <summary>
/// Get a random float that is greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <returns>A random float that is greater than or equal to 0.0 and less than 1.0.</returns>
public float GetFloat();
/// <summary>
/// Get a random float that is greater than or equal to min and less than max.
/// </summary>
@@ -41,7 +41,7 @@ public interface IRandom
/// <param name="max">The maximum value (exclusive).</param>
/// <returns>A random float that is greater than or equal to min and less than max.</returns>
public float GetFloat(float min, float max);
/// <summary>
/// Get a random boolean. 50% chance of being true.
/// </summary>

View File

@@ -22,14 +22,12 @@ public readonly record struct StringKey
/// Converts a <see cref="StringKey"/> to a <see cref="string"/>.
/// </summary>
public static implicit operator string(StringKey key) => key._key;
/// <summary>
/// Converts a <see cref="string"/> to a <see cref="StringKey"/>.
/// </summary>
public static implicit operator StringKey(string key)
{
return string.IsNullOrWhiteSpace(key) ? default : new StringKey(key);
}
public static implicit operator StringKey(string key) =>
string.IsNullOrWhiteSpace(key) ? default : new StringKey(key);
/// <inheritdoc cref="string.ToString()"/>
public override string ToString() => _key.ToLowerInvariant();