checkpoint
This commit is contained in:
parent
d144069dbe
commit
16fb3848a1
4 changed files with 259 additions and 62 deletions
228
src/main.zig
228
src/main.zig
|
|
@ -12,59 +12,203 @@ pub const DbVector2 = struct {
|
|||
y: f32,
|
||||
};
|
||||
|
||||
pub const person: spacetime.Table = .{ .schema = Person, };
|
||||
pub const Person = struct{
|
||||
pub const config: spacetime.Table = .{ .schema = Config, .primary_key = "id", .access = .Public, };
|
||||
pub const Config = struct {
|
||||
//#[primary_key]
|
||||
id: u32,
|
||||
world_size: u64,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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,
|
||||
pos: DbVector2,
|
||||
schedule: spacetime.ScheduleAt,
|
||||
|
||||
pub fn destroy(self: *@This(), allocator: std.mem.Allocator) void {
|
||||
allocator.free(self.name);
|
||||
allocator.destroy(self);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Init: spacetime.Reducer = .{
|
||||
.func_type = @TypeOf(InitReducer),
|
||||
.func = @ptrCast(&InitReducer),
|
||||
.lifecycle = .Init,
|
||||
pub const food: spacetime.Table = .{ .schema = Food, .primary_key = "entity_id", .access = .Public };
|
||||
pub const Food = struct {
|
||||
//#[primary_key]
|
||||
entity_id: u32,
|
||||
};
|
||||
|
||||
pub fn InitReducer(_: *spacetime.ReducerContext) void {
|
||||
// Called when the module is initially published
|
||||
spacetime.print("[Init]");
|
||||
//#[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,
|
||||
};
|
||||
|
||||
//#[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,
|
||||
};
|
||||
|
||||
//#[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,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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 {
|
||||
.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(_: *spacetime.ReducerContext) void {
|
||||
pub fn OnConnectReducer(ctx: *spacetime.ReducerContext) !void {
|
||||
// Called everytime a new client connects
|
||||
spacetime.print("[OnConnect]");
|
||||
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(_: *spacetime.ReducerContext) void {
|
||||
pub fn OnDisconnectReducer(ctx: *spacetime.ReducerContext) !void {
|
||||
// Called everytime a client disconnects
|
||||
spacetime.print("[OnDisconnect]");
|
||||
}
|
||||
|
||||
pub const add = spacetime.Reducer{ .func_type = @TypeOf(addReducer), .func = @ptrCast(&addReducer), .params = &.{ "name", "time" }};
|
||||
pub fn addReducer(ctx: *spacetime.ReducerContext, name: []const u8, time: i64) void {
|
||||
const personTable = ctx.*.db.get("person");
|
||||
personTable.insert(Person{
|
||||
.name = name,
|
||||
.pos = DbVector2{ .x = 10.4, .y = 20.6 },
|
||||
.schedule = .{ .Interval = .{ .__time_duration_micros__ = time, }, },
|
||||
});
|
||||
|
||||
var buf: [128]u8 = undefined;
|
||||
spacetime.print(std.fmt.bufPrint(&buf, "[add] {{{s}}}!", .{ name }) catch "[add] Error: name to long");
|
||||
}
|
||||
|
||||
pub const say_hello = spacetime.Reducer{ .func_type = @TypeOf(say_helloReducer), .func = @ptrCast(&say_helloReducer), };
|
||||
pub fn say_helloReducer(ctx: *spacetime.ReducerContext) void {
|
||||
//_ = ctx;
|
||||
var personIter = ctx.*.db.get("person").iter();
|
||||
while(personIter.next() catch {
|
||||
@panic("person Iter errored!");
|
||||
}) |item| {
|
||||
var buffer: [512]u8 = undefined;
|
||||
const msg = std.fmt.bufPrint(&buffer, "Hello, {s} (pos: {{{d}, {d}}}) (time: {})!", .{ item.name, item.pos.x, item.pos.y, item.schedule.Interval.__time_duration_micros__ }) catch "<Unknown>";
|
||||
spacetime.print(msg);
|
||||
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;
|
||||
}
|
||||
spacetime.print("Hello, World!");
|
||||
}
|
||||
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" }
|
||||
};
|
||||
pub fn move_all_players_reducer(ctx: *spacetime.ReducerContext, _timer: MoveAllPlayersTimer) !void {
|
||||
_ = ctx;
|
||||
_ = _timer;
|
||||
//std.log.info("Move Players!", .{});
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -265,10 +265,14 @@ pub fn zigTypeToSpacetimeType(comptime param: ?type) AlgebraicType {
|
|||
[]const u8 => .{ .String = {} },
|
||||
i32 => .{ .I32 = {}, },
|
||||
i64 => .{ .I64 = {}, },
|
||||
i128 => .{ .I128 = {}, },
|
||||
i256 => .{ .I258 = {}, },
|
||||
u32 => .{ .U32 = {}, },
|
||||
u64 => .{ .U64 = {}, },
|
||||
f32 => .{ .F32 = {}, },
|
||||
u128 => .{ .U128 = {}, },
|
||||
u256 => .{ .U256 = {}, },
|
||||
f32 => .{ .F32 = {}, },
|
||||
f64 => .{ .F64 = {}, },
|
||||
else => blk: {
|
||||
if(@typeInfo(param.?) == .@"struct") {
|
||||
var elements: []const ProductTypeElement = &.{};
|
||||
|
|
@ -446,6 +450,28 @@ pub fn compile(comptime moduleTables : []const Table, comptime moduleReducers :
|
|||
}
|
||||
};
|
||||
}
|
||||
if(table.indexes) |_indexes| {
|
||||
inline for(_indexes) |index| {
|
||||
|
||||
const fieldIndex = std.meta.fieldIndex(table.schema, index.name).?;
|
||||
|
||||
const indexAlgo: RawIndexAlgorithm = blk: {
|
||||
switch(index.layout) {
|
||||
.BTree => break :blk .{ .BTree = &.{ fieldIndex } },
|
||||
.Hash => break :blk .{ .Hash = &.{ fieldIndex } },
|
||||
.Direct => break :blk .{ .Direct = fieldIndex },
|
||||
}
|
||||
};
|
||||
|
||||
indexes = indexes ++ &[_]RawIndexDefV9{
|
||||
RawIndexDefV9{
|
||||
.name = null,
|
||||
.accessor_name = index.name,
|
||||
.algorithm = indexAlgo
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var constraints: []const RawConstraintDefV9 = &[_]RawConstraintDefV9{};
|
||||
if(table.primary_key) |_| {
|
||||
|
|
@ -657,6 +683,11 @@ pub const Reducer = struct {
|
|||
func: *const fn()void,
|
||||
};
|
||||
|
||||
pub const Index = struct {
|
||||
name: []const u8,
|
||||
layout: std.meta.Tag(RawIndexAlgorithm),
|
||||
};
|
||||
|
||||
pub const Table = struct {
|
||||
name: ?[]const u8 = null,
|
||||
schema: type,
|
||||
|
|
@ -664,7 +695,7 @@ pub const Table = struct {
|
|||
access: TableAccess = .Private,
|
||||
primary_key: ?[]const u8 = null,
|
||||
schedule_reducer: ?*const Reducer = null,
|
||||
indexes: ?[]const []const u8 = null,
|
||||
indexes: ?[]const Index = null,
|
||||
unique: ?[]const []const u8 = null,
|
||||
autoinc: ?[]const []const u8 = null,
|
||||
};
|
||||
|
|
@ -771,7 +802,7 @@ pub export fn __call_reducer__(
|
|||
comptime var argCount = 1;
|
||||
comptime var argList: []const std.builtin.Type.StructField = &[_]std.builtin.Type.StructField{
|
||||
std.builtin.Type.StructField{
|
||||
.alignment = 0,
|
||||
.alignment = @alignOf(*ReducerContext),
|
||||
.default_value = null,
|
||||
.is_comptime = false,
|
||||
.name = "0",
|
||||
|
|
@ -783,7 +814,7 @@ pub export fn __call_reducer__(
|
|||
_ = name;
|
||||
argList = argList ++ &[_]std.builtin.Type.StructField{
|
||||
std.builtin.Type.StructField{
|
||||
.alignment = 0,
|
||||
.alignment = @alignOf(param.type.?),
|
||||
.default_value = null,
|
||||
.is_comptime = false,
|
||||
.name = comptime utils.itoa(argCount),
|
||||
|
|
|
|||
33
src/spacetime/FFI.zig
Normal file
33
src/spacetime/FFI.zig
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
const spacetime = @import("../spacetime.zig");
|
||||
|
||||
const BytesSink = spacetime.BytesSink;
|
||||
const BytesSource = spacetime.BytesSource;
|
||||
const TableId = spacetime.TableId;
|
||||
const RowIter = spacetime.RowIter;
|
||||
const IndexId = spacetime.IndexId;
|
||||
const ColId = spacetime.ColId;
|
||||
|
||||
extern "spacetime_10.0" fn bytes_sink_write(sink: BytesSink, buffer_ptr: [*c]const u8, buffer_len_ptr: *usize) u16;
|
||||
extern "spacetime_10.0" fn bytes_source_read(source: BytesSource, buffer_ptr: [*c]u8, buffer_len_ptr: *usize) i16;
|
||||
extern "spacetime_10.0" fn table_id_from_name(name: [*c]const u8, name_len: usize, out: *TableId) u16;
|
||||
extern "spacetime_10.0" fn datastore_insert_bsatn(table_id: TableId, row_ptr: [*c]const u8, row_len_ptr: *usize) u16;
|
||||
extern "spacetime_10.0" fn row_iter_bsatn_advance(iter: RowIter, buffer_ptr: [*c]u8, buffer_len_ptr: *usize) i16;
|
||||
extern "spacetime_10.0" fn datastore_table_scan_bsatn(table_id: TableId, out: [*c]RowIter) u16;
|
||||
extern "spacetime_10.0" fn index_id_from_name(name_ptr: [*c]const u8, name_len: usize, out: *IndexId) u16;
|
||||
extern "spacetime_10.0" fn datastore_index_scan_range_bsatn( index_id: IndexId, prefix_ptr: [*c]const u8, prefix_len: usize, prefix_elems: ColId, rstart_ptr: [*c]const u8, rstart_len: usize, rend_ptr: [*c]const u8, rend_len: usize, out: *RowIter) u16;
|
||||
|
||||
pub fn tableIdFromName(name: []const u8, out: *TableId) u16 {
|
||||
return spacetime.retMap(table_id_from_name(name.ptr, name.len, out));
|
||||
}
|
||||
|
||||
pub fn datastoreTableScanBsatn(table_id: TableId, out: [*c]RowIter) u16 {
|
||||
return spacetime.retMap(datastore_table_scan_bsatn(table_id, out));
|
||||
}
|
||||
|
||||
pub fn indexIdFromName(name: []const u8, out: *IndexId) u16 {
|
||||
return spacetime.retMap(index_id_from_name(name.ptr, name.len, out));
|
||||
}
|
||||
|
||||
pub fn datastoreIndexScanRangeBsatn( index_id: IndexId, prefix: []const u8, prefix_elems: ColId, rstart: []const u8, rend: []const u8, out: *RowIter) u16 {
|
||||
return spacetime.retMap(datastore_index_scan_range_bsatn( index_id, prefix.ptr, prefix.len, prefix_elems, rstart.ptr, rstart.len, rend.ptr, rend.len, out));
|
||||
}
|
||||
|
|
@ -346,39 +346,28 @@ pub fn Iter(struct_type: type) type {
|
|||
last_ret: SpacetimeValue = .OK,
|
||||
|
||||
pub fn next(self: *@This()) spacetime.ReducerError!?*struct_type {
|
||||
std.log.debug("line: {} (handle: {})", .{358, self.handle});
|
||||
var buffer_len: usize = undefined;
|
||||
//while(true)
|
||||
//{
|
||||
var ret: spacetime.SpacetimeValue = self.last_ret;
|
||||
if(self.contents == null or self.contents.?.len == 0) {
|
||||
std.log.debug("line: {} (contents: {any})", .{364, self.contents});
|
||||
if(self.handle._inner == spacetime.RowIter.INVALID._inner) {
|
||||
std.log.debug("line: {}", .{366});
|
||||
|
||||
self.contents = null;
|
||||
return null;
|
||||
}
|
||||
std.log.debug("line: {}", .{371});
|
||||
|
||||
buffer_len = self.buffer.len;
|
||||
std.log.debug("line: {}", .{374});
|
||||
ret = try spacetime.retMap(spacetime.row_iter_bsatn_advance(self.handle, @constCast(@ptrCast(&self.buffer)), &buffer_len));
|
||||
std.log.debug("ret: {}", .{ret});
|
||||
std.log.debug("self.buffer[0..buffer_len]: {any} {any} {any}", .{(&self.buffer).ptr, self.buffer.len, buffer_len});
|
||||
self.contents = self.buffer[0..buffer_len];
|
||||
std.log.debug("line: {}", .{379});
|
||||
|
||||
if(ret == .EXHAUSTED) {
|
||||
std.log.debug("line: {}", .{382});
|
||||
self.handle = spacetime.RowIter.INVALID;
|
||||
}
|
||||
std.log.debug("line: {}", .{385});
|
||||
self.last_ret = ret;
|
||||
}
|
||||
if(self.contents == null or self.contents.?.len == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
std.log.debug("{}", .{struct_type});
|
||||
return StructDeserializer(struct_type)(self.allocator, &(self.contents.?));
|
||||
//}
|
||||
}
|
||||
|
||||
pub fn one_or_null(self: *@This()) ?*struct_type {
|
||||
|
|
@ -428,7 +417,7 @@ pub fn Column2ORM(comptime table_name: []const u8, comptime column_name: [:0]con
|
|||
allocator: std.mem.Allocator,
|
||||
|
||||
pub fn filter(self: @This(), val: wrapped_type) !Iter(struct_type) {
|
||||
const temp_name: []const u8 = table_name ++ "_" ++ column_name ++ "_idx_btree";
|
||||
const temp_name: []const u8 = comptime table_name ++ "_" ++ column_name ++ "_idx_btree";
|
||||
var id = spacetime.IndexId{ ._inner = std.math.maxInt(u32)};
|
||||
const err = try spacetime.retMap(spacetime.index_id_from_name(temp_name.ptr, temp_name.len, &id));
|
||||
std.log.debug("index_id_from_name({}): {x}", .{err, id._inner});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue