JsonElement.get and .put can now handle Vector attributes.

fixes #430
This commit is contained in:
IntegratedQuantum 2024-06-02 20:09:34 +02:00
parent f339db4e69
commit 3a74300a43
8 changed files with 56 additions and 91 deletions

View File

@ -1,11 +1,11 @@
{ {
"spawn" : { "spawn" : [
"x" : 3198, 3198,
"z" : 100, 59786,
"y" : 59786 100
}, ],
"version" : 2, "version" : 2,
"seed" : 1982878604, "seed" : 1982878604,
"doGameTimeCycle" : false, "doGameTimeCycle" : true,
"gameTime" : 0 "gameTime" : 0
} }

View File

@ -150,10 +150,7 @@ pub const World = struct {
// TODO: Consider using a per-world allocator. // TODO: Consider using a per-world allocator.
self.blockPalette = try assets.BlockPalette.init(main.globalAllocator, json.getChild("blockPalette")); self.blockPalette = try assets.BlockPalette.init(main.globalAllocator, json.getChild("blockPalette"));
errdefer self.blockPalette.deinit(); errdefer self.blockPalette.deinit();
const jsonSpawn = json.getChild("spawn"); self.spawn = json.get(Vec3f, "spawn", .{0, 0, 0});
self.spawn[0] = jsonSpawn.get(f32, "x", 0);
self.spawn[1] = jsonSpawn.get(f32, "y", 0);
self.spawn[2] = jsonSpawn.get(f32, "z", 0);
try assets.loadWorldAssets("serverAssets", self.blockPalette); try assets.loadWorldAssets("serverAssets", self.blockPalette);
Player.loadFrom(json.getChild("player")); Player.loadFrom(json.getChild("player"));

View File

@ -105,16 +105,8 @@ pub const ItemDropManager = struct {
return; return;
}; };
const properties = .{ const properties = .{
Vec3d{ json.get(Vec3d, "pos", .{0, 0, 0}),
json.get(f64, "x", 0), json.get(Vec3d, "vel", .{0, 0, 0}),
json.get(f64, "y", 0),
json.get(f64, "z", 0),
},
Vec3d{
json.get(f64, "vx", 0),
json.get(f64, "vy", 0),
json.get(f64, "vz", 0),
},
items.ItemStack{.item = item, .amount = json.get(u16, "amount", 1)}, items.ItemStack{.item = item, .amount = json.get(u16, "amount", 1)},
json.get(i32, "despawnTime", 60), json.get(i32, "despawnTime", 60),
0 0
@ -147,12 +139,8 @@ pub const ItemDropManager = struct {
const obj = JsonElement.initObject(allocator); const obj = JsonElement.initObject(allocator);
const itemDrop = self.list.get(i); const itemDrop = self.list.get(i);
obj.put("i", i); obj.put("i", i);
obj.put("x", itemDrop.pos.x); obj.put("pos", itemDrop.pos);
obj.put("y", itemDrop.pos.y); obj.put("vel", itemDrop.vel);
obj.put("z", itemDrop.pos.z);
obj.put("vx", itemDrop.vel.x);
obj.put("vy", itemDrop.vel.y);
obj.put("vz", itemDrop.vel.z);
itemDrop.itemStack.storeToJson(obj); itemDrop.itemStack.storeToJson(obj);
obj.put("despawnTime", itemDrop.despawnTime); obj.put("despawnTime", itemDrop.despawnTime);
return obj; return obj;

View File

@ -84,9 +84,9 @@ pub const JsonElement = union(JsonType) {
} }
} }
pub fn as(self: *const JsonElement, comptime _type: type, replacement: _type) _type { pub fn as(self: *const JsonElement, comptime T: type, replacement: T) T {
comptime var typeInfo = @typeInfo(_type); comptime var typeInfo : std.builtin.Type = @typeInfo(T);
comptime var innerType = _type; comptime var innerType = T;
inline while(typeInfo == .Optional) { inline while(typeInfo == .Optional) {
innerType = typeInfo.Optional.child; innerType = typeInfo.Optional.child;
typeInfo = @typeInfo(innerType); typeInfo = @typeInfo(innerType);
@ -106,6 +106,21 @@ pub const JsonElement = union(JsonType) {
else => return replacement, else => return replacement,
} }
}, },
.Vector => {
const len = typeInfo.Vector.len;
const elems = self.toSlice();
if(elems.len != len) return replacement;
var result: innerType = undefined;
if(innerType == T) result = replacement;
inline for(0..len) |i| {
if(innerType == T) {
result[i] = elems[i].as(typeInfo.Vector.child, result[i]);
} else {
result[i] = elems[i].as(?typeInfo.Vector.child, null) orelse return replacement;
}
}
return result;
},
else => { else => {
switch(innerType) { switch(innerType) {
[]const u8 => { []const u8 => {
@ -122,14 +137,14 @@ pub const JsonElement = union(JsonType) {
} }
}, },
else => { else => {
@compileError("Unsupported type '" ++ @typeName(_type) ++ "'."); @compileError("Unsupported type '" ++ @typeName(T) ++ "'.");
} }
} }
}, },
} }
} }
fn createElementFromRandomType(value: anytype) JsonElement { fn createElementFromRandomType(value: anytype, allocator: std.mem.Allocator) JsonElement {
switch(@typeInfo(@TypeOf(value))) { switch(@typeInfo(@TypeOf(value))) {
.Void => return JsonElement{.JsonNull={}}, .Void => return JsonElement{.JsonNull={}},
.Null => return JsonElement{.JsonNull={}}, .Null => return JsonElement{.JsonNull={}},
@ -157,11 +172,20 @@ pub const JsonElement = union(JsonType) {
}, },
.Optional => { .Optional => {
if(value) |val| { if(value) |val| {
return createElementFromRandomType(val); return createElementFromRandomType(val, allocator);
} else { } else {
return JsonElement{.JsonNull={}}; return JsonElement{.JsonNull={}};
} }
}, },
.Vector => {
const len = @typeInfo(@TypeOf(value)).Vector.len;
const result = initArray(main.utils.NeverFailingAllocator{.allocator = allocator, .IAssertThatTheProvidedAllocatorCantFail = {}});
result.JsonArray.ensureCapacity(len);
inline for(0..len) |i| {
result.JsonArray.appendAssumeCapacity(createElementFromRandomType(value[i], allocator));
}
return result;
},
else => { else => {
if(@TypeOf(value) == JsonElement) { if(@TypeOf(value) == JsonElement) {
return value; return value;
@ -173,7 +197,7 @@ pub const JsonElement = union(JsonType) {
} }
pub fn put(self: *const JsonElement, key: []const u8, value: anytype) void { pub fn put(self: *const JsonElement, key: []const u8, value: anytype) void {
const result = createElementFromRandomType(value); const result = createElementFromRandomType(value, self.JsonObject.allocator);
self.JsonObject.put(self.JsonObject.allocator.dupe(u8, key) catch unreachable, result) catch unreachable; self.JsonObject.put(self.JsonObject.allocator.dupe(u8, key) catch unreachable, result) catch unreachable;
} }

View File

@ -676,11 +676,7 @@ pub const Protocols = struct {
const jsonObject = JsonElement.initObject(main.stackAllocator); const jsonObject = JsonElement.initObject(main.stackAllocator);
defer jsonObject.free(main.stackAllocator); defer jsonObject.free(main.stackAllocator);
jsonObject.put("player", conn.user.?.player.save(main.stackAllocator)); jsonObject.put("player", conn.user.?.player.save(main.stackAllocator));
const spawn = JsonElement.initObject(main.stackAllocator); jsonObject.put("spawn", main.server.world.?.spawn);
spawn.put("x", main.server.world.?.spawn[0]);
spawn.put("y", main.server.world.?.spawn[1]);
spawn.put("z", main.server.world.?.spawn[2]);
jsonObject.put("spawn", spawn);
jsonObject.put("blockPalette", main.server.world.?.blockPalette.save(main.stackAllocator)); jsonObject.put("blockPalette", main.server.world.?.blockPalette.save(main.stackAllocator));
const outData = jsonObject.toStringEfficient(main.stackAllocator, &[1]u8{stepServerData}); const outData = jsonObject.toStringEfficient(main.stackAllocator, &[1]u8{stepServerData});
@ -1107,12 +1103,8 @@ pub const Protocols = struct {
pub fn itemStackDrop(conn: *Connection, stack: ItemStack, pos: Vec3d, dir: Vec3f, vel: f32) void { pub fn itemStackDrop(conn: *Connection, stack: ItemStack, pos: Vec3d, dir: Vec3f, vel: f32) void {
const jsonObject = stack.store(main.stackAllocator); const jsonObject = stack.store(main.stackAllocator);
defer jsonObject.free(main.stackAllocator); defer jsonObject.free(main.stackAllocator);
jsonObject.put("x", pos[0]); jsonObject.put("pos", pos);
jsonObject.put("y", pos[1]); jsonObject.put("dir", dir);
jsonObject.put("z", pos[2]);
jsonObject.put("dirX", dir[0]);
jsonObject.put("dirY", dir[1]);
jsonObject.put("dirZ", dir[2]);
jsonObject.put("vel", vel); jsonObject.put("vel", vel);
const string = jsonObject.toString(main.stackAllocator); const string = jsonObject.toString(main.stackAllocator);
defer main.stackAllocator.free(string); defer main.stackAllocator.free(string);

View File

@ -13,40 +13,16 @@ rot: Vec3f = .{0, 0, 0},
// TODO: Health and hunger // TODO: Health and hunger
// TODO: Name // TODO: Name
fn loadVec3f(json: JsonElement) Vec3f {
return .{
json.get(f32, "x", 0),
json.get(f32, "y", 0),
json.get(f32, "z", 0),
};
}
fn loadVec3d(json: JsonElement) Vec3d {
return .{
json.get(f64, "x", 0),
json.get(f64, "y", 0),
json.get(f64, "z", 0),
};
}
fn saveVec3(allocator: NeverFailingAllocator, vector: anytype) JsonElement {
const json = JsonElement.initObject(allocator);
json.put("x", vector[0]);
json.put("y", vector[1]);
json.put("z", vector[2]);
return json;
}
pub fn loadFrom(self: *@This(), json: JsonElement) void { pub fn loadFrom(self: *@This(), json: JsonElement) void {
self.pos = loadVec3d(json.getChild("position")); self.pos = json.get(Vec3d, "position", .{0, 0, 0});
self.vel = loadVec3d(json.getChild("velocity")); self.vel = json.get(Vec3d, "velocity", .{0, 0, 0});
self.rot = loadVec3f(json.getChild("rotation")); self.rot = json.get(Vec3f, "rotation", .{0, 0, 0});
} }
pub fn save(self: *@This(), allocator: NeverFailingAllocator) JsonElement { pub fn save(self: *@This(), allocator: NeverFailingAllocator) JsonElement {
const json = JsonElement.initObject(allocator); const json = JsonElement.initObject(allocator);
json.put("position", saveVec3(allocator, self.pos)); json.put("position", self.pos);
json.put("velocity", saveVec3(allocator, self.vel)); json.put("velocity", self.vel);
json.put("rotation", saveVec3(allocator, self.rot)); json.put("rotation", self.rot);
return json; return json;
} }

View File

@ -63,14 +63,9 @@ const Stripe = struct {
maxWidth: f64, maxWidth: f64,
pub fn init(parameters: JsonElement) Stripe { pub fn init(parameters: JsonElement) Stripe {
const items: []JsonElement = parameters.getChild("direction").toSlice(); var dir: ?Vec3d = parameters.get(?Vec3d, "direction", null);
var dir: ?Vec3d = null; if(dir != null) {
if (items.len == 3) { dir = main.vec.normalize(dir.?);
const dx = items[0].as(f64, 0);
const dy = items[1].as(f64, 0);
const dz = items[2].as(f64, 0);
const d: Vec3d = .{dx, dy, dz};
dir = main.vec.normalize(d);
} }
const block: u16 = blocks.getByID(parameters.get([]const u8, "block", "")); const block: u16 = blocks.getByID(parameters.get([]const u8, "block", ""));

View File

@ -287,10 +287,7 @@ const WorldIO = struct {
self.world.doGameTimeCycle = worldData.get(bool, "doGameTimeCycle", true); self.world.doGameTimeCycle = worldData.get(bool, "doGameTimeCycle", true);
self.world.gameTime = worldData.get(i64, "gameTime", 0); self.world.gameTime = worldData.get(i64, "gameTime", 0);
const spawnData = worldData.getChild("spawn"); self.world.spawn = worldData.get(Vec3i, "spawn", .{0, 0, 0});
self.world.spawn[0] = spawnData.get(i32, "x", 0);
self.world.spawn[1] = spawnData.get(i32, "y", 0);
self.world.spawn[2] = spawnData.get(i32, "z", 0);
} }
pub fn saveWorldData(self: WorldIO) !void { pub fn saveWorldData(self: WorldIO) !void {
@ -300,11 +297,7 @@ const WorldIO = struct {
worldData.put("seed", self.world.seed); worldData.put("seed", self.world.seed);
worldData.put("doGameTimeCycle", self.world.doGameTimeCycle); worldData.put("doGameTimeCycle", self.world.doGameTimeCycle);
worldData.put("gameTime", self.world.gameTime); worldData.put("gameTime", self.world.gameTime);
const spawnData = JsonElement.initObject(main.stackAllocator); worldData.put("spawn", self.world.spawn);
spawnData.put("x", self.world.spawn[0]);
spawnData.put("y", self.world.spawn[1]);
spawnData.put("z", self.world.spawn[2]);
worldData.put("spawn", spawnData);
// TODO: Save entities // TODO: Save entities
try self.dir.writeJson("world.dat", worldData); try self.dir.writeJson("world.dat", worldData);
} }