using System; using System.Runtime.InteropServices; using gaemstone.ECS.Utility; using static flecs_hub.flecs; namespace gaemstone.ECS; public unsafe struct World : IEquatable , IDisposable { public ecs_world_t* Handle { get; } public bool IsDeferred => ecs_is_deferred(this); public bool IsQuitRequested => ecs_should_quit(this); public World(ecs_world_t* handle) => Handle = handle; /// Initializes a new Flecs world. /// If true, doesn't automatically import built-in modules. public World(bool minimal = false) { [UnmanagedCallersOnly] static void Abort() => throw new FlecsAbortException(); ecs_os_set_api_defaults(); var api = ecs_os_get_api(); api.abort_ = new FnPtr_Void { Pointer = &Abort }; ecs_os_set_api(&api); Handle = minimal ? ecs_mini() : ecs_init(); } public bool Progress(TimeSpan delta) => ecs_progress(this, (float)delta.TotalSeconds); public void Quit() => ecs_quit(this); public void Dispose() => ecs_fini(this); public Entity LookupAlive(Entity value) => new(ecs_get_alive(this, value)); public Entity LookupPath(EntityPath path, Entity parent = default, bool throwOnNotFound = false) => new(EntityPath.Lookup(this, path, parent, throwOnNotFound)); // TODO: Provide overload that uses a UTF-8 byte span? public Entity LookupSymbol(string symbol) { using var alloc = TempAllocator.Use(); return new(ecs_lookup_symbol(this, alloc.AllocateCString(symbol), false)); } public bool Equals(World other) { if (Handle == other.Handle) return true; return ecs_get_world((ecs_poly_t*)Handle) == ecs_get_world((ecs_poly_t*)other.Handle); } public override bool Equals(object? obj) => (obj is World other) && Equals(other); public override int GetHashCode() => ((nint)ecs_get_world((ecs_poly_t*)Handle)).GetHashCode(); public static bool operator ==(World left, World right) => left.Equals(right); public static bool operator !=(World left, World right) => !left.Equals(right); public static implicit operator ecs_world_t*(World w) => w.Handle; }