From 551527e81ce4fe986c4e833141cb12ab868a499f Mon Sep 17 00:00:00 2001 From: ookami125 Date: Mon, 7 Apr 2025 13:21:41 -0400 Subject: [PATCH] broken, some test improvements to the syntax --- src/main.zig | 269 ++++++++++++++++------------------------------ src/spacetime.zig | 26 ++--- 2 files changed, 108 insertions(+), 187 deletions(-) diff --git a/src/main.zig b/src/main.zig index 3a1d86b..5d0187d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,5 +1,6 @@ const std = @import("std"); const spacetime = @import("spacetime.zig"); +const utils = @import("spacetime/utils.zig"); comptime { _ = spacetime; } pub const std_options = std.Options{ @@ -7,208 +8,128 @@ pub const std_options = std.Options{ .logFn = spacetime.logFn, }; -pub const DbVector2 = struct { - x: f32, - y: f32, +const TableAttribs = struct { + scheduled: ?[]const u8, + autoinc: ?[]const []const u8, + primary_key: ?[]const u8, + unique: ?[]const []const u8, }; -pub const config: spacetime.Table = .{ .schema = Config, .primary_key = "id", .access = .Public, }; -pub const Config = struct { - //#[primary_key] - id: u32, - world_size: u64, +const TableAttribsPair = struct { + schema: type, + attribs: TableAttribs, }; -pub const entity: spacetime.Table = .{ .schema = Entity, .primary_key = "entity_id", .access = .Public }; -pub const Entity = struct { - //#[auto_inc] - //#[primary_key] - entity_id: u32, - position: DbVector2, - mass: u32, -}; +comptime { + var attributeList: []const TableAttribsPair = &.{}; +} -pub const circles: spacetime.Table = .{ - .schema = Circle, - .primary_key = "entity_id", - .access = .Public, - .indexes = &.{ .{ .name = "player_id", .layout = .BTree } }, -}; -pub const Circle = struct { - //#[auto_inc] - //#[primary_key] - entity_id: u32, - //#[index(btree)] - player_id: u32, - direction: DbVector2, - speed: f32, - last_split_time: spacetime.Timestamp, -}; +fn removeComptimeFields(data: type) type { + const typeInfo = @typeInfo(data).@"struct"; + var newFields: []const std.builtin.Type.StructField = &.{}; -pub const players: spacetime.Table = .{ - .schema = Player, - .primary_key = "identity", - .access = .Public, - .unique = &.{ "player_id" }, - .autoinc = &.{ "player_id" }, -}; -pub const logged_out_players: spacetime.Table = .{ - .schema = Player, - .primary_key = "identity", - .unique = &.{ "player_id" } -}; -pub const Player = struct { - //#[primary_key] - identity: spacetime.Identity, - //#[unique] - //#[auto_inc] - player_id: u32, - name: []const u8, - - pub fn destroy(self: *@This(), allocator: std.mem.Allocator) void { - allocator.free(self.name); - allocator.destroy(self); + inline for(std.meta.fields(data)) |field| { + if(!field.is_comptime) { + newFields = newFields ++ &[_]std.builtin.Type.StructField{ field }; + } } -}; -pub const food: spacetime.Table = .{ .schema = Food, .primary_key = "entity_id", .access = .Public }; -pub const Food = struct { - //#[primary_key] - entity_id: u32, -}; + return @Type(.{ + .@"struct" = std.builtin.Type.Struct{ + .backing_integer = typeInfo.backing_integer, + .decls = typeInfo.decls, + .fields = newFields, + .is_tuple = typeInfo.is_tuple, + .layout = typeInfo.layout, + } + }); +} -//#[spacetimedb::table(name = spawn_food_timer, scheduled(spawn_food))] -pub const spawn_food_timer: spacetime.Table = .{ .schema = SpawnFoodTimer, .primary_key = "scheduled_id" }; -pub const SpawnFoodTimer = struct { - //#[primary_key] - //#[auto_inc] - scheduled_id: u64, - scheduled_at: spacetime.ScheduleAt, -}; +fn Table(data: type) spacetime.Table { + const fieldIdx = std.meta.fieldIndex(data, "__spacetime_10.0__attribs__"); + if(fieldIdx == null) return .{ .schema = data, .schema_name = @typeName(data), }; -//#[spacetimedb::table(name = circle_decay_timer, scheduled(circle_decay))] -pub const circle_decay_timer: spacetime.Table = .{ .schema = CircleDecayTimer, .primary_key = "scheduled_id" }; -pub const CircleDecayTimer = struct { - //#[primary_key] - //#[auto_inc] - scheduled_id: u64, - scheduled_at: spacetime.ScheduleAt, -}; + const attribs: TableAttribs = utils.getMemberDefaultValue(data, "__spacetime_10.0__attribs__"); + return .{ + .schema = removeComptimeFields(data), + .schema_name = @typeName(data), + .primary_key = attribs.primary_key, + //.schedule_reducer = attribs.scheduled, + .unique = attribs.unique, + .autoinc = attribs.autoinc, + }; +} -//#[spacetimedb::table(name = circle_recombine_timer, scheduled(circle_recombine))] -pub const circle_recombine_timer: spacetime.Table = .{ .schema = CircleRecombineTimer, .primary_key = "scheduled_id" }; -pub const CircleRecombineTimer = struct { - //#[primary_key] - //#[auto_inc] - scheduled_id: u64, - scheduled_at: spacetime.ScheduleAt, - player_id: u32, -}; +fn TableSchema(data: TableAttribsPair) type { + const attribs: TableAttribs = data.attribs; -pub const consume_entity_timer: spacetime.Table = .{ .schema = ConsumeEntityTimer, .primary_key = "scheduled_id" }; -pub const ConsumeEntityTimer = struct { - //#[primary_key] - //#[auto_inc] - scheduled_id: u64, - scheduled_at: spacetime.ScheduleAt, - consumed_entity_id: u32, - consumer_entity_id: u32, -}; + attributeList = attributeList ++ &[1]TableAttribsPair{ data }; + + var newFields: []const std.builtin.Type.StructField = &.{}; + + newFields = newFields ++ &[_]std.builtin.Type.StructField{ + std.builtin.Type.StructField{ + .alignment = @alignOf(TableAttribs), + .default_value = @ptrCast(&attribs), + .is_comptime = false, + .name = "__spacetime_10.0__attribs__", + .type = TableAttribs, + } + }; + + newFields = newFields ++ std.meta.fields(data.schema); + const newStruct: std.builtin.Type.Struct = .{ + .backing_integer = null, + .decls = &[_]std.builtin.Type.Declaration{}, + .fields = newFields, + .is_tuple = false, + .layout = .auto + }; + return @Type(.{ + .@"struct" = newStruct, + }); +} + +//#[spacetimedb::table(name = move_all_players_timer, scheduled(move_all_players))] +pub const move_all_players_timer = Table(MoveAllPlayersTimer); +pub const MoveAllPlayersTimer = TableSchema(.{ + .schema = struct { + scheduled_id: u64, + scheduled_at: spacetime.ScheduleAt, + }, + .attribs = TableAttribs{ + .scheduled = "move_all_players_reducer", + .autoinc = &.{"scheduled_id"}, + .primary_key = "scheduled_id", + .unique = &.{}, + } +}); pub const Init: spacetime.Reducer = .{ .func_type = @TypeOf(InitReducer), .func = @ptrCast(&InitReducer), .lifecycle = .Init, }; pub fn InitReducer(ctx: *spacetime.ReducerContext) !void { std.log.info("Initializing...", .{}); - try ctx.db.get("config").insert(Config { - .id = 0, - .world_size = 1000, - }); - try ctx.db.get("circle_decay_timer").insert(CircleDecayTimer { - .scheduled_id = 0, - .scheduled_at = .{ .Interval = .{ .__time_duration_micros__ = 5 * std.time.us_per_s }}, - }); - try ctx.db.get("spawn_food_timer").insert(SpawnFoodTimer { - .scheduled_id = 0, - .scheduled_at = .{ .Interval = .{ .__time_duration_micros__ = 500 * std.time.us_per_ms }} - }); - try ctx.db.get("move_all_players_timer").insert(MoveAllPlayersTimer { + try ctx.db.get("move_all_players_timer").insert(MoveAllPlayersTimer{ .scheduled_id = 0, .scheduled_at = .{ .Interval = .{ .__time_duration_micros__ = 50 * std.time.us_per_ms }} }); } -pub const OnConnect = spacetime.Reducer{ .func_type = @TypeOf(OnConnectReducer), .func = @ptrCast(&OnConnectReducer), .lifecycle = .OnConnect, }; -pub fn OnConnectReducer(ctx: *spacetime.ReducerContext) !void { - // Called everytime a new client connects - std.log.info("[OnConnect]", .{}); - const nPlayer = try ctx.db.get("logged_out_players").col("identity").find(.{ .identity = ctx.sender }); - if (nPlayer) |player| { - try ctx.db.get("players").insert(player.*); - try ctx.db.get("logged_out_players").col("identity").delete(.{ .identity = player.identity }); - } else { - try ctx.db.get("players").insert(Player { - .identity = ctx.sender, - .player_id = 0, - .name = "", - }); - } -} - -pub const OnDisconnect = spacetime.Reducer{ .func_type = @TypeOf(OnDisconnectReducer), .func = @ptrCast(&OnDisconnectReducer), .lifecycle = .OnDisconnect, }; -pub fn OnDisconnectReducer(ctx: *spacetime.ReducerContext) !void { - // Called everytime a client disconnects - std.log.info("[OnDisconnect]", .{}); - const nPlayer = try ctx.db.get("players").col("identity").find(.{ .identity = ctx.sender}); - if(nPlayer == null) { - std.log.err("Disconnecting player doesn't have a valid players row!",.{}); - return; - } - const player = nPlayer.?; - //std.log.info("{?}", .{player}); - const player_id = player.player_id; - try ctx.db.get("logged_out_players").insert(player.*); - try ctx.db.get("players").col("identity").delete(.{ .identity = ctx.sender}); - - // Remove any circles from the arena - var iter = ctx.db.get("circles").col("player_id").filter(.{ .player_id = player_id }); - //_ = player_id; - _ = &iter; - // std.log.info("blag", .{}); - // while (try iter.next()) |circle_val| { - // try ctx.db.get("entity").col("entity_id").delete(.{ .entity_id = circle_val.entity_id, }); - // try ctx.db.get("circle").col("entity_id").delete(.{ .entity_id = circle_val.entity_id, }); - // } -} - -//#[spacetimedb::table(name = move_all_players_timer, scheduled(move_all_players))] -pub const move_all_players_timer: spacetime.Table = .{ - .schema = MoveAllPlayersTimer, - .primary_key = "scheduled_id", - .schedule_reducer = &move_all_players -}; -pub const MoveAllPlayersTimer = struct { - //#[primary_key] - //#[auto_inc] - scheduled_id: u64, - scheduled_at: spacetime.ScheduleAt, -}; - pub const move_all_players = spacetime.Reducer{ .func_type = @TypeOf(move_all_players_reducer), .func = @ptrCast(&move_all_players_reducer), - .params = &.{ "_timer" } + .params = &.{ "timer" } }; -pub fn move_all_players_reducer(ctx: *spacetime.ReducerContext, _timer: MoveAllPlayersTimer) !void { +pub fn move_all_players_reducer(ctx: *spacetime.ReducerContext, timer: MoveAllPlayersTimer) !void { _ = ctx; - _ = _timer; - //std.log.info("Move Players!", .{}); + std.log.info("(id: {}) Move Players!", .{timer.scheduled_id}); return; } -pub const say_hello = spacetime.Reducer{ .func_type = @TypeOf(say_hello_reducer), .func = @ptrCast(&say_hello_reducer)}; +// pub const say_hello = spacetime.Reducer{ .func_type = @TypeOf(say_hello_reducer), .func = @ptrCast(&say_hello_reducer)}; -pub fn say_hello_reducer(ctx: *spacetime.ReducerContext) !void { - _ = ctx; - std.log.info("Hello!", .{}); - return; -} +// pub fn say_hello_reducer(ctx: *spacetime.ReducerContext) !void { +// _ = ctx; +// std.log.info("Hello!", .{}); +// return; +// } diff --git a/src/spacetime.zig b/src/spacetime.zig index 37340ae..902e120 100644 --- a/src/spacetime.zig +++ b/src/spacetime.zig @@ -244,7 +244,6 @@ pub fn readArg(allocator: std.mem.Allocator, args: BytesSource, comptime t: type inline else => |tag_field| { const field = std.meta.fields(t)[@intFromEnum(tag_field)]; @field(temp, field.name) = (try readArg(allocator, args, field.type)); - } } //@field(temp, field.name) = try readArg(allocator, args, @TypeOf(field)); @@ -320,8 +319,8 @@ const StructImpl = struct { fields: []const StructFieldImpl, }; -pub fn addStructImpl(structImpls: *[]const StructImpl, layout: anytype) u32 { - const name = blk: { +pub fn addStructImpl(structImpls: *[]const StructImpl, layout: anytype, name_override: ?[]const u8) u32 { + const name = name_override orelse blk: { var temp: []const u8 = @typeName(layout); if(std.mem.lastIndexOf(u8, temp, ".")) |idx| temp = temp[idx+1..]; @@ -344,7 +343,7 @@ pub fn addStructImpl(structImpls: *[]const StructImpl, layout: anytype) u32 { .name = field.name, .type = .{ .Ref = .{ - .inner = addStructImpl(structImpls, field.type), + .inner = addStructImpl(structImpls, field.type, null), } } } @@ -429,7 +428,7 @@ pub fn compile(comptime moduleTables : []const Table, comptime moduleReducers : const table_type: TableType = table.type; const table_access: TableAccess = table.access; const product_type_ref: AlgebraicTypeRef = AlgebraicTypeRef{ - .inner = addStructImpl(&structDecls, table.schema), + .inner = addStructImpl(&structDecls, table.schema, table.schema_name), }; const primary_key: []const u16 = blk: { if(table.primary_key) |key| { @@ -601,8 +600,7 @@ pub fn callReducer(comptime mdef: []const Reducer, id: usize, args: anytype) Red } pub fn PrintModule(data: anytype) void { - var buf: [64]u8 = undefined; - std.log.debug(std.fmt.bufPrint(&buf, "\"{s}\": {{", .{@typeName(@TypeOf(data))}) catch ""); + std.log.debug("\"{s}\": {{", .{@typeName(@TypeOf(data))}); switch(@TypeOf(data)) { RawModuleDefV9 => { PrintModule(data.typespace); @@ -658,16 +656,16 @@ pub fn PrintModule(data: anytype) void { } }, []const u8 => { - std.log.debug(std.fmt.bufPrint(&buf, "\"{s}\"", .{data}) catch ""); + std.log.debug("\"{s}\"", .{data}); }, u32 => { - std.log.debug(std.fmt.bufPrint(&buf, "{}", .{data}) catch ""); + std.log.debug("{}", .{data}); }, else => { - std.log.debug("\"...\""); + std.log.debug("\"...\"", .{}); }, } - std.log.debug("},"); + std.log.debug("}},", .{}); } pub const Param = struct { @@ -691,6 +689,7 @@ pub const Index = struct { pub const Table = struct { name: ?[]const u8 = null, schema: type, + schema_name: []const u8, type: TableType = .User, access: TableAccess = .Private, primary_key: ?[]const u8 = null, @@ -706,7 +705,7 @@ pub const reducers: []const Reducer = blk: { for(@typeInfo(root).@"struct".decls) |decl| { const field = @field(root, decl.name); if(@TypeOf(@field(root, decl.name)) == Reducer) { - temp = temp ++ &[_]Reducer{ + temp = temp ++ &[_]Reducer{ Reducer{ .name = field.name orelse decl.name, .lifecycle = field.lifecycle, @@ -731,6 +730,7 @@ pub const tables: []const Table = blk: { .type = field.type, .access = field.access, .schema = field.schema, + .schema_name = field.schema_name, .name = field.name orelse decl.name, .primary_key = field.primary_key, .schedule_reducer = field.schedule_reducer, @@ -759,7 +759,7 @@ pub export fn __describe_module__(description: BytesSink) void { @compileError(fmterr); }; - //PrintModule(compiledModule); + PrintModule(compiledModule); serialize_module(&moduleDefBytes, compiledModule) catch { std.log.err("Allocator Error: Cannot continue!", .{});