Skip to content

Commit

Permalink
Added back field based ccCustoms, while retaining identifier based lo…
Browse files Browse the repository at this point in the history
…okups.
  • Loading branch information
CptMoore committed Mar 2, 2025
1 parent 1f14464 commit d6f9ae9
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 54 deletions.
92 changes: 58 additions & 34 deletions source/CustomComponents/CCLight/Database.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,27 @@ namespace CustomComponents;

public class Database
{
internal static T GetCustom<T>(object target)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static CCFlags GetCCFlags(object target, ref List<object> customs)
{
var identifier = Identifier(target);

if (identifier == null)
var count = CustomsCountAndEnsureCustomsField(target, ref customs);
if (count == 0)
{
return default;
return null;
}
// CCFlags is kept in front to improve combat performance
return customs[0] as CCFlags;
}

if (!Customs.TryGetValue(identifier, out var customs))
internal static T GetCustom<T>(object target, ref List<object> customs)
{
var count = CustomsCountAndEnsureCustomsField(target, ref customs);
if (count == 0)
{
return default;
}

for (var index = 0; index < customs.Length; index++)
for (var index = 0; index < count; index++)
{
if (customs[index] is T csT)
{
Expand All @@ -34,18 +40,37 @@ internal static T GetCustom<T>(object target)
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool Is<T>(object target, out T value)
internal static bool Is<T>(object target, ref List<object> customs, out T value)
{
value = GetCustom<T>(target);
value = GetCustom<T>(target, ref customs);
return value != null;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool Is<T>(object target)
internal static bool Is<T>(object target, ref List<object> customs)
{
return GetCustom<T>(target) != null;
return GetCustom<T>(target, ref customs) != null;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int CustomsCountAndEnsureCustomsField(object target, ref List<object> customs)
{
if (customs == null)
{
var identifier = Identifier(target);

if (identifier == null)
{
return 0;
}

if (!Customs.TryGetValue(identifier, out customs))
{
Customs[identifier] = customs = [];
}
}
return customs.Count;
}
internal static string Identifier(object target)
{
if (target == null)
Expand All @@ -63,21 +88,17 @@ internal static string Identifier(object target)
};
}

internal static IEnumerable<T> GetCustoms<T>(object target)
internal static IEnumerable<T> GetCustoms<T>(object target, ref List<object> customs)
{
var identifier = Identifier(target);

if (identifier == null)
{
yield break;
}

if (!Customs.TryGetValue(identifier, out var customs))
{
yield break;
}

for (var index = 0; index < customs.Length; index++)
var count = CustomsCountAndEnsureCustomsField(target, ref customs);
return count == 0
? []
: GetCustomsIter<T>(customs, count);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static IEnumerable<T> GetCustomsIter<T>(List<object> customs, int count)
{
for (var index = 0; index < count; index++)
{
if (customs[index] is T csT)
{
Expand All @@ -86,23 +107,27 @@ internal static IEnumerable<T> GetCustoms<T>(object target)
}
}

private static readonly Dictionary<string, object[]> Customs = new(StringComparer.Ordinal);
private static readonly Dictionary<string, List<object>> Customs = new(StringComparer.Ordinal);
internal static bool AddCustom(object target, ICustom cc)
{
var identifier = Identifier(target);

if (identifier == null)
{
return false;
}

Customs.TryGetValue(identifier, out var customs);
if (!Customs.TryGetValue(identifier, out var customs))
{
Customs[identifier] = customs = [];
}

Log.CCLoading.Trace?.Log($"{nameof(AddCustom)} identifier={identifier} cc={cc} cc.type={cc.GetType()}");

var attribute = GetAttributeByType(cc.GetType());
Log.CCLoading.Trace?.Log($"--{nameof(CustomComponentAttribute)} {nameof(attribute.Name)}={attribute.Name} {nameof(attribute.AllowArray)}={attribute.AllowArray}");

if (customs is { Length: > 0 } && !attribute.AllowArray)
if (customs is { Count: > 0 } && !attribute.AllowArray)
{
var isDuplicate = customs
.Select(custom => GetAttributeByType(custom.GetType()))
Expand All @@ -117,17 +142,16 @@ internal static bool AddCustom(object target, ICustom cc)
}

Log.CCLoading.Trace?.Log("--added");
if (customs == null)
if (cc.GetType() == typeof(CCFlags))
{
Customs[identifier] = [cc];
// CCFlags is kept in front to improve combat performance
customs.Insert(0, cc);
}
else
{
var newCustoms = new object[customs.Length + 1];
Array.Copy(customs, newCustoms, customs.Length);
newCustoms[customs.Length] = cc;
Customs[identifier] = newCustoms;
customs.Add(cc);
}

return true;
}

Expand Down
38 changes: 22 additions & 16 deletions source/CustomComponents/CCLight/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,31 @@ public static class MechComponentDefExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T GetComponent<T>(this MechComponentDef target)
{
return Database.GetCustom<T>(target);
return Database.GetCustom<T>(target, ref target.ccCustoms);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IEnumerable<T> GetComponents<T>(this MechComponentDef target)
{
return Database.GetCustoms<T>(target);
return Database.GetCustoms<T>(target, ref target.ccCustoms);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Is<T>(this MechComponentDef target, out T res)
{
return Database.Is(target, out res);
if (typeof(T) == typeof(CCFlags))
{
// CCFlags is kept in front to improve combat performance
res = (T)(object)Database.GetCCFlags(target, ref target.ccCustoms);
return res != null;
}
return Database.Is(target, ref target.ccCustoms, out res);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Is<T>(this MechComponentDef target)
{
return Database.Is<T>(target);
return Database.Is<T>(target, ref target.ccCustoms);
}

public static T AddComponent<T>(this MechComponentDef target, T component) where T : ICustom
Expand Down Expand Up @@ -61,25 +67,25 @@ public static class VehicleExtentions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T GetComponent<T>(this VehicleChassisDef target)
{
return Database.GetCustom<T>(target);
return Database.GetCustom<T>(target, ref target.ccCustoms);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IEnumerable<T> GetComponents<T>(this VehicleChassisDef target)
{
return Database.GetCustoms<T>(target);
return Database.GetCustoms<T>(target, ref target.ccCustoms);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Is<T>(this VehicleChassisDef target, out T res)
{
return Database.Is(target, out res);
return Database.Is(target, ref target.ccCustoms, out res);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Is<T>(this VehicleChassisDef target)
{
return Database.Is<T>(target);
return Database.Is<T>(target, ref target.ccCustoms);
}
}

Expand All @@ -88,25 +94,25 @@ public static class MechDefExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T GetComponent<T>(this MechDef target)
{
return Database.GetCustom<T>(target);
return Database.GetCustom<T>(target, ref target.ccCustoms);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IEnumerable<T> GetComponents<T>(this MechDef target)
{
return Database.GetCustoms<T>(target);
return Database.GetCustoms<T>(target, ref target.ccCustoms);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Is<T>(this MechDef target, out T res)
{
return Database.Is(target, out res);
return Database.Is(target, ref target.ccCustoms, out res);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Is<T>(this MechDef target)
{
return Database.Is<T>(target);
return Database.Is<T>(target, ref target.ccCustoms);
}

public static bool IsBroken(this MechDef def)
Expand Down Expand Up @@ -150,25 +156,25 @@ public static class ChassisDefExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T GetComponent<T>(this ChassisDef target)
{
return Database.GetCustom<T>(target);
return Database.GetCustom<T>(target, ref target.ccCustoms);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IEnumerable<T> GetComponents<T>(this ChassisDef target)
{
return Database.GetCustoms<T>(target);
return Database.GetCustoms<T>(target, ref target.ccCustoms);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Is<T>(this ChassisDef target, out T res)
{
return Database.Is(target, out res);
return Database.Is(target, ref target.ccCustoms, out res);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Is<T>(this ChassisDef target)
{
return Database.Is<T>(target);
return Database.Is<T>(target, ref target.ccCustoms);
}

public static T AddComponent<T>(this ChassisDef target, T component) where T : ICustom
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

<!-- customs -->
<AddField ToType="BattleTech.MechComponentDef" InAssembly="Assembly-CSharp"
Name="ccCustoms" OfType="System.Object[]" />
Name="ccCustoms" OfType="System.Collections.Generic.List<System.Object>" />
<AddField ToType="BattleTech.VehicleChassisDef" InAssembly="Assembly-CSharp"
Name="ccCustoms" OfType="System.Object[]" />
Name="ccCustoms" OfType="System.Collections.Generic.List<System.Object>" />
<AddField ToType="BattleTech.MechDef" InAssembly="Assembly-CSharp"
Name="ccCustoms" OfType="System.Object[]" />
Name="ccCustoms" OfType="System.Collections.Generic.List<System.Object>" />
<AddField ToType="BattleTech.ChassisDef" InAssembly="Assembly-CSharp"
Name="ccCustoms" OfType="System.Object[]" />
Name="ccCustoms" OfType="System.Collections.Generic.List<System.Object>" />
</ModTekSimpleInjector>

0 comments on commit d6f9ae9

Please sign in to comment.