diff options
| author | Joel Stålnacke <joel@saker.fi> | 2026-03-23 19:50:18 +0200 |
|---|---|---|
| committer | Joel Stålnacke <joel@saker.fi> | 2026-03-23 19:50:18 +0200 |
| commit | 3a1f9fe6800ef5fe7bbf1c0a5976720383ba84fe (patch) | |
| tree | f1218eb4085a654f6bb70671b41b4a74e646c052 /Djup.Native/src | |
| parent | 3870982f640260822bf605e693782ce9f5d79cf6 (diff) | |
Rewrite native code in Odin and use ECSodin
Diffstat (limited to 'Djup.Native/src')
| -rw-r--r-- | Djup.Native/src/Djup.Native.csproj | 2 | ||||
| -rw-r--r-- | Djup.Native/src/LibDjup.cs | 74 | ||||
| -rw-r--r-- | Djup.Native/src/Types.cs | 126 |
3 files changed, 131 insertions, 71 deletions
diff --git a/Djup.Native/src/Djup.Native.csproj b/Djup.Native/src/Djup.Native.csproj index a581a58..f2a149b 100644 --- a/Djup.Native/src/Djup.Native.csproj +++ b/Djup.Native/src/Djup.Native.csproj @@ -9,7 +9,7 @@ </PropertyGroup> <PropertyGroup> - <BuildDir>$(MSBuildThisFileDirectory)../../lib/build</BuildDir> + <BuildDir>$(MSBuildThisFileDirectory)../../lib/output</BuildDir> </PropertyGroup> <ItemGroup Condition=" '$(Configuration)'=='Release' "> diff --git a/Djup.Native/src/LibDjup.cs b/Djup.Native/src/LibDjup.cs index 4cd99f8..864f330 100644 --- a/Djup.Native/src/LibDjup.cs +++ b/Djup.Native/src/LibDjup.cs @@ -5,50 +5,62 @@ namespace Djup.Native; public static partial class LibDjup { const string LibraryName = "djup"; - const string Prefix = "dp_"; - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(hello_world))] - public static partial void hello_world(); + [LibraryImport(LibraryName, EntryPoint = nameof(vec2_dot))] + public static partial Vec2 vec2_dot(Vec2 a, Vec2 b); - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(get_num))] - public static partial int get_num(); + [LibraryImport(LibraryName, EntryPoint = nameof(vec2_length))] + public static partial float vec2_length(Vec2 v); - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(get_vec2))] - public static partial Vec2 get_vec2(); + [LibraryImport(LibraryName, EntryPoint = nameof(vec2_normal))] + public static partial Vec2 vec2_normal(Vec2 v); - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(vec2_mul))] - public static partial Vec2 vec2_mul(Vec2 v, float scalar); + [LibraryImport(LibraryName, EntryPoint = nameof(sim_log_init))] + public static partial void sim_log_init(IntPtr simulation, [MarshalAs(UnmanagedType.FunctionPtr)] LoggerDelegate logger, [MarshalAs(UnmanagedType.FunctionPtr)] AssertDelegate assert); - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(vec2_normal))] - public static partial Vec2 vec2_normal(Vec2 v); + [LibraryImport(LibraryName, EntryPoint = nameof(sim_set_log_level))] + public static partial void sim_set_log_level(IntPtr simulation, LogLevel minLevel); - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(vec2_length))] - public static partial float vec2_length(Vec2 v); + [LibraryImport(LibraryName, EntryPoint = nameof(sim_create))] + public static partial IntPtr sim_create(int snapshots, int entities); + + [LibraryImport(LibraryName, EntryPoint = nameof(sim_free))] + public static partial void sim_free(IntPtr simulation); - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(log_set_output))] - public static partial void log_set_output([MarshalAs(UnmanagedType.FunctionPtr)] LoggerDelegate logger); + [LibraryImport(LibraryName, EntryPoint = nameof(sim_get_snapshot))] + public unsafe static partial Snapshot* sim_get_snapshot(IntPtr simulation); - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(log_set_level))] - public static partial void log_set_level(LogLevel minLevel); + [LibraryImport(LibraryName, EntryPoint = nameof(sim_return_snapshot))] + public unsafe static partial void sim_return_snapshot(IntPtr simulation, Snapshot* snapshot); - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(physics_context_create))] - public static partial IntPtr physics_context_create(int snapshots, int players, int balls); + [LibraryImport(LibraryName, EntryPoint = nameof(sim_tick))] + public unsafe static partial void sim_tick(Snapshot* current, Snapshot* next); - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(physics_context_free))] - public static partial void physics_context_free(IntPtr context); + [LibraryImport(LibraryName, EntryPoint = nameof(snapshot_create_entity))] + public unsafe static partial EntityId snapshot_create_entity(Snapshot* snapshot); - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(physics_context_get_snapshot))] - public static partial IntPtr physics_context_get_snapshot(IntPtr context); + public enum ComponentAddError + { + None, + InvalidArg, + InvalidId, + EntityNotFound + } - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(physics_context_return_snapshot))] - public static partial void physics_context_return_snapshot(IntPtr context, IntPtr snapshot); + [LibraryImport(LibraryName, EntryPoint = nameof(snapshot_add_component))] + public unsafe static partial ComponentAddError snapshot_add_component(Snapshot* snapshot, EntityId entity, Component component, void* init); - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(physics_tick))] - public static partial int physics_tick(IntPtr currentSnapshot, double delta, IntPtr nextSnapshot); + public enum ComponentRemoveError + { + None, + InvalidArg, + InvalidId, + EntityNotFound + } - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(snapshot_put_player))] - public static unsafe partial int snapshot_put_player(IntPtr snapshot, int playerId, Player* player); + [LibraryImport(LibraryName, EntryPoint = nameof(snapshot_remove_components))] + public unsafe static partial ComponentRemoveError snapshot_remove_components(Snapshot* snapshot, EntityId entity, Components components); - [LibraryImport(LibraryName, EntryPoint = Prefix + nameof(snapshot_set_player_input))] - public static partial int snapshot_set_player_input(IntPtr snapshot, int playerId, byte input); + [LibraryImport(LibraryName, EntryPoint = nameof(snapshot_reset_entity))] + public unsafe static partial ComponentRemoveError snapshot_reset_entity(Snapshot* snapshot, EntityId entity); } diff --git a/Djup.Native/src/Types.cs b/Djup.Native/src/Types.cs index 3afce83..e9eb824 100644 --- a/Djup.Native/src/Types.cs +++ b/Djup.Native/src/Types.cs @@ -4,10 +4,84 @@ using System.Runtime.InteropServices; namespace Djup.Native; [StructLayout(LayoutKind.Sequential)] +public struct EntityId +{ + public int Id { get; } + + public static readonly EntityId Invalid = new(-1); + + public EntityId(int id) + { + Id = id; + } + + public bool IsInvalid => Id < 0; + + public override string ToString() => $"#{Id}"; + + public override bool Equals(object? other) + { + if (other is EntityId id) + { + return this == id; + } + return false; + } + + public override int GetHashCode() => Id.GetHashCode(); + + public static bool operator ==(EntityId a, EntityId b) + { + if (a < 0) + return b < 0; + if (b < 0) + return false; + return a.Id == b.Id; + } + public static bool operator !=(EntityId a, EntityId b) => !(a == b); + public static implicit operator int(EntityId entityId) => entityId.Id; + public static implicit operator EntityId(int id) => new(id); +} + +public enum Component : int +{ + Exists, + Ball, + PlayerInput +} + +[Flags] +public enum Components : int +{ + Exists = 1 << Component.Exists, + Ball = 1 << Component.Ball, + PlayerInput = 1 << Component.PlayerInput +} + +[StructLayout(LayoutKind.Sequential)] +public unsafe struct OdinSlice<T> +{ + public void* Data { get; } + public nint Len { get; } + + public Span<T> AsSpan() => new Span<T>(Data, Len.ToInt32()); + public ReadOnlySpan<T> AsReadOnlySpan() => new ReadOnlySpan<T>(Data, Len.ToInt32()); +} + +[StructLayout(LayoutKind.Sequential)] +public unsafe struct OdinString +{ + public sbyte* Data { get; } + public nint Len { get; } + + public override string ToString() => new string(Data, 0, Len.ToInt32()); +} + +[StructLayout(LayoutKind.Sequential)] public struct Vec2 { - public float X { get; } - public float Y { get; } + public float X { get; set; } + public float Y { get; set; } public Vec2(float x, float y) { @@ -21,59 +95,32 @@ public struct Vec2 public override string ToString() => $"({X}, {Y})"; } -public enum EntityState : byte -{ - Inactive = 0, - Active, - Removed, - Dead -} - -public enum PlayerInput : byte -{ - Up = 1 << 0, - Down = 1 << 1, - Left = 1 << 2, - Right = 1 << 3 -} - [StructLayout(LayoutKind.Sequential)] -public struct Player +public struct Ball { - public EntityState State { get; } - private byte input; public Vec2 Position { get; set; } public Vec2 Velocity { get; set; } } [StructLayout(LayoutKind.Sequential)] -public struct Bullet +public struct PlayerInput { - public EntityState State { get; set; } - public Vec2 Position { get; set; } - public Vec2 Velocity { get; set; } + public Vec2 Direction { get; set; } } [StructLayout(LayoutKind.Sequential)] -public unsafe struct Snapshot +public struct Snapshot { - private byte active; + private readonly byte active; public uint Tick { get; } - private int playersLength; - private Player* players; - private int bulletsLength; - private Bullet* bullets; - - public ReadOnlySpan<Player> Players => - new ReadOnlySpan<Player>(players, playersLength); - - public ReadOnlySpan<Bullet> Bullets => - new ReadOnlySpan<Bullet>(bullets, bulletsLength); + public OdinSlice<Components> Metadata { get; } + public OdinSlice<Ball> Balls { get; } + public OdinSlice<PlayerInput> PlayerInputs { get; } + private IntPtr ctx; } public enum LogLevel { - Trace, Debug, Info, Warn, @@ -81,4 +128,5 @@ public enum LogLevel Fatal } -public delegate void LoggerDelegate(LogLevel level, string source, int line, string message); +public delegate void LoggerDelegate(LogLevel level, OdinString message, OdinString procedure, OdinString file, int line); +public delegate void AssertDelegate(OdinString prefix, OdinString message, OdinString procedure, OdinString file, int line); |
