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" : {
"x" : 3198,
"z" : 100,
"y" : 59786
},
"spawn" : [
3198,
59786,
100
],
"version" : 2,
"seed" : 1982878604,
"doGameTimeCycle" : false,
"doGameTimeCycle" : true,
"gameTime" : 0
}

View File

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

View File

@ -105,16 +105,8 @@ pub const ItemDropManager = struct {
return;
};
const properties = .{
Vec3d{
json.get(f64, "x", 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),
},
json.get(Vec3d, "pos", .{0, 0, 0}),
json.get(Vec3d, "vel", .{0, 0, 0}),
items.ItemStack{.item = item, .amount = json.get(u16, "amount", 1)},
json.get(i32, "despawnTime", 60),
0
@ -147,12 +139,8 @@ pub const ItemDropManager = struct {
const obj = JsonElement.initObject(allocator);
const itemDrop = self.list.get(i);
obj.put("i", i);
obj.put("x", itemDrop.pos.x);
obj.put("y", itemDrop.pos.y);
obj.put("z", itemDrop.pos.z);
obj.put("vx", itemDrop.vel.x);
obj.put("vy", itemDrop.vel.y);
obj.put("vz", itemDrop.vel.z);
obj.put("pos", itemDrop.pos);
obj.put("vel", itemDrop.vel);
itemDrop.itemStack.storeToJson(obj);
obj.put("despawnTime", itemDrop.despawnTime);
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 {
comptime var typeInfo = @typeInfo(_type);
comptime var innerType = _type;
pub fn as(self: *const JsonElement, comptime T: type, replacement: T) T {
comptime var typeInfo : std.builtin.Type = @typeInfo(T);
comptime var innerType = T;
inline while(typeInfo == .Optional) {
innerType = typeInfo.Optional.child;
typeInfo = @typeInfo(innerType);
@ -106,6 +106,21 @@ pub const JsonElement = union(JsonType) {
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 => {
switch(innerType) {
[]const u8 => {
@ -122,14 +137,14 @@ pub const JsonElement = union(JsonType) {
}
},
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))) {
.Void => return JsonElement{.JsonNull={}},
.Null => return JsonElement{.JsonNull={}},
@ -157,11 +172,20 @@ pub const JsonElement = union(JsonType) {
},
.Optional => {
if(value) |val| {
return createElementFromRandomType(val);
return createElementFromRandomType(val, allocator);
} else {
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 => {
if(@TypeOf(value) == JsonElement) {
return value;
@ -173,7 +197,7 @@ pub const JsonElement = union(JsonType) {
}
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;
}

View File

@ -676,11 +676,7 @@ pub const Protocols = struct {
const jsonObject = JsonElement.initObject(main.stackAllocator);
defer jsonObject.free(main.stackAllocator);
jsonObject.put("player", conn.user.?.player.save(main.stackAllocator));
const spawn = JsonElement.initObject(main.stackAllocator);
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("spawn", main.server.world.?.spawn);
jsonObject.put("blockPalette", main.server.world.?.blockPalette.save(main.stackAllocator));
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 {
const jsonObject = stack.store(main.stackAllocator);
defer jsonObject.free(main.stackAllocator);
jsonObject.put("x", pos[0]);
jsonObject.put("y", pos[1]);
jsonObject.put("z", pos[2]);
jsonObject.put("dirX", dir[0]);
jsonObject.put("dirY", dir[1]);
jsonObject.put("dirZ", dir[2]);
jsonObject.put("pos", pos);
jsonObject.put("dir", dir);
jsonObject.put("vel", vel);
const string = jsonObject.toString(main.stackAllocator);
defer main.stackAllocator.free(string);

View File

@ -13,40 +13,16 @@ rot: Vec3f = .{0, 0, 0},
// TODO: Health and hunger
// 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 {
self.pos = loadVec3d(json.getChild("position"));
self.vel = loadVec3d(json.getChild("velocity"));
self.rot = loadVec3f(json.getChild("rotation"));
self.pos = json.get(Vec3d, "position", .{0, 0, 0});
self.vel = json.get(Vec3d, "velocity", .{0, 0, 0});
self.rot = json.get(Vec3f, "rotation", .{0, 0, 0});
}
pub fn save(self: *@This(), allocator: NeverFailingAllocator) JsonElement {
const json = JsonElement.initObject(allocator);
json.put("position", saveVec3(allocator, self.pos));
json.put("velocity", saveVec3(allocator, self.vel));
json.put("rotation", saveVec3(allocator, self.rot));
json.put("position", self.pos);
json.put("velocity", self.vel);
json.put("rotation", self.rot);
return json;
}

View File

@ -63,14 +63,9 @@ const Stripe = struct {
maxWidth: f64,
pub fn init(parameters: JsonElement) Stripe {
const items: []JsonElement = parameters.getChild("direction").toSlice();
var dir: ?Vec3d = null;
if (items.len == 3) {
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);
var dir: ?Vec3d = parameters.get(?Vec3d, "direction", null);
if(dir != null) {
dir = main.vec.normalize(dir.?);
}
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.gameTime = worldData.get(i64, "gameTime", 0);
const spawnData = worldData.getChild("spawn");
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);
self.world.spawn = worldData.get(Vec3i, "spawn", .{0, 0, 0});
}
pub fn saveWorldData(self: WorldIO) !void {
@ -300,11 +297,7 @@ const WorldIO = struct {
worldData.put("seed", self.world.seed);
worldData.put("doGameTimeCycle", self.world.doGameTimeCycle);
worldData.put("gameTime", self.world.gameTime);
const spawnData = JsonElement.initObject(main.stackAllocator);
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);
worldData.put("spawn", self.world.spawn);
// TODO: Save entities
try self.dir.writeJson("world.dat", worldData);
}