artificer/api/schemas/map.zig

99 lines
3.1 KiB
Zig

// zig fmt: off
const std = @import("std");
const Store = @import("../store.zig");
const Position = @import("./position.zig");
const json_utils = @import("../json_utils.zig");
const Monster = @import("./monster.zig");
const Resource = @import("./resource.zig");
const Craft = @import("./craft.zig");
const EnumStringUtils = @import("../enum_string_utils.zig").EnumStringUtils;
const Map = @This();
pub const Name = std.BoundedArray(u8, 16);
pub const max_skin_size = 32;
pub const Skin = std.BoundedArray(u8, max_skin_size);
pub const Content = struct {
pub const Type = enum {
monster,
resource,
workshop,
bank,
grand_exchange,
tasks_master,
santa_claus,
const Utils = EnumStringUtils(Type, .{
.{ "monster" , Type.monster },
.{ "resource" , Type.resource },
.{ "workshop" , Type.workshop },
.{ "bank" , Type.bank },
.{ "grand_exchange", Type.grand_exchange },
.{ "tasks_master" , Type.tasks_master },
.{ "santa_claus" , Type.santa_claus },
});
pub const fromString = Utils.fromString;
pub const toString = Utils.toString;
};
pub const max_code_size = size: {
var max: usize = 0;
max = @max(max, Monster.max_code_size);
max = @max(max, Resource.max_code_size);
for (std.meta.fields(Craft.Skill)) |field| {
max = @max(max, Craft.Skill.toString(@enumFromInt(field.value)).len);
}
max = @max(max, "bank".len);
max = @max(max, "grand_exchange".len);
// TODO: max type 'tasks_master'
break :size max;
};
pub const Code = std.BoundedArray(u8, max_code_size);
type: Type,
code: Code,
};
name: Name,
skin: Skin,
position: Position,
content: ?Content,
pub fn parse(store: *Store, obj: std.json.ObjectMap) !Map {
_ = store;
const name = try json_utils.getStringRequired(obj, "name");
const skin = try json_utils.getStringRequired(obj, "skin");
const x = try json_utils.getIntegerRequired(obj, "x");
const y = try json_utils.getIntegerRequired(obj, "y");
var content: ?Content = null;
if (json_utils.getObject(obj, "content")) |content_obj| {
const content_code = try json_utils.getStringRequired(content_obj, "code");
const content_type = try json_utils.getStringRequired(content_obj, "type");
content = Content{
.code = try Content.Code.fromSlice(content_code),
.type = Content.Type.fromString(content_type) orelse return error.InvalidContentType
};
}
return Map{
.name = try Name.fromSlice(name),
.skin = try Skin.fromSlice(skin),
.position = Position.init(x, y),
.content = content
};
}
pub fn parseAndAppend(store: *Store, obj: std.json.ObjectMap) !Position {
return store.appendOrUpdateMap(try parse(store, obj));
}
pub fn parseAndAppendObject(store: *Store, obj: std.json.ObjectMap) !Map {
const position = try parseAndAppend(store, obj);
return store.getMap(position).?.*;
}