A stable modding interface between Techblox and mods https://mod.exmods.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

56 lines
2.6KB

  1. using System;
  2. using System.Diagnostics.CodeAnalysis;
  3. using System.Linq;
  4. using System.Reflection;
  5. using HarmonyLib;
  6. using Svelto.DataStructures;
  7. using Svelto.ECS;
  8. namespace TechbloxModdingAPI.Utility.ECS
  9. {
  10. public static partial class NativeApiExtensions
  11. {
  12. [SuppressMessage("ReSharper", "StaticMemberInGenericType")]
  13. private static class EntitiesDBHelper<T> where T : unmanaged, IEntityComponent
  14. { // Each type gets a new set of fields here (that's what the ReSharper warning is about too)
  15. public static readonly Lazy<MethodInfo> EntityStream =
  16. new(() => AccessTools.PropertyGetter(typeof(EntitiesDB), "_entityStream"));
  17. public static readonly Lazy<FieldInfo> Streams = new(() =>
  18. AccessTools.Field(EntityStream.Value.ReturnType, "_streams"));
  19. public static readonly Lazy<FieldInfo> Consumers = new(() =>
  20. AccessTools.Field(typeof(EntityStream<T>), "_consumers"));
  21. public static readonly Lazy<MethodInfo> TryGetValue =
  22. new(AccessTools.Method(Streams.Value.FieldType, "TryGetValue"));
  23. public static readonly Lazy<FieldInfo> RingBuffer =
  24. new(() => AccessTools.Field(typeof(Consumer<T>), "_ringBuffer"));
  25. }
  26. private static EntityStream<T> GetEntityStream<T>(this EntitiesDB entitiesDB) where T : unmanaged, IEntityComponent
  27. {
  28. // EntitiesStreams (internal)
  29. var entitiesStreams = EntitiesDBHelper<T>.EntityStream.Value.Invoke(entitiesDB, Array.Empty<object>());
  30. // FasterDictionary<RefWrapperType, ITypeSafeStream> (interface is internal)
  31. var streams = EntitiesDBHelper<T>.Streams.Value.GetValue(entitiesStreams);
  32. var parameters = new object[] { TypeRefWrapper<T>.wrapper, null };
  33. var success = EntitiesDBHelper<T>.TryGetValue.Value.Invoke(streams, parameters);
  34. if (!(bool)success)
  35. return null; // There is no entity stream for this type
  36. return (EntityStream<T>)parameters[1];
  37. }
  38. private static ThreadSafeFasterList<Consumer<T>> GetConsumers<T>(this EntityStream<T> stream) where T : unmanaged, IEntityComponent
  39. {
  40. return (ThreadSafeFasterList<Consumer<T>>)EntitiesDBHelper<T>.Consumers.Value.GetValue(stream);
  41. }
  42. private static RingBuffer<(T, EGID)> GetRingBuffer<T>(this Consumer<T> consumer) where T : unmanaged, IEntityComponent
  43. {
  44. return (RingBuffer<(T, EGID)>)EntitiesDBHelper<T>.RingBuffer.Value.GetValue(consumer);
  45. }
  46. }
  47. }