parent
9456d51538
commit
4aa7fc1ff4
6 changed files with 128 additions and 72 deletions
45
src/main.zig
45
src/main.zig
|
|
@ -188,6 +188,9 @@ pub const spacespec = spacetime.Spec{
|
|||
.params = &.{ "_timer", },
|
||||
})
|
||||
},
|
||||
.row_level_security = &.{
|
||||
"SELECT * FROM logged_out_player WHERE identity = :sender"
|
||||
}
|
||||
};
|
||||
|
||||
pub const DbVector2 = struct {
|
||||
|
|
@ -356,6 +359,7 @@ pub fn disconnect(ctx: *spacetime.ReducerContext) !void {
|
|||
|
||||
// Remove any circles from the arena
|
||||
var iter = try ctx.db.get("circle").col("player_id").filter(.{ .player_id = player.player_id });
|
||||
defer iter.close();
|
||||
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, });
|
||||
|
|
@ -435,6 +439,7 @@ pub fn suicide(ctx: *spacetime.ReducerContext) !void {
|
|||
.find(.{ .identity = ctx.sender})).?;
|
||||
|
||||
var circles = try ctx.db.get("circle").col("player_id").filter(.{ .player_id = player.player_id});
|
||||
defer circles.close();
|
||||
|
||||
while(try circles.next()) |circle| {
|
||||
try destroy_entity(ctx, circle.entity_id);
|
||||
|
|
@ -450,6 +455,7 @@ pub fn update_player_input(ctx: *spacetime.ReducerContext, direction: DbVector2)
|
|||
.col("identity")
|
||||
.find(.{ .identity = ctx.sender})).?;
|
||||
var circles = try ctx.db.get("circle").col("player_id").filter(.{ .player_id = player.player_id});
|
||||
defer circles.close();
|
||||
while(try circles.next()) |circle| {
|
||||
var copy_circle = circle;
|
||||
copy_circle.direction = direction.normalized();
|
||||
|
|
@ -491,22 +497,26 @@ pub fn move_all_players(ctx: *spacetime.ReducerContext, _timer: MoveAllPlayersTi
|
|||
.db.get("config").col("id")
|
||||
.find(.{ .id = 0 })).?.world_size;
|
||||
|
||||
var circle_directions = std.AutoHashMap(u32, DbVector2).init(ctx.db.allocator);
|
||||
var circleIter = ctx.db.get("circle").iter();
|
||||
var circle_directions = std.AutoHashMap(u32, DbVector2).init(ctx.allocator);
|
||||
var circleIter = try ctx.db.get("circle").iter();
|
||||
defer circleIter.close();
|
||||
while(try circleIter.next()) |circle| {
|
||||
try circle_directions.put(circle.entity_id, circle.direction.scale(circle.speed));
|
||||
}
|
||||
|
||||
var playerIter = ctx.db.get("player").iter();
|
||||
var playerIter = try ctx.db.get("player").iter();
|
||||
defer playerIter.close();
|
||||
|
||||
while(try playerIter.next()) |player| {
|
||||
var circles = std.ArrayList(Circle).init(ctx.db.allocator);
|
||||
var circles = std.ArrayList(Circle).init(ctx.allocator);
|
||||
var circlesIter1 = try ctx.db.get("circle").col("player_id")
|
||||
.filter(.{ .player_id = player.player_id});
|
||||
defer circlesIter1.close();
|
||||
while(try circlesIter1.next()) |circle| {
|
||||
try circles.append(circle);
|
||||
}
|
||||
|
||||
var player_entities = std.ArrayList(Entity).init(ctx.db.allocator);
|
||||
var player_entities = std.ArrayList(Entity).init(ctx.allocator);
|
||||
for(circles.items) |c| {
|
||||
try player_entities.append((try ctx.db.get("entity").col("entity_id").find(.{ .entity_id = c.entity_id})).?);
|
||||
}
|
||||
|
|
@ -575,7 +585,8 @@ pub fn move_all_players(ctx: *spacetime.ReducerContext, _timer: MoveAllPlayersTi
|
|||
}
|
||||
}
|
||||
|
||||
var circleIter2 = ctx.db.get("circle").iter();
|
||||
var circleIter2 = try ctx.db.get("circle").iter();
|
||||
defer circleIter2.close();
|
||||
while(try circleIter2.next()) |circle| {
|
||||
const circle_entity_n = (ctx.db.get("entity").col("entity_id").find(.{ .entity_id = circle.entity_id }) catch {
|
||||
continue;
|
||||
|
|
@ -586,22 +597,24 @@ pub fn move_all_players(ctx: *spacetime.ReducerContext, _timer: MoveAllPlayersTi
|
|||
const new_pos = circle_entity.position.add(direction.scale(mass_to_max_move_speed(circle_entity.mass)));
|
||||
const min = circle_radius;
|
||||
const max = @as(f32, @floatFromInt(world_size)) - circle_radius;
|
||||
if(max < min) continue;
|
||||
circle_entity.position.x = std.math.clamp(new_pos.x, min, max);
|
||||
circle_entity.position.y = std.math.clamp(new_pos.y, min, max);
|
||||
try ctx.db.get("entity").col("entity_id").update(circle_entity);
|
||||
}
|
||||
|
||||
// Check collisions
|
||||
var entities = std.AutoHashMap(u32, Entity).init(ctx.db.allocator);
|
||||
var entitiesIter = ctx.db.get("entity").iter();
|
||||
var entities = std.AutoHashMap(u32, Entity).init(ctx.allocator);
|
||||
var entitiesIter = try ctx.db.get("entity").iter();
|
||||
defer entitiesIter.close();
|
||||
while(try entitiesIter.next()) |e| {
|
||||
try entities.put(e.entity_id, e);
|
||||
}
|
||||
var circleIter3 = ctx.db.get("circle").iter();
|
||||
var circleIter3 = try ctx.db.get("circle").iter();
|
||||
defer circleIter3.close();
|
||||
while(try circleIter3.next()) |circle| {
|
||||
// let span = spacetimedb::time_span::Span::start("collisions");
|
||||
var circle_entity = entities.get(circle.entity_id).?;
|
||||
_ = &circle_entity;
|
||||
var entityIter = entities.iterator();
|
||||
while (entityIter.next()) |other_entity| {
|
||||
if(other_entity.value_ptr.entity_id == circle_entity.entity_id) {
|
||||
|
|
@ -670,12 +683,13 @@ pub fn player_split(ctx: *spacetime.ReducerContext) !void {
|
|||
const player = (try ctx
|
||||
.db.get("player").col("identity")
|
||||
.find(.{ .identity = ctx.sender})).?;
|
||||
var circles = std.ArrayList(Circle).init(ctx.db.allocator);
|
||||
var circles = std.ArrayList(Circle).init(ctx.allocator);
|
||||
var circlesIter = try ctx
|
||||
.db
|
||||
.get("circle")
|
||||
.col("player_id")
|
||||
.filter(.{ .player_id = player.player_id});
|
||||
defer circlesIter.close();
|
||||
while(try circlesIter.next()) |circle| {
|
||||
try circles.append(circle);
|
||||
}
|
||||
|
|
@ -756,7 +770,8 @@ pub fn spawn_food(ctx: *spacetime.ReducerContext, _: SpawnFoodTimer) !void {
|
|||
}
|
||||
|
||||
pub fn circle_decay(ctx: *spacetime.ReducerContext, _: CircleDecayTimer) !void {
|
||||
var circleIter = ctx.db.get("circle").iter();
|
||||
var circleIter = try ctx.db.get("circle").iter();
|
||||
defer circleIter.close();
|
||||
while(try circleIter.next()) |circle| {
|
||||
var circle_entity = (try ctx
|
||||
.db
|
||||
|
|
@ -779,7 +794,6 @@ pub fn calculate_center_of_mass(entities: []const Entity) DbVector2 {
|
|||
}
|
||||
break :blk sum;
|
||||
};
|
||||
//entities.iter().map(|e| e.position * e.mass as f32).sum();
|
||||
const center_of_mass: DbVector2 = blk: {
|
||||
var sum: DbVector2 = 0;
|
||||
for(entities) |entity| {
|
||||
|
|
@ -792,16 +806,17 @@ pub fn calculate_center_of_mass(entities: []const Entity) DbVector2 {
|
|||
}
|
||||
|
||||
pub fn circle_recombine(ctx: *spacetime.ReducerContext, timer: CircleRecombineTimer) !void {
|
||||
var circles = std.ArrayList(Circle).init(ctx.db.allocator);
|
||||
var circles = std.ArrayList(Circle).init(ctx.allocator);
|
||||
var circlesIter = try ctx
|
||||
.db
|
||||
.get("circle")
|
||||
.col("player_id")
|
||||
.filter(.{ .player_id = timer.player_id });
|
||||
defer circlesIter.close();
|
||||
while(try circlesIter.next()) |circle| {
|
||||
try circles.append(circle);
|
||||
}
|
||||
var recombining_entities = std.ArrayList(Entity).init(ctx.db.allocator);
|
||||
var recombining_entities = std.ArrayList(Entity).init(ctx.allocator);
|
||||
for(circles.items) |circle| {
|
||||
if(@as(f32, @floatFromInt(ctx.timestamp.__timestamp_micros_since_unix_epoch__ - circle.last_split_time.__timestamp_micros_since_unix_epoch__)) >= SPLIT_RECOMBINE_DELAY_SEC) {
|
||||
const entity = (try ctx.db
|
||||
|
|
|
|||
|
|
@ -64,7 +64,13 @@ pub fn logFn(comptime level: std.log.Level, comptime _: @TypeOf(.enum_literal),
|
|||
pub const BytesSink = extern struct { inner: u32 };
|
||||
pub const BytesSource = extern struct { inner: u32 };
|
||||
pub const TableId = extern struct { _inner: u32, };
|
||||
pub const RowIter = extern struct { _inner: u32, pub const INVALID = RowIter{ ._inner = 0}; };
|
||||
pub const RowIter = extern struct {
|
||||
_inner: u32,
|
||||
pub const INVALID = RowIter{ ._inner = 0};
|
||||
pub fn invalid(self: @This()) bool {
|
||||
return self._inner == 0;
|
||||
}
|
||||
};
|
||||
pub const IndexId = extern struct{ _inner: u32 };
|
||||
pub const ColId = extern struct { _inner: u16 };
|
||||
|
||||
|
|
@ -121,6 +127,7 @@ pub const SpacetimeValue = enum(u1) {
|
|||
};
|
||||
|
||||
pub const SpacetimeError = error {
|
||||
UNKNOWN,
|
||||
HOST_CALL_FAILURE,
|
||||
NOT_IN_TRANSACTION,
|
||||
BSATN_DECODE_ERROR,
|
||||
|
|
@ -586,6 +593,7 @@ pub const Table = struct {
|
|||
pub const Spec = struct {
|
||||
tables: []const Table,
|
||||
reducers: []const SpecReducer,
|
||||
row_level_security: []const []const u8,
|
||||
includes: []const Spec = &.{},
|
||||
};
|
||||
|
||||
|
|
@ -598,6 +606,8 @@ pub fn SpecBuilder(comptime spec: Spec) RawModuleDefV9 {
|
|||
var raw_types: []const AlgebraicType = &[_]AlgebraicType{};
|
||||
var types: []const RawTypeDefV9 = &[_]RawTypeDefV9{};
|
||||
|
||||
var row_level_security: []const RawRowLevelSecurityDefV9 = &[_]RawRowLevelSecurityDefV9{};
|
||||
|
||||
var structDecls: []const StructImpl = &[_]StructImpl{};
|
||||
|
||||
for(spec.tables) |table| {
|
||||
|
|
@ -773,6 +783,14 @@ pub fn SpecBuilder(comptime spec: Spec) RawModuleDefV9 {
|
|||
};
|
||||
}
|
||||
|
||||
for(spec.row_level_security) |rls| {
|
||||
row_level_security = row_level_security ++ &[_]RawRowLevelSecurityDefV9{
|
||||
RawRowLevelSecurityDefV9{
|
||||
.sql = rls,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return .{
|
||||
.typespace = .{
|
||||
.types = raw_types,
|
||||
|
|
@ -781,7 +799,7 @@ pub fn SpecBuilder(comptime spec: Spec) RawModuleDefV9 {
|
|||
.reducers = reducerDefs,
|
||||
.types = types,
|
||||
.misc_exports = &[_]RawMiscModuleExportV9{},
|
||||
.row_level_security = &[_]RawRowLevelSecurityDefV9{},
|
||||
.row_level_security = row_level_security,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -830,14 +848,19 @@ pub export fn __call_reducer__(
|
|||
) i16 {
|
||||
_ = err;
|
||||
|
||||
const allocator = std.heap.wasm_allocator;
|
||||
const backend_allocator = std.heap.wasm_allocator;
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(backend_allocator);
|
||||
defer arena_allocator.deinit();
|
||||
const allocator = arena_allocator.allocator();
|
||||
|
||||
var ctx: ReducerContext = .{
|
||||
.allocator = allocator,
|
||||
.sender = std.mem.bytesAsValue(Identity, std.mem.sliceAsBytes(&[_]u64{ sender_0, sender_1, sender_2, sender_3})).*,
|
||||
.timestamp = Timestamp{ .__timestamp_micros_since_unix_epoch__ = @intCast(timestamp), },
|
||||
.connection_id = std.mem.bytesAsValue(ConnectionId, std.mem.sliceAsBytes(&[_]u64{ conn_id_0, conn_id_1})).*,
|
||||
.db = .{
|
||||
.allocator = allocator,
|
||||
.allocator = backend_allocator,
|
||||
.frame_allocator = allocator,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -109,9 +109,8 @@ fn serialize_raw_misc_module_export_v9(array: *std.ArrayList(u8), val: RawMiscMo
|
|||
}
|
||||
|
||||
fn serialize_raw_row_level_security_def_v9(array: *std.ArrayList(u8), val: RawRowLevelSecurityDefV9) !void {
|
||||
_ = array;
|
||||
_ = val;
|
||||
unreachable;
|
||||
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.sql.len))));
|
||||
try array.appendSlice(val.sql);
|
||||
}
|
||||
|
||||
fn serialize_raw_index_algorithm(array: *std.ArrayList(u8), val: RawIndexAlgorithm) !void {
|
||||
|
|
|
|||
|
|
@ -302,7 +302,6 @@ pub fn StructDeserializer(struct_type: type) fn(allocator: std.mem.Allocator, *[
|
|||
i8, u8, i16, u16, i32, u32,
|
||||
i64, u64, i128, u128, i256, u256,
|
||||
f32, f64 => {
|
||||
//std.log.debug("field_type: {} (offset_mem.len: {})", .{field.type, offset_mem.len});
|
||||
@field(ret, field.name) = std.mem.bytesAsValue(field.type, offset_mem[0..@sizeOf(field.type)]).*;
|
||||
offset_mem = offset_mem[@sizeOf(field.type)..];
|
||||
},
|
||||
|
|
@ -341,44 +340,74 @@ pub fn Iter(struct_type: type) type {
|
|||
return struct {
|
||||
allocator: std.mem.Allocator,
|
||||
handle: spacetime.RowIter,
|
||||
buffer: [0x5_000]u8 = undefined,
|
||||
contents: ?[]u8 = null,
|
||||
buffer: []u8,
|
||||
contents: []u8,
|
||||
last_ret: SpacetimeValue = .OK,
|
||||
inited: bool = false,
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, rowIter: spacetime.RowIter) !@This() {
|
||||
const buffer = try allocator.alloc(u8, 0x20_000);
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.handle = rowIter,
|
||||
.buffer = buffer,
|
||||
.contents = buffer[0..0],
|
||||
.inited = true,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn next(self: *@This()) spacetime.ReducerError!?struct_type {
|
||||
var buffer_len: usize = undefined;
|
||||
var ret: spacetime.SpacetimeValue = self.last_ret;
|
||||
if(self.contents == null or self.contents.?.len == 0) {
|
||||
if(self.handle._inner == spacetime.RowIter.INVALID._inner) {
|
||||
self.contents = null;
|
||||
blk: while(true) {
|
||||
if(self.contents.len == 0) {
|
||||
if(self.handle._inner == spacetime.RowIter.INVALID._inner) {
|
||||
return null;
|
||||
}
|
||||
|
||||
buffer_len = self.buffer.len;
|
||||
ret = spacetime.retMap(spacetime.row_iter_bsatn_advance(self.handle, self.buffer.ptr, &buffer_len)) catch |err| {
|
||||
switch(err) {
|
||||
SpacetimeError.BUFFER_TOO_SMALL => {
|
||||
self.buffer = try self.allocator.realloc(self.buffer, buffer_len);
|
||||
continue :blk;
|
||||
},
|
||||
SpacetimeError.NO_SUCH_ITER => {
|
||||
return SpacetimeError.NO_SUCH_ITER;
|
||||
},
|
||||
else => {
|
||||
return SpacetimeError.UNKNOWN;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.contents = self.buffer[0..buffer_len];
|
||||
|
||||
if(ret == .EXHAUSTED) {
|
||||
self.handle = spacetime.RowIter.INVALID;
|
||||
}
|
||||
self.last_ret = ret;
|
||||
}
|
||||
if(self.contents.len == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
buffer_len = self.buffer.len;
|
||||
ret = try spacetime.retMap(spacetime.row_iter_bsatn_advance(self.handle, @constCast(@ptrCast(&self.buffer)), &buffer_len));
|
||||
self.contents = self.buffer[0..buffer_len];
|
||||
|
||||
if(ret == .EXHAUSTED) {
|
||||
self.handle = spacetime.RowIter.INVALID;
|
||||
}
|
||||
self.last_ret = ret;
|
||||
}
|
||||
if(self.contents == null or self.contents.?.len == 0) {
|
||||
return null;
|
||||
}
|
||||
var offset = self.contents;
|
||||
const retValue = try StructDeserializer(struct_type)(self.allocator, &offset);
|
||||
self.contents = offset;
|
||||
|
||||
return try StructDeserializer(struct_type)(self.allocator, &(self.contents.?));
|
||||
}
|
||||
|
||||
pub fn one_or_null(self: *@This()) ?struct_type {
|
||||
defer self.close();
|
||||
return self.next() catch null;
|
||||
return retValue;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(self: *@This()) void {
|
||||
_ = spacetime.row_iter_bsatn_close(self.handle);
|
||||
self.handle = spacetime.RowIter.INVALID;
|
||||
self.contents = null;
|
||||
if (self.handle.invalid())
|
||||
{
|
||||
_ = spacetime.row_iter_bsatn_close(self.handle);
|
||||
self.handle = spacetime.RowIter.INVALID;
|
||||
}
|
||||
self.contents = undefined;
|
||||
self.allocator.free(self.buffer);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -429,9 +458,9 @@ pub fn Column2ORM(comptime table_name: []const u8, comptime column_name: [:0]con
|
|||
};
|
||||
|
||||
const size: usize = getStructSize(nVal);
|
||||
const mem = try self.allocator.alloc(u8, size);
|
||||
var offset_mem = mem;
|
||||
const mem = try self.allocator.alignedAlloc(u8, 1, size);
|
||||
defer self.allocator.free(mem);
|
||||
var offset_mem = mem;
|
||||
getStructData(nVal, &offset_mem);
|
||||
|
||||
const data = mem[0..size];
|
||||
|
|
@ -449,15 +478,12 @@ pub fn Column2ORM(comptime table_name: []const u8, comptime column_name: [:0]con
|
|||
&rowIter
|
||||
));
|
||||
|
||||
return Iter(struct_type){
|
||||
.allocator = self.allocator,
|
||||
.handle = rowIter,
|
||||
};
|
||||
return Iter(struct_type).init(self.allocator, rowIter);
|
||||
}
|
||||
|
||||
pub fn find(self: @This(), val: wrapped_type) !?struct_type {
|
||||
var iter = try self.filter(val);
|
||||
return iter.one_or_null();
|
||||
return try iter.next();
|
||||
}
|
||||
|
||||
pub fn delete(self: @This(), val: wrapped_type) !void {
|
||||
|
|
@ -472,8 +498,8 @@ pub fn Column2ORM(comptime table_name: []const u8, comptime column_name: [:0]con
|
|||
|
||||
const size: usize = getStructSize(nVal);
|
||||
const mem = try self.allocator.alloc(u8, size);
|
||||
var offset_mem = mem;
|
||||
defer self.allocator.free(mem);
|
||||
var offset_mem = mem;
|
||||
getStructData(nVal, &offset_mem);
|
||||
|
||||
const data = mem[0..size];
|
||||
|
|
@ -502,8 +528,8 @@ pub fn Column2ORM(comptime table_name: []const u8, comptime column_name: [:0]con
|
|||
|
||||
const size: usize = getStructSize(val);
|
||||
const mem = try self.allocator.alloc(u8, size);
|
||||
var offset_mem = mem;
|
||||
defer self.allocator.free(mem);
|
||||
var offset_mem = mem;
|
||||
getStructData(val, &offset_mem);
|
||||
|
||||
const data = mem[0..size];
|
||||
|
|
@ -579,15 +605,12 @@ pub fn Table2ORM(comptime table_name: []const u8) type {
|
|||
return data_copy;
|
||||
}
|
||||
|
||||
pub fn iter(self: @This()) Iter(struct_type) {
|
||||
pub fn iter(self: @This()) !Iter(struct_type) {
|
||||
var id: TableId = undefined;
|
||||
_ = spacetime.table_id_from_name(table_name.ptr, table_name.len, &id);
|
||||
var rowIter: spacetime.RowIter = undefined;
|
||||
_ = spacetime.datastore_table_scan_bsatn(id, &rowIter);
|
||||
return Iter(struct_type){
|
||||
.allocator = self.allocator,
|
||||
.handle = rowIter,
|
||||
};
|
||||
return Iter(struct_type).init(self.allocator, rowIter);
|
||||
}
|
||||
|
||||
pub fn col(self: @This(), comptime column_name: [:0]const u8) Column2ORM(table_name, column_name) {
|
||||
|
|
@ -609,15 +632,17 @@ pub fn Table2ORM(comptime table_name: []const u8) type {
|
|||
|
||||
pub const Local = struct {
|
||||
allocator: std.mem.Allocator,
|
||||
frame_allocator: std.mem.Allocator,
|
||||
|
||||
pub fn get(self: @This(), comptime table: []const u8) Table2ORM(table) {
|
||||
return .{
|
||||
.allocator = self.allocator,
|
||||
.allocator = self.frame_allocator,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const ReducerContext = struct {
|
||||
allocator: std.mem.Allocator,
|
||||
sender: spacetime.Identity,
|
||||
timestamp: spacetime.Timestamp,
|
||||
connection_id: spacetime.ConnectionId,
|
||||
|
|
@ -648,7 +673,7 @@ pub const RawMiscModuleExportV9 = enum {
|
|||
RESERVED,
|
||||
};
|
||||
|
||||
pub const RawSql = []u8;
|
||||
pub const RawSql = Str;
|
||||
|
||||
pub const RawRowLevelSecurityDefV9 = struct {
|
||||
sql: RawSql,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue