fix(core): Removes some uses of Linq (#421)

- [X] Removes some uses of linq
- [X] Creates struct based enumerator for Skills
- [X] Creates a struct based enumerator for TypeCache
- [X] Changes HarvestDefinition to an init array instead of List
- [X] Changes HeritageTokenGump Response from List to Array
This commit is contained in:
Kamron Batman 2021-01-18 21:05:11 -08:00 committed by GitHub
parent 52356866ed
commit b921c38879
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 1006 additions and 507 deletions

View file

@ -14,6 +14,7 @@
*************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -89,40 +90,41 @@ namespace Server
return m_TypeCaches[asm] = new TypeCache(asm);
}
public static Type FindFirstTypeForName(string name, bool ignoreCase = false, Func<Type, bool> predicate = null)
private static bool IgnoreCaseTypeComparer(string name, Type type) =>
type.FullName.InsensitiveEquals(name) || type.Name.InsensitiveEquals(name);
private static bool CaseTypeComparer(string name, Type type) =>
type.FullName.EqualsOrdinal(name) || type.Name.EqualsOrdinal(name);
public static Type FindFirstTypeForName(string name, bool ignoreCase = false, Func<string, Type, bool> predicate = null)
{
if (string.IsNullOrWhiteSpace(name))
{
return null;
}
var types = FindTypesByName(name, ignoreCase).ToList();
var types = FindTypesByName(name, ignoreCase);
if (types.Count == 0)
{
return null;
}
if (predicate != null)
{
return types.FirstOrDefault(predicate);
}
if (types.Count == 1)
{
return types[0];
}
// Try to find the closest match if there is no predicate.
// Check for exact match of the FullName or Name
// Then check for case-insensitive match of FullName or Name
// Otherwise just return the first entry
var stringComparer = ignoreCase ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal;
predicate ??= ignoreCase ? IgnoreCaseTypeComparer : CaseTypeComparer;
return types.FirstOrDefault(
x =>
stringComparer.Equals(x.FullName, name) || stringComparer.Equals(x.Name, name)
) ??
types[0];
foreach (var type in types)
{
if (predicate(name, type))
{
return type;
}
}
return null;
}
public static List<Type> FindTypesByName(string name, bool ignoreCase = false)
@ -136,12 +138,18 @@ namespace Server
for (var i = 0; i < Assemblies.Length; i++)
{
types.AddRange(GetTypeCache(Assemblies[i])[name]);
foreach (var type in GetTypeCache(Assemblies[i])[name])
{
types.Add(type);
}
}
if (types.Count == 0)
{
types.AddRange(GetTypeCache(Core.Assembly)[name]);
foreach(var type in GetTypeCache(Core.Assembly)[name])
{
types.Add(type);
}
}
return types;
@ -159,11 +167,10 @@ namespace Server
public class TypeCache
{
private readonly Dictionary<string, int[]> m_NameMap = new();
private readonly Type[] m_Types;
public TypeCache(Assembly asm)
{
m_Types = asm?.GetTypes() ?? Type.EmptyTypes;
Types = asm?.GetTypes() ?? Type.EmptyTypes;
var nameMap = new Dictionary<string, HashSet<int>>();
HashSet<int> refs;
@ -181,9 +188,9 @@ namespace Server
};
var aliasType = typeof(TypeAliasAttribute);
for (var i = 0; i < m_Types.Length; i++)
for (var i = 0; i < Types.Length; i++)
{
var current = m_Types[i];
var current = Types[i];
addToRefs(i, current.Name);
addToRefs(i, current.Name.ToLower());
addToRefs(i, current.FullName);
@ -204,10 +211,70 @@ namespace Server
}
}
public IEnumerable<Type> Types => m_Types;
public IEnumerable<string> Names => m_NameMap.Keys;
public Enumerator this[string name] => new(name, this);
public IEnumerable<Type> this[string name] =>
m_NameMap.TryGetValue(name, out var value) ? value.Select(x => m_Types[x]) : Array.Empty<Type>();
public Type[] Types { get; }
public struct Enumerator : IEnumerable<Type>, IEnumerator<Type>
{
private readonly TypeCache _cache;
private readonly int[] _values;
private int _index;
private Type _current;
internal Enumerator(string name, TypeCache cache)
{
_cache = cache;
_values = !cache.m_NameMap.TryGetValue(name, out var values) ? Array.Empty<int>() : values;
_index = 0;
_current = default;
}
public void Dispose()
{
}
public bool MoveNext()
{
int[] localList = _values;
while ((uint)_index < (uint)localList.Length)
{
_current = _cache.Types[_values[_index++]];
if (_current != null)
{
return true;
}
}
return false;
}
public Type Current => _current!;
object IEnumerator.Current
{
get
{
if (_index == 0 || _index == _values.Length + 1)
{
throw new InvalidOperationException(nameof(_index));
}
return Current;
}
}
void IEnumerator.Reset()
{
_index = 0;
_current = default;
}
public IEnumerator<Type> GetEnumerator() => this;
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
}

View file

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
namespace Server.ContextMenus
{
@ -64,7 +63,21 @@ namespace Server.ContextMenus
/// <summary>
/// Returns true if this ContextMenu requires packet version 2.
/// </summary>
public bool RequiresNewPacket =>
Entries.Any(t => t.Number < 3000000 || t.Number > 3032767);
public bool RequiresNewPacket
{
get
{
for (var i = 0; i < Entries.Length; ++i)
{
var number = Entries[i].Number;
if (number < 3000000 || number > 3032767)
{
return true;
}
}
return false;
}
}
}
}

View file

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
namespace Server.Guilds
{
@ -43,11 +42,31 @@ namespace Server.Guilds
public abstract void Deserialize(IGenericReader reader);
public abstract void OnDelete(Mobile mob);
public static BaseGuild FindByName(string name) =>
World.Guilds.Values.FirstOrDefault(g => g.Name == name);
public static BaseGuild FindByName(string name)
{
foreach (var g in World.Guilds.Values)
{
if (g.Name == name)
{
return g;
}
}
public static BaseGuild FindByAbbrev(string abbr) =>
World.Guilds.Values.FirstOrDefault(g => g.Abbreviation == abbr);
return null;
}
public static BaseGuild FindByAbbrev(string abbr)
{
foreach (var g in World.Guilds.Values)
{
if (g.Abbreviation == abbr)
{
return g;
}
}
return null;
}
public static HashSet<BaseGuild> Search(string find)
{

View file

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Server.Network;
using Server.Utilities;
using QueuePool = Server.Utilities.RefPool<Server.Utilities.QueueRef<Server.Items.Container>>;
@ -1457,7 +1456,11 @@ namespace Server.Items
for (var j = 0; j < groups.Count; ++j)
{
var items = groups[j].ToArray();
var total = items.Sum(t => t.Amount);
var total = 0;
foreach (var item in items)
{
total += item.Amount;
}
if (total >= best)
{
@ -1531,9 +1534,27 @@ namespace Server.Items
return best;
}
public int GetAmount(Type type, bool recurse = true) => FindItemsByType(type, recurse).Sum(t => t.Amount);
public int GetAmount(Type type, bool recurse = true)
{
var total = 0;
foreach (var item in FindItemsByType(type, recurse))
{
total += item.Amount;
}
public int GetAmount(Type[] types, bool recurse = true) => FindItemsByType(types, recurse).Sum(t => t.Amount);
return total;
}
public int GetAmount(Type[] types, bool recurse = true)
{
var total = 0;
foreach (var item in FindItemsByType(types, recurse))
{
total += item.Amount;
}
return total;
}
public Item[] FindItemsByType(Type type, bool recurse = true)
{

View file

@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using Server.ContextMenus;
using Server.Items;
@ -3619,28 +3618,27 @@ namespace Server
var eable = map.GetItemsInRange(p, 0);
var items = eable.Where(
item =>
var items = new List<Item>();
foreach (var item in eable)
{
if (item is BaseMulti || item.ItemID > TileData.MaxItemValue)
{
if (item is BaseMulti || item.ItemID > TileData.MaxItemValue)
{
return false;
}
var id = item.ItemData;
if (id.Surface)
{
var top = item.Z + id.CalcHeight;
if (top <= maxZ && top >= z)
{
z = top;
}
}
return true;
continue;
}
).ToList();
var id = item.ItemData;
if (id.Surface)
{
var top = item.Z + id.CalcHeight;
if (top <= maxZ && top >= z)
{
z = top;
}
}
items.Add(item);
}
eable.Free();

View file

@ -17,7 +17,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime;
using System.Runtime.InteropServices;
@ -38,7 +37,9 @@ namespace Server
private static bool m_Profiling;
private static DateTime m_ProfileStart;
private static TimeSpan m_ProfileTime;
private static bool? m_IsRunningFromXUnit;
#nullable enable
private static bool? _isRunningFromXUnit;
#nullable disable
private static long m_CycleIndex;
private static readonly float[] m_CyclesPerSecond = new float[127]; // Divisible by long.MaxValue
@ -58,11 +59,31 @@ namespace Server
private const string assembliesConfiguration = "Data/assemblies.json";
public static bool IsRunningFromXUnit =>
m_IsRunningFromXUnit ??= AppDomain.CurrentDomain.GetAssemblies()
.Any(
a => a.FullName.InsensitiveStartsWith("XUNIT")
);
#nullable enable
// TODO: Find a way to get rid of this
public static bool IsRunningFromXUnit
{
get
{
if (_isRunningFromXUnit != null)
{
return _isRunningFromXUnit.Value;
}
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
{
if (a.FullName.InsensitiveStartsWith("xunit"))
{
_isRunningFromXUnit = true;
return true;
}
}
_isRunningFromXUnit = false;
return false;
}
}
#nullable disable
public static bool Profiling
{
@ -440,9 +461,11 @@ namespace Server
var assemblyPath = Path.Join(BaseDirectory, assembliesConfiguration);
// Load UOContent.dll
var assemblyFiles = JsonConfig.Deserialize<List<string>>(assemblyPath)
.Select(t => Path.Join(BaseDirectory, "Assemblies", t))
.ToArray();
var assemblyFiles = JsonConfig.Deserialize<List<string>>(assemblyPath).ToArray();
for (var i = 0; i < assemblyFiles.Length; i++)
{
assemblyFiles[i] = Path.Join(BaseDirectory, "Assemblies", assemblyFiles[i]);
}
AssemblyHandler.LoadScripts(assemblyFiles);

View file

@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using Microsoft.Toolkit.HighPerformance.Extensions;
@ -6012,7 +6011,15 @@ namespace Server
de.Responsible = list = new List<DamageEntry>();
}
var resp = list.FirstOrDefault(check => check.Damager == master);
DamageEntry resp = null;
foreach (var check in list)
{
if (check.Damager == master)
{
resp = check;
break;
}
}
if (resp == null)
{

View file

@ -1,7 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Server.Network;
namespace Server
@ -806,15 +805,9 @@ namespace Server
[CommandProperty(AccessLevel.Counselor)]
public Skill Throwing => this[SkillName.Throwing];
public IEnumerator<Skill> GetEnumerator()
{
return m_Skills.Where(s => s != null).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return m_Skills.Where(s => s != null).GetEnumerator();
}
public Enumerator GetEnumerator() => new(this);
IEnumerator<Skill> IEnumerable<Skill>.GetEnumerator() => new Enumerator(this);
IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this);
public override string ToString() => "...";
@ -902,5 +895,60 @@ namespace Server
Owner.OnSkillInvalidated(skill);
Owner.NetState.SendSkillChange(skill);
}
public struct Enumerator : IEnumerator<Skill>
{
private readonly Skills _skills;
private int _index;
private Skill _current;
internal Enumerator(Skills skills)
{
_skills = skills;
_index = 0;
_current = default;
}
public void Dispose()
{
}
public bool MoveNext()
{
Skills localList = _skills;
while ((uint)_index < (uint)localList.Length)
{
_current = localList.m_Skills[_index++];
if (_current != null)
{
return true;
}
}
return false;
}
public Skill Current => _current!;
object IEnumerator.Current
{
get
{
if (_index == 0 || _index == _skills.Length + 1)
{
throw new InvalidOperationException(nameof(_index));
}
return Current;
}
}
void IEnumerator.Reset()
{
_index = 0;
_current = default;
}
}
}
}

View file

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -224,16 +223,11 @@ namespace Server
var any = false;
m_TilesList.AddRange(
eable.SelectMany(
t =>
{
any = true;
return t;
}
)
.ToArray()
);
foreach (StaticTile[] multiTiles in eable)
{
any = true;
m_TilesList.AddRange(multiTiles);
}
eable.Free();

View file

@ -3,7 +3,6 @@ using System.Buffers.Binary;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
@ -742,7 +741,12 @@ namespace Server
var byteIndex = 0;
var length = mems.Sum(mem => mem.Length);
var length = 0;
for (var i = 0; i < mems.Length; i++)
{
length += mems[i].Length;
}
var position = 0;
var memIndex = 0;
var span = mems[memIndex].Span;
@ -1386,5 +1390,7 @@ namespace Server
i = (i & 0x3333333333333333UL) + ((i >> 2) & 0x3333333333333333UL);
return (int)(unchecked(((i + (i >> 4)) & 0xF0F0F0F0F0F0F0FUL) * 0x101010101010101UL) >> 56);
}
}
}