artificer/api/schemas/character.zig

191 lines
6.6 KiB
Zig

// zig fmt: off
const std = @import("std");
const Store = @import("../store.zig");
const EnumStringUtils = @import("../enum_string_utils.zig").EnumStringUtils;
const json_utils = @import("../json_utils.zig");
pub const Equipment = @import("./equipment.zig");
const Task = @import("./task.zig");
const SimpleItem = @import("./simple_item.zig");
const Character = @This();
pub const Skin = enum {
men1,
men2,
men3,
women1,
women2,
women3,
const Utils = EnumStringUtils(Skin, .{
.{ "men1" , Skin.men1 },
.{ "men2" , Skin.men2 },
.{ "men3" , Skin.men3 },
.{ "women1", Skin.women1 },
.{ "women2", Skin.women2 },
.{ "women3", Skin.women3 },
});
pub const fromString = Utils.fromString;
pub const toString = Utils.toString;
};
pub const Skill = enum {
combat,
fishing,
weaponcrafting,
gearcrafting,
jewelrycrafting,
cooking,
woodcutting,
mining,
alchemy,
const Utils = EnumStringUtils(Skill, .{
.{ "combat" , Skill.combat },
.{ "fishing" , Skill.fishing },
.{ "weaponcrafting" , Skill.weaponcrafting },
.{ "gearcrafting" , Skill.gearcrafting },
.{ "jewelrycrafting", Skill.jewelrycrafting },
.{ "cooking" , Skill.cooking },
.{ "woodcutting" , Skill.woodcutting },
.{ "mining" , Skill.mining },
.{ "alchemy" , Skill.alchemy },
});
pub const toString = Utils.toString;
pub const fromString = Utils.fromString;
};
pub const SkillStats = struct {
level: u64 = 0,
xp: u64 = 0,
max_xp: u64 = 0,
pub fn parse(object: std.json.ObjectMap, level: []const u8, xp: []const u8, max_xp: []const u8) !SkillStats {
return SkillStats{
.level = try json_utils.getPositiveIntegerRequired(object, level),
.xp = try json_utils.getPositiveIntegerRequired(object, xp),
.max_xp = try json_utils.getPositiveIntegerRequired(object, max_xp),
};
}
};
pub const Element = enum {
water,
fire,
earth,
air,
};
pub const ElementalStats = struct {
attack: i64,
damage: i64,
resistance: i64,
pub fn parse(object: std.json.ObjectMap, attack: []const u8, damage: []const u8, resistance: []const u8) !ElementalStats {
return ElementalStats{
.attack = try json_utils.getIntegerRequired(object, attack),
.damage = try json_utils.getIntegerRequired(object, damage),
.resistance = try json_utils.getIntegerRequired(object, resistance),
};
}
};
const TaskMasterTask = struct {
target: Store.Id,
type: Task.Type,
progress: u64,
total: u64,
fn parse(store: *Store, obj: std.json.ObjectMap) !?TaskMasterTask {
const task_target = try json_utils.getStringRequired(obj, "task");
if (task_target.len == 0) {
return null;
}
const task_type = try json_utils.getStringRequired(obj, "task_type");
const progress = try json_utils.getPositiveIntegerRequired(obj, "task_progress");
const total = try json_utils.getPositiveIntegerRequired(obj, "task_total");
return TaskMasterTask{
.target = try store.tasks.getOrReserveId(task_target),
.type = Task.Type.fromString(task_type) orelse return error.InvalidTaskType,
.total = total,
.progress = progress,
};
}
};
pub const ElementalStatsArray = std.EnumArray(Element, ElementalStats);
pub const Skills = std.EnumArray(Skill, SkillStats);
pub const max_name_size = 12;
pub const Name = std.BoundedArray(u8, max_name_size);
pub const max_account_size = 32;
pub const Account = std.BoundedArray(u8, max_account_size);
pub const Inventory = SimpleItem.BoundedArray(20);
name: Name,
account: Account,
skin: Skin,
gold: u64,
skills: Skills,
elemental_stats: ElementalStatsArray,
equipment: Equipment,
task: ?TaskMasterTask,
inventory_max_items: u64,
inventory: Inventory,
pub fn parse(store: *Store, obj: std.json.ObjectMap) !Character {
const name = try json_utils.getStringRequired(obj, "name");
if (name.len == 0) {
return error.InvalidName;
}
const inventory = try json_utils.getArrayRequired(obj, "inventory");
const account = try json_utils.getStringRequired(obj, "name");
const skin = try json_utils.getStringRequired(obj, "skin");
const gold = try json_utils.getPositiveIntegerRequired(obj, "gold");
const inventory_max_items = try json_utils.getPositiveIntegerRequired(obj, "inventory_max_items");
const skill_stats = Skills.init(.{
.combat = try SkillStats.parse(obj, "level", "xp", "max_xp"),
.mining = try SkillStats.parse(obj, "mining_level", "mining_xp", "mining_max_xp"),
.woodcutting = try SkillStats.parse(obj, "woodcutting_level", "woodcutting_xp", "woodcutting_max_xp"),
.fishing = try SkillStats.parse(obj, "fishing_level", "fishing_xp", "fishing_max_xp"),
.weaponcrafting = try SkillStats.parse(obj, "weaponcrafting_level", "weaponcrafting_xp", "weaponcrafting_max_xp"),
.gearcrafting = try SkillStats.parse(obj, "gearcrafting_level", "gearcrafting_xp", "gearcrafting_max_xp"),
.jewelrycrafting = try SkillStats.parse(obj, "jewelrycrafting_level", "jewelrycrafting_xp", "jewelrycrafting_max_xp"),
.cooking = try SkillStats.parse(obj, "cooking_level", "cooking_xp", "cooking_max_xp"),
.alchemy = try SkillStats.parse(obj, "alchemy_level", "alchemy_xp", "alchemy_max_xp"),
});
const elemental_stats = ElementalStatsArray.init(.{
.water = try ElementalStats.parse(obj, "attack_water", "dmg_water", "res_water"),
.fire = try ElementalStats.parse(obj, "attack_fire", "dmg_fire", "res_fire"),
.earth = try ElementalStats.parse(obj, "attack_earth", "dmg_earth", "res_earth"),
.air = try ElementalStats.parse(obj, "attack_air", "dmg_air", "res_air"),
});
return Character{
.name = try Name.fromSlice(name),
.account = try Account.fromSlice(account),
.skin = Skin.fromString(skin) orelse return error.SkinNotFound,
.gold = gold,
.skills = skill_stats,
.elemental_stats = elemental_stats,
.equipment = try Equipment.parse(store, obj),
.task = try TaskMasterTask.parse(store, obj),
.inventory_max_items = inventory_max_items,
.inventory = try Inventory.parse(store, inventory)
};
}
pub fn parseAndAppend(store: *Store, obj: std.json.ObjectMap) !Store.Id {
return store.characters.appendOrUpdate(try parse(store, obj));
}