public static TeleportEvent Serdes(TeleportEvent e, AssetMapping mapping, ISerializer s) { if (s == null) { throw new ArgumentNullException(nameof(s)); } e ??= new TeleportEvent(); e.X = s.UInt8(nameof(X), e.X); e.Y = s.UInt8(nameof(Y), e.Y); e.Direction = s.EnumU8(nameof(Direction), e.Direction); e.Unk4 = s.UInt8(nameof(Unk4), e.Unk4); e.Unk5 = s.UInt8(nameof(Unk5), e.Unk5); e.MapId = MapId.SerdesU16(nameof(MapId), e.MapId, mapping, s); int zeroed = s.UInt16(null, 0); s.Assert(e.Unk4 == 0 || e.Unk4 == 1 || e.Unk4 == 2 || e.Unk4 == 3 || e.Unk4 == 6 || e.Unk4 == 106 || e.Unk4 == 255, "TeleportEvent: Expected field 4 to be in { 0,1,2,3,6,106,255 }"); // Always 255 in maps s.Assert(zeroed == 0, "TeleportEvent: Expected field 8 to be 0"); return(e); }
public static CloneAutomapEvent Serdes(CloneAutomapEvent e, AssetMapping mapping, ISerializer s) { if (s == null) { throw new ArgumentNullException(nameof(s)); } e ??= new CloneAutomapEvent(); int zeroes = s.UInt8(null, 0); zeroes += s.UInt8(null, 0); zeroes += s.UInt8(null, 0); zeroes += s.UInt8(null, 0); zeroes += s.UInt8(null, 0); s.Assert(zeroes == 0, "CloneAutomap: Expected fields 1-5 to be 0"); e.From = MapId.SerdesU16(nameof(From), e.From, mapping, s); e.To = MapId.SerdesU16(nameof(To), e.To, mapping, s); return(e); }
public static ChangeIconEvent Serdes(ChangeIconEvent e, AssetMapping mapping, ISerializer s) { if (s == null) { throw new ArgumentNullException(nameof(s)); } e ??= new ChangeIconEvent(); e.X = s.Int8(nameof(X), unchecked ((sbyte)e.X)); // 1 e.Y = s.Int8(nameof(Y), unchecked ((sbyte)e.Y)); // 2 e.Scope = s.EnumU8(nameof(Scope), e.Scope); // 3 e.ChangeType = s.EnumU8(nameof(ChangeType), e.ChangeType); // 4 e.Layers = s.EnumU8(nameof(Layers), e.Layers); // 5 e.Value = s.UInt16(nameof(Value), e.Value); // 6 e.MapId = MapId.SerdesU16(nameof(MapId), e.MapId, mapping, s); // 8 if (e.Scope is EventScope.AbsPerm or EventScope.AbsTemp) { e.X = unchecked ((byte)e.X); e.Y = unchecked ((byte)e.Y); } return(e); }
public static TeleportEvent Serdes(TeleportEvent e, AssetMapping mapping, ISerializer s) { if (s == null) { throw new ArgumentNullException(nameof(s)); } e ??= new TeleportEvent(); e.X = s.UInt8(nameof(X), e.X); e.Y = s.UInt8(nameof(Y), e.Y); e.Direction = s.EnumU8(nameof(Direction), e.Direction); e.Unk4 = s.UInt8(nameof(Unk4), e.Unk4); e.Unk5 = s.UInt8(nameof(Unk5), e.Unk5); e.MapId = MapId.SerdesU16(nameof(MapId), e.MapId, mapping, s); e.Unk8 = s.UInt16(nameof(Unk8), e.Unk8); ApiUtil.Assert(e.Unk4 == 0 || e.Unk4 == 1 || e.Unk4 == 2 || e.Unk4 == 3 || e.Unk4 == 6 || e.Unk4 == 106 || e.Unk4 == 255); // Always 255 in maps ApiUtil.Assert(e.Unk8 == 0); return(e); }
public static SavedGame Serdes(SavedGame save, AssetMapping mapping, ISerializer s) { if (s == null) { throw new ArgumentNullException(nameof(s)); } save ??= new SavedGame(); ushort nameLength = s.UInt16("NameLength", (ushort)(save.Name?.Length ?? 0)); save.Unk0 = s.UInt16(nameof(Unk0), save.Unk0); save.Name = s.FixedLengthString(nameof(Name), save.Name, nameLength); save.Unk1 = s.UInt32(nameof(Unk1), save.Unk1); var versionOffset = s.Offset; save.Version = s.UInt16(nameof(Version), save.Version); // 0 ApiUtil.Assert(save.Version == 138); // TODO: Throw error for other versions? save.Unk9 = s.ByteArray(nameof(Unk9), save.Unk9, 6); // 2 ushort days = s.UInt16("Days", (ushort)save.ElapsedTime.TotalDays); // 8 ushort hours = s.UInt16("Hours", (ushort)save.ElapsedTime.Hours); // A ushort minutes = s.UInt16("Minutes", (ushort)save.ElapsedTime.Minutes); // C save.ElapsedTime = new TimeSpan(days, hours, minutes, save.ElapsedTime.Seconds, save.ElapsedTime.Milliseconds); save.MapId = MapId.SerdesU16(nameof(MapId), save.MapId, mapping, s); // E save.PartyX = s.UInt16(nameof(PartyX), save.PartyX); // 10 save.PartyY = s.UInt16(nameof(PartyY), save.PartyY); // 12 save.PartyDirection = s.EnumU16(nameof(PartyDirection), save.PartyDirection); // 14 save.Unknown16 = s.ByteArrayHex(nameof(Unknown16), save.Unknown16, 0x184); // 16 save.ActiveMembers = s.List( nameof(ActiveMembers), save.ActiveMembers, MaxPartySize, (i, x, s2) => { var value = PartyMemberId.SerdesU8(null, save.ActiveMembers[i], mapping, s); s2.UInt8("dummy", 0); return(value); }); save.Misc = s.Object(nameof(Misc), save.Misc, MiscState.Serdes); // 1A6 save._switches.SetPacked(0, s.ByteArrayHex("Switches", save._switches.GetPacked(0, FlagDictionary.OriginalSaveGameMax, mapping), FlagDictionary.PackedSize(0, FlagDictionary.OriginalSaveGameMax)), mapping); // 276 save.Unknown2C1 = s.ByteArrayHex(nameof(Unknown2C1), save.Unknown2C1, 0x5833); // 0x2C1 s.Object(nameof(Tickers), save._tickers, TickerDictionary.Serdes); // 5AF4 save.Unknown5B9F = s.ByteArrayHex(nameof(Unknown5B9F), save.Unknown5B9F, 0x2C); var mapType = MapType.TwoD; s.List(nameof(save.Npcs), save.Npcs, (mapType, mapping), MaxNpcCount, NpcState.Serdes); save.Unknown5B71 = s.ByteArrayHex( nameof(Unknown5B71), save.Unknown5B71, (int)(0x947C + versionOffset - s.Offset)); // 5B9F uint permChangesSize = s.UInt32("PermanentMapChanges_Size", (uint)(save.PermanentMapChanges.Count * MapChange.SizeOnDisk + 2)); ushort permChangesCount = s.UInt16("PermanentMapChanges_Count", (ushort)save.PermanentMapChanges.Count); ApiUtil.Assert(permChangesSize == permChangesCount * MapChange.SizeOnDisk + 2); save.PermanentMapChanges = (MapChangeCollection)s.List( nameof(PermanentMapChanges), save.PermanentMapChanges, mapping, permChangesCount, MapChange.Serdes, _ => new MapChangeCollection()); uint tempChangesSize = s.UInt32("TemporaryMapChanges_Size", (uint)(save.TemporaryMapChanges.Count * MapChange.SizeOnDisk + 2)); ushort tempChangesCount = s.UInt16("TemporaryMapChanges_Count", (ushort)save.TemporaryMapChanges.Count); ApiUtil.Assert(tempChangesSize == tempChangesCount * MapChange.SizeOnDisk + 2); save.TemporaryMapChanges = (MapChangeCollection)s.List( nameof(TemporaryMapChanges), save.TemporaryMapChanges, mapping, tempChangesCount, MapChange.Serdes, _ => new MapChangeCollection()); uint visitedEventsSize = s.UInt32("VisitedEvents_Size", (uint)(save.VisitedEvents.Count * VisitedEvent.SizeOnDisk + 2)); ushort visitedEventsCount = s.UInt16("VisitedEvents_Count", (ushort)save.VisitedEvents.Count); ApiUtil.Assert(visitedEventsSize == visitedEventsCount * VisitedEvent.SizeOnDisk + 2); save.VisitedEvents = s.List(nameof(VisitedEvents), save.VisitedEvents, mapping, visitedEventsCount, VisitedEvent.Serdes); var partyIds = save.Sheets.Keys.Select(x => x.Id).ToList(); partyIds.Add(199); // Force extra XLD length fields to be written for empty objects to preserve compat with original game. partyIds.Add(299); // s.Object($"XldPartyCharacter.0"); XldContainerLoader.Serdes(XldCategory.PartyCharacter, 0, (save, mapping), s, SerdesPartyCharacter, partyIds); XldContainerLoader.Serdes(XldCategory.PartyCharacter, 1, (save, mapping), s, SerdesPartyCharacter, partyIds); XldContainerLoader.Serdes(XldCategory.PartyCharacter, 2, (save, mapping), s, SerdesPartyCharacter, partyIds); var automapIds = save.Automaps.Keys.Select(x => x.Id).ToList(); // TODO: Allow extension somehow automapIds.Add(199); automapIds.Add(399); XldContainerLoader.Serdes(XldCategory.Automap, 1, (save, mapping), s, SerdesAutomap, automapIds); XldContainerLoader.Serdes(XldCategory.Automap, 2, (save, mapping), s, SerdesAutomap, automapIds); XldContainerLoader.Serdes(XldCategory.Automap, 3, (save, mapping), s, SerdesAutomap, automapIds); var chestIds = save.Inventories.Keys.Select(x => x.Id).ToList(); // TODO: Allow extension somehow chestIds.Add(199); chestIds.Add(599); XldContainerLoader.Serdes(XldCategory.Chest, 0, (save, mapping), s, SerdesChest, chestIds); XldContainerLoader.Serdes(XldCategory.Chest, 1, (save, mapping), s, SerdesChest, chestIds); XldContainerLoader.Serdes(XldCategory.Chest, 2, (save, mapping), s, SerdesChest, chestIds); XldContainerLoader.Serdes(XldCategory.Chest, 5, (save, mapping), s, SerdesChest, chestIds); var merchantIds = save.Inventories.Keys.Select(x => x.Id).ToList(); // TODO: Allow extension somehow merchantIds.Add(199); merchantIds.Add(299); XldContainerLoader.Serdes(XldCategory.Merchant, 0, (save, mapping), s, SerdesMerchant, merchantIds); XldContainerLoader.Serdes(XldCategory.Merchant, 1, (save, mapping), s, SerdesMerchant, merchantIds); XldContainerLoader.Serdes(XldCategory.Merchant, 2, (save, mapping), s, SerdesMerchant, merchantIds); var npcIds = save.Sheets.Keys.Select(x => x.Id).ToList(); // TODO: Allow extension somehow npcIds.Add(299); XldContainerLoader.Serdes(XldCategory.NpcCharacter, 0, (save, mapping), s, SerdesNpcCharacter, npcIds); XldContainerLoader.Serdes(XldCategory.NpcCharacter, 1, (save, mapping), s, SerdesNpcCharacter, npcIds); XldContainerLoader.Serdes(XldCategory.NpcCharacter, 2, (save, mapping), s, SerdesNpcCharacter, npcIds); s.RepeatU8("Padding", 0, 4); // TODO: Save additional sheets & inventories from mods. return(save); }