From f616610fe6e7ac6d57a6da3d46e1a8cf3189ed24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ki=C3=ABd=20Llaentenn?= Date: Thu, 12 Oct 2023 13:02:03 -0400 Subject: [PATCH] feat: (WIP) serialization --- src/items.zig | 19 ++++++++++ src/items/itemlists.zig | 3 ++ src/list.zig | 16 ++++++-- src/main.zig | 9 ++++- src/mobs.zig | 65 ++++++++++++-------------------- src/serializer.zig | 83 ++++++++++++++++++++++++++--------------- 6 files changed, 117 insertions(+), 78 deletions(-) diff --git a/src/items.zig b/src/items.zig index 9ff10f07..ae5886e3 100644 --- a/src/items.zig +++ b/src/items.zig @@ -1798,6 +1798,25 @@ pub const SHOCK2_STRS = [_]DamageStr{ _dmgstr(100, "electrocutes", "electrocutes", ""), }; +// Mob weapons {{{ +pub const NONE_WEAPON = Weapon{ + .id = "", + .name = "blue plastic train", + .damage = 0, + .strs = &[_]DamageStr{_dmgstr(80, "hurl", "hurls", " at kiedtl")}, +}; + +pub const W_SWORD_1 = Weapon{ .damage = 1, .strs = &SLASHING_STRS, .name = "sword" }; +pub const W_SWORD_2 = Weapon{ .damage = 2, .strs = &SLASHING_STRS, .name = "sword" }; +pub const W_KNOUT_3 = Weapon{ .damage = 3, .strs = &CRUSHING_STRS, .delay = 200, .name = "knout" }; +pub const W_BLUDG_1 = Weapon{ .damage = 1, .strs = &CRUSHING_STRS, .name = "bludgeon" }; +pub const W_BLUDG_2 = Weapon{ .damage = 2, .strs = &CRUSHING_STRS, .name = "bludgeon" }; +pub const W_MACES_2 = Weapon{ .damage = 2, .strs = &CRUSHING_STRS, .name = "mace" }; +pub const W_MACES_3 = Weapon{ .damage = 3, .strs = &CRUSHING_STRS, .name = "mace" }; +pub const W_MSWRD_1 = Weapon{ .damage = 1, .strs = &SLASHING_STRS, .name = "martial sword", .martial = true }; +pub const W_SPROD_1 = Weapon{ .damage = 1, .damage_kind = .Electric, .strs = &SHOCK_STRS, .name = "shock prod" }; +// }}} + // Body weapons {{{ pub const FistWeapon = Weapon{ .id = "none", diff --git a/src/items/itemlists.zig b/src/items/itemlists.zig index fb926658..96d6fa39 100644 --- a/src/items/itemlists.zig +++ b/src/items/itemlists.zig @@ -2,6 +2,7 @@ const std = @import("std"); const meta = std.meta; const items = @import("../items.zig"); +const mobs = @import("../items.zig"); const types = @import("../types.zig"); const Armor = types.Armor; @@ -14,10 +15,12 @@ const Weapon = types.Weapon; fn _createDeclList(comptime T: type) []const *const T { @setEvalBranchQuota(9999); comptime var buf: []const *const T = &[_]*const T{}; + inline for (meta.declarations(items)) |declinfo| if (declinfo.is_pub) comptime if (@TypeOf(@field(items, declinfo.name)) == T) { buf = buf ++ [_]*const T{&@field(items, declinfo.name)}; }; + return buf; } diff --git a/src/list.zig b/src/list.zig index c17860bd..749ab717 100644 --- a/src/list.zig +++ b/src/list.zig @@ -162,10 +162,18 @@ pub fn LinkedList(comptime T: type) type { } pub fn deserialize(out: *@This(), in: anytype, alloc: mem.Allocator) !void { - out.* = @This().init(alloc); - var i = try serializer.deserializeQ(usize, in, alloc); - while (i > 0) : (i -= 1) - try out.append(try serializer.deserializeQ(T, in, alloc)); + //out.* = @This().init(alloc); + const neededlen = try serializer.deserializeQ(usize, in, alloc); + + if (neededlen > out.len()) { + var i = out.len(); + while (i < neededlen) : (i += 1) try out.append(undefined); + } + + var i: usize = 0; + while (i < neededlen) : (i += 1) { + try serializer.deserialize(T, out.nth(i).?, in, alloc); + } } // Deserialization stuff diff --git a/src/main.zig b/src/main.zig index 5733bd89..d3cd291d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -745,8 +745,13 @@ fn viewerMain() void { if (t == termbox.TB_EVENT_KEY) { if (ev.key != 0) { - if (ev.key == termbox.TB_KEY_CTRL_C) { - break; + switch (ev.key) { + termbox.TB_KEY_CTRL_C => break, + termbox.TB_KEY_F7 => { + serializer.serializeWorld() catch err.wat(); + serializer.deserializeWorld() catch err.wat(); + }, + else => {}, } } else if (ev.ch != 0) { switch (ev.ch) { diff --git a/src/mobs.zig b/src/mobs.zig index 869becd4..dbffaa7d 100644 --- a/src/mobs.zig +++ b/src/mobs.zig @@ -54,25 +54,6 @@ pub const templates_test = @import("mobs/templates_test.zig"); // ----------------------------------------------------------------------------- -const NONE_WEAPON = Weapon{ - .id = "", - .name = "blue plastic train", - .damage = 0, - .strs = &[_]DamageStr{ - items._dmgstr(80, "hurl", "hurls", " at kiedtl"), - }, -}; - -const W_SWORD_1 = Weapon{ .damage = 1, .strs = &items.SLASHING_STRS, .name = "sword" }; -const W_SWORD_2 = Weapon{ .damage = 2, .strs = &items.SLASHING_STRS, .name = "sword" }; -const W_KNOUT_3 = Weapon{ .damage = 3, .strs = &items.CRUSHING_STRS, .delay = 200, .name = "knout" }; -const W_BLUDG_1 = Weapon{ .damage = 1, .strs = &items.CRUSHING_STRS, .name = "bludgeon" }; -const W_BLUDG_2 = Weapon{ .damage = 2, .strs = &items.CRUSHING_STRS, .name = "bludgeon" }; -const W_MACES_2 = Weapon{ .damage = 2, .strs = &items.CRUSHING_STRS, .name = "mace" }; -const W_MACES_3 = Weapon{ .damage = 3, .strs = &items.CRUSHING_STRS, .name = "mace" }; -const W_MSWRD_1 = Weapon{ .damage = 1, .strs = &items.SLASHING_STRS, .name = "martial sword", .martial = true }; -const W_SPROD_1 = Weapon{ .damage = 1, .damage_kind = .Electric, .strs = &items.SHOCK_STRS, .name = "shock prod" }; - pub const PLAYER_VISION = 12; pub const RESIST_IMMUNE = 1000; pub const WILL_IMMUNE = 1000; @@ -266,7 +247,7 @@ pub const ExecutionerTemplate = MobTemplate{ .memory_duration = 5, .stats = .{ .Willpower = 2 }, }, - .weapon = &W_KNOUT_3, + .weapon = &items.W_KNOUT_3, }; pub const WatcherTemplate = MobTemplate{ @@ -306,7 +287,7 @@ pub const GuardTemplate = MobTemplate{ .stats = .{ .Willpower = 1 }, }, - .weapon = &W_BLUDG_1, + .weapon = &items.W_BLUDG_1, }; pub const ArmoredGuardTemplate = MobTemplate{ @@ -328,7 +309,7 @@ pub const ArmoredGuardTemplate = MobTemplate{ .stats = .{ .Willpower = 2, .Melee = 70 }, .innate_resists = .{ .Armor = 15 }, }, - .weapon = &W_BLUDG_2, + .weapon = &items.W_BLUDG_2, }; pub fn createEnforcerTemplate(comptime minion: []const u8) MobTemplate { @@ -357,7 +338,7 @@ pub fn createEnforcerTemplate(comptime minion: []const u8) MobTemplate { .stats = .{ .Willpower = 2, .Melee = 70 }, .innate_resists = .{ .Armor = 15, .rElec = 50 }, }, - .weapon = &W_SPROD_1, + .weapon = &items.W_SPROD_1, .squad = &[_][]const MobTemplate.SquadMember{ &[_]MobTemplate.SquadMember{ @@ -396,7 +377,7 @@ pub const JavelineerTemplate = MobTemplate{ .memory_duration = 5, .stats = .{ .Willpower = 2, .Evade = 10, .Missile = 80, .Vision = 5 }, }, - .weapon = &W_BLUDG_2, + .weapon = &items.W_BLUDG_2, .armor = items.GambesonArmor, }; @@ -423,7 +404,7 @@ pub const DefenderTemplate = MobTemplate{ .memory_duration = 6, .stats = .{ .Willpower = 3, .Evade = 10, .Missile = 90 }, }, - .weapon = &W_SWORD_1, + .weapon = &items.W_SWORD_1, .armor = items.HauberkArmor, .projectile = &items.NetProj, }; @@ -556,7 +537,7 @@ pub const PatrolTemplate = MobTemplate{ .memory_duration = 8, .stats = .{ .Willpower = 1 }, }, - .weapon = &W_BLUDG_1, + .weapon = &items.W_BLUDG_1, .squad = &[_][]const MobTemplate.SquadMember{ &[_]MobTemplate.SquadMember{ @@ -818,7 +799,7 @@ pub const KyaniteStatueTemplate = MobTemplate{ .mob = .{ .id = "kyanite_statue", - .species = &Species{ .name = "kyanite statue", .default_attack = &NONE_WEAPON }, + .species = &Species{ .name = "kyanite statue", .default_attack = &items.NONE_WEAPON }, .tile = '☻', .ai = AI{ .profession_description = "gazing", @@ -853,7 +834,7 @@ pub const NebroStatueTemplate = MobTemplate{ .mob = .{ .id = "nebro_statue", - .species = &Species{ .name = "nebro statue", .default_attack = &NONE_WEAPON }, + .species = &Species{ .name = "nebro statue", .default_attack = &items.NONE_WEAPON }, .tile = '☻', .ai = AI{ .profession_description = "gazing", @@ -888,7 +869,7 @@ pub const CrystalStatueTemplate = MobTemplate{ .mob = .{ .id = "crystal_statue", - .species = &Species{ .name = "crystal statue", .default_attack = &NONE_WEAPON }, + .species = &Species{ .name = "crystal statue", .default_attack = &items.NONE_WEAPON }, .tile = '☻', .ai = AI{ .profession_description = "gazing", @@ -1070,7 +1051,7 @@ pub const AncientMageTemplate = MobTemplate{ .innate_resists = .{ .rFume = 100, .rElec = 75 }, .stats = .{ .Willpower = 10, .Evade = 20, .Speed = 150 }, }, - .weapon = &W_MACES_3, + .weapon = &items.W_MACES_3, .armor = items.HauberkArmor, .cloak = &items.SilCloak, }; @@ -1093,7 +1074,7 @@ pub const RecruitTemplate = MobTemplate{ .memory_duration = 6, .stats = .{ .Willpower = 1, .Melee = 80, .Evade = 5, .Vision = 6 }, }, - .weapon = &W_BLUDG_1, + .weapon = &items.W_BLUDG_1, .armor = items.GambesonArmor, }; @@ -1115,7 +1096,7 @@ pub const WarriorTemplate = MobTemplate{ .memory_duration = 6, .stats = .{ .Willpower = 2, .Melee = 90, .Evade = 10, .Vision = 6 }, }, - .weapon = &W_MACES_2, + .weapon = &items.W_MACES_2, .armor = items.CuirassArmor, }; @@ -1137,7 +1118,7 @@ pub const HunterTemplate = MobTemplate{ .memory_duration = 20, .stats = .{ .Willpower = 3, .Melee = 70, .Speed = 150, .Vision = 8 }, }, - .weapon = &W_MACES_2, + .weapon = &items.W_MACES_2, .armor = items.GambesonArmor, .squad = &[_][]const MobTemplate.SquadMember{ @@ -1171,7 +1152,7 @@ pub const BoneMageTemplate = MobTemplate{ .memory_duration = 6, .stats = .{ .Willpower = 4, .Vision = 6, .Melee = 40 }, }, - .weapon = &W_BLUDG_1, + .weapon = &items.W_BLUDG_1, .squad = &[_][]const MobTemplate.SquadMember{ &[_]MobTemplate.SquadMember{ @@ -1199,7 +1180,7 @@ pub const DeathKnightTemplate = MobTemplate{ .innate_resists = .{ .Armor = 25 }, .stats = .{ .Willpower = 6, .Melee = 65, .Martial = 1, .Evade = 10, .Vision = 6 }, }, - .weapon = &W_MSWRD_1, + .weapon = &items.W_MSWRD_1, .squad = &[_][]const MobTemplate.SquadMember{ &[_]MobTemplate.SquadMember{ @@ -1233,7 +1214,7 @@ pub const DeathMageTemplate = MobTemplate{ .memory_duration = 10, .stats = .{ .Willpower = 8, .Evade = 10 }, }, - .weapon = &W_SWORD_2, + .weapon = &items.W_SWORD_2, .armor = items.HauberkArmor, .squad = &[_][]const MobTemplate.SquadMember{ @@ -1270,7 +1251,7 @@ pub const EmberMageTemplate = MobTemplate{ .memory_duration = 6, .stats = .{ .Willpower = 4, .Vision = 6 }, }, - .weapon = &W_BLUDG_1, + .weapon = &items.W_BLUDG_1, .cloak = &items.SilCloak, .squad = &[_][]const MobTemplate.SquadMember{ @@ -1308,7 +1289,7 @@ pub const BrimstoneMageTemplate = MobTemplate{ .memory_duration = 8, .stats = .{ .Willpower = 6, .Evade = 10 }, }, - .weapon = &W_MACES_2, + .weapon = &items.W_MACES_2, .armor = items.HauberkArmor, .cloak = &items.SilCloak, @@ -1344,7 +1325,7 @@ pub const SparkMageTemplate = MobTemplate{ .memory_duration = 6, .stats = .{ .Willpower = 4, .Vision = 6 }, }, - .weapon = &W_BLUDG_1, + .weapon = &items.W_BLUDG_1, .cloak = &items.FurCloak, .squad = &[_][]const MobTemplate.SquadMember{ @@ -1380,7 +1361,7 @@ pub const LightningMageTemplate = MobTemplate{ .memory_duration = 8, .stats = .{ .Willpower = 6, .Evade = 10 }, }, - .weapon = &W_MACES_2, + .weapon = &items.W_MACES_2, .armor = items.HauberkArmor, .cloak = &items.FurCloak, @@ -1680,7 +1661,7 @@ pub const SkeletalBlademasterTemplate = MobTemplate{ .innate_resists = .{ .rFume = 100, .rFire = -25, .Armor = 35 }, .stats = .{ .Willpower = 4, .Melee = 90, .Martial = 2, .Vision = 6 }, }, - .weapon = &W_MSWRD_1, + .weapon = &items.W_MSWRD_1, }; pub const TorturerNecromancerTemplate = MobTemplate{ @@ -1711,7 +1692,7 @@ pub const TorturerNecromancerTemplate = MobTemplate{ .memory_duration = 8, .stats = .{ .Willpower = 8, .Evade = 10 }, }, - .weapon = &W_BLUDG_1, + .weapon = &items.W_BLUDG_1, .armor = items.GambesonArmor, }; diff --git a/src/serializer.zig b/src/serializer.zig index 0c81b4fc..62e72edc 100644 --- a/src/serializer.zig +++ b/src/serializer.zig @@ -19,6 +19,8 @@ const GeneratorCtx = @import("generators.zig").GeneratorCtx; pub const Error = error{ PointerNotFound, MismatchedPointerTypes, CorruptedData, MismatchedType, InvalidUnionField } || std.ArrayList(u8).Writer.Error || std.mem.Allocator.Error || std.fs.File.Reader.Error || std.fs.File.Writer.Error || error{EndOfStream} || microtar.MTar.Error; +const FIELDS_ALWAYS_KEEP_LIST = [_][]const u8{ "__next", "__prev" }; + const STATIC_CONTAINERS = [_]struct { m: []const u8, t: type, @@ -87,13 +89,13 @@ fn _normIntT(comptime Int: type) type { } pub fn write(comptime IntType: type, value: IntType, out: anytype) !void { - std.log.debug("..... => {: <20} {}", .{ _normIntT(IntType), value }); + // std.log.debug("..... => {: <20} {}", .{ _normIntT(IntType), value }); try out.writeIntLittle(_normIntT(IntType), @as(_normIntT(IntType), value)); } pub fn read(comptime IntType: type, in: anytype) !IntType { const value = try in.readIntLittle(_normIntT(IntType)); - std.log.debug("..... <= {: <20} {}", .{ _normIntT(IntType), value }); + // std.log.debug("..... <= {: <20} {}", .{ _normIntT(IntType), value }); return @intCast(IntType, value); } @@ -187,7 +189,7 @@ pub fn serialize(comptime T: type, obj: T, out: anytype) Error!void { if (mem.eql(u8, item, field.name)) break true; } else false; if (!noser_field) { - std.log.debug("Ser {s: <20} ({s})", .{ field.name, @typeName(field.field_type) }); + // std.log.debug("Ser {s: <20} ({s})", .{ field.name, @typeName(field.field_type) }); try serialize(usize, _typeId(field.field_type), out); if (@hasDecl(T, "__SER_FIELDW_" ++ field.name)) { @@ -274,8 +276,18 @@ pub fn deserialize(comptime T: type, out: *T, in: anytype, alloc: mem.Allocator) *@TypeOf(@field(state, declinfo.name)).ChildType == T) { if (mem.eql(u8, declinfo.name, ptrdata.container)) { - out.* = @field(state, declinfo.name).nth(ptrdata.index).?; - return; + if (@field(state, declinfo.name).nth(ptrdata.index)) |d| { + out.* = d; + return; + } else { + std.log.err("Pointer {s},{s},{} not in container (len: {})", .{ + ptrdata.container, + ptrdata.ptrtype, + ptrdata.index, + @field(state, declinfo.name).len(), + }); + return error.PointerNotFound; + } } }; @@ -307,6 +319,8 @@ pub fn deserialize(comptime T: type, out: *T, in: anytype, alloc: mem.Allocator) if (comptime std.meta.trait.hasFn("deserialize")(T)) { try T.deserialize(out, in, alloc); } else { + const oldobj = out.*; + if (@hasDecl(T, "__SER_GET_PROTO")) { comptime assert(@hasDecl(T, "__SER_GET_ID")); const id = try deserializeQ([]const u8, in, alloc); @@ -320,11 +334,15 @@ pub fn deserialize(comptime T: type, out: *T, in: anytype, alloc: mem.Allocator) @setEvalBranchQuota(9999); if (mem.eql(u8, item, field.name)) break true; } else false; + const keep_field = comptime for (FIELDS_ALWAYS_KEEP_LIST) |item| { + @setEvalBranchQuota(9999); + if (mem.eql(u8, item, field.name)) break true; + } else false; if (!noser_field) { - std.log.debug("Deser {s: <20} ({s})", .{ - field.name, - @typeName(field.field_type), - }); + // std.log.debug("Deser {s: <20} ({s})", .{ + // field.name, + // @typeName(field.field_type), + // }); try deserializeExpect(field.field_type, in, alloc); @@ -335,27 +353,29 @@ pub fn deserialize(comptime T: type, out: *T, in: anytype, alloc: mem.Allocator) try deserialize(field.field_type, &@field(out, field.name), in, alloc); } - switch (@typeInfo(field.field_type)) { - .Pointer => if (field.field_type == []const u8) std.log.debug("Deser value: {s}", .{@field(out, field.name)}) else std.log.debug("Deser value: skip", .{}), - .Array => std.log.debug("Deser value: {any}", .{@field(out, field.name)}), - .Bool, .Enum, .Int, .Float => { - std.log.debug("Deser value: {}", .{@field(out, field.name)}); - }, - else => { - if (field.field_type == ?[]const u8) { - if (@field(out, field.name)) |v| - std.log.debug("Deser value: {s}", .{v}) - else - std.log.debug("Deser value: null", .{}); - } else if (field.field_type == ?types.Damage or - field.field_type == ?types.Direction) - { - std.log.debug("Deser value: {}", .{@field(out, field.name)}); - } else { - std.log.debug("Deser value: skip", .{}); - } - }, - } + // switch (@typeInfo(field.field_type)) { + // .Pointer => if (field.field_type == []const u8) std.log.debug("Deser value: {s}", .{@field(out, field.name)}) else std.log.debug("Deser value: skip", .{}), + // .Array => std.log.debug("Deser value: {any}", .{@field(out, field.name)}), + // .Bool, .Enum, .Int, .Float => { + // std.log.debug("Deser value: {}", .{@field(out, field.name)}); + // }, + // else => { + // if (field.field_type == ?[]const u8) { + // if (@field(out, field.name)) |v| + // std.log.debug("Deser value: {s}", .{v}) + // else + // std.log.debug("Deser value: null", .{}); + // } else if (field.field_type == ?types.Damage or + // field.field_type == ?types.Direction) + // { + // std.log.debug("Deser value: {}", .{@field(out, field.name)}); + // } else { + // std.log.debug("Deser value: skip", .{}); + // } + // }, + // } + } else if (keep_field) { + @field(out, field.name) = @field(oldobj, field.name); } } } @@ -458,6 +478,7 @@ pub fn initPointerContainers() void { if (mem.eql(u8, declinfo.name, ptrinit.container)) { const container = &@field(state, declinfo.name); var i: usize = ptrinit.init_up_to -| container.len(); + std.log.info("initing {s} ({s}), up to {} ({})", .{ ptrinit.container, declinfo.name, ptrinit.init_up_to, i }); while (i > 0) : (i -= 1) { container.append(undefined) catch err.wat(); } @@ -488,6 +509,7 @@ pub fn serializeWorld() !void { try serializeWE(@TypeOf(ptrinits), ptrinits, f.writer()); try serializeWE(@TypeOf(state.mobs), state.mobs, f.writer()); + // try serializeWE(types.Mob, state.player.*, f.writer()); } pub fn deserializeWorld() !void { @@ -504,4 +526,5 @@ pub fn deserializeWorld() !void { initPointerContainers(); try deserializeWE(@TypeOf(state.mobs), &state.mobs, f.reader(), alloc); + // try deserializeWE(types.Mob, state.player, f.reader(), alloc); }