// 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).?.*; }