public static void Deserialize(FileInfo file, Action <GenericReader> deserializer, bool ensure) { file.Refresh(); if (file.Directory != null && !file.Directory.Exists) { if (!ensure) { throw new DirectoryNotFoundException(); } file.Directory.Create(); } if (!file.Exists) { if (!ensure) { throw new FileNotFoundException { Source = file.FullName }; } file.Create().Close(); } file.Refresh(); using (var fs = file.OpenRead()) { var reader = new BinaryFileReader(new BinaryReader(fs)); try { deserializer(reader); } catch (EndOfStreamException eos) { if (file.Length > 0) { Console.WriteLine("[Persistence]: {0}", eos); } } catch (Exception e) { Console.WriteLine("[Persistence]: {0}", e); } finally { reader.Close(); } } }
public static void Load() { if (Loaded) { return; } Loaded = true; LoadingType = null; Console.Write("World: Loading..."); var watch = Stopwatch.StartNew(); Loading = true; _addQueue = new Queue <IEntity>(); _deleteQueue = new Queue <IEntity>(); var ctorArgs = new object[1]; // MOBILE var mobiles = new List <MobileEntry>(); if (File.Exists(MobileIndexPath) && File.Exists(MobileTypesPath)) { using (var idx = new FileStream(MobileIndexPath, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var idxR = new BinaryReader(idx)) using (var tdb = new FileStream(MobileTypesPath, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var tdbR = new BinaryReader(tdb)) { var types = ReadTypes(tdbR); var mobileCount = idxR.ReadInt32(); Mobiles = new Dictionary <Serial, Mobile>(mobileCount); for (var i = 0; i < mobileCount; ++i) { var typeID = idxR.ReadInt32(); var serial = idxR.ReadInt32(); var pos = idxR.ReadInt64(); var length = idxR.ReadInt32(); var objs = types[typeID]; if (objs == null) { continue; } Mobile m = null; var ctor = objs.Item1; var typeName = objs.Item2; try { ctorArgs[0] = (Serial)serial; m = (Mobile)(ctor.Invoke(ctorArgs)); } catch { } if (m != null) { mobiles.Add(new MobileEntry(m, typeID, typeName, pos, length)); AddMobile(m); } } } } else { Mobiles = new Dictionary <Serial, Mobile>(); } // ITEM var items = new List <ItemEntry>(); if (File.Exists(ItemIndexPath) && File.Exists(ItemTypesPath)) { using (var idx = new FileStream(ItemIndexPath, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var idxR = new BinaryReader(idx)) using (var tdb = new FileStream(ItemTypesPath, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var tdbR = new BinaryReader(tdb)) { var types = ReadTypes(tdbR); var itemCount = idxR.ReadInt32(); Items = new Dictionary <Serial, Item>(itemCount); for (var i = 0; i < itemCount; ++i) { var typeID = idxR.ReadInt32(); var serial = idxR.ReadInt32(); var pos = idxR.ReadInt64(); var length = idxR.ReadInt32(); var objs = types[typeID]; if (objs == null) { continue; } Item item = null; var ctor = objs.Item1; var typeName = objs.Item2; try { ctorArgs[0] = (Serial)serial; item = (Item)(ctor.Invoke(ctorArgs)); } catch { } if (item != null) { items.Add(new ItemEntry(item, typeID, typeName, pos, length)); AddItem(item); } } } } else { Items = new Dictionary <Serial, Item>(); } // GUILD var guilds = new List <GuildEntry>(); if (File.Exists(GuildIndexPath)) { using (var idx = new FileStream(GuildIndexPath, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var idxReader = new BinaryReader(idx)) { var guildCount = idxReader.ReadInt32(); var createEventArgs = new CreateGuildEventArgs(-1); for (var i = 0; i < guildCount; ++i) { idxReader.ReadInt32(); // no typeid for guilds var id = idxReader.ReadInt32(); var pos = idxReader.ReadInt64(); var length = idxReader.ReadInt32(); createEventArgs.Id = id; EventSink.InvokeCreateGuild(createEventArgs); var guild = createEventArgs.Guild; if (guild != null) { guilds.Add(new GuildEntry(guild, pos, length)); } } } } // bool failedMobiles = false, failedItems = false, failedGuilds = false; Type failedType = null; var failedSerial = Serial.Zero; Exception failed = null; var failedTypeID = 0; // MOBILE DATA if (File.Exists(MobileDataPath)) { using (var fs = new FileStream(MobileDataPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { var r = new BinaryFileReader(new BinaryReader(fs)); for (var i = 0; i < mobiles.Count; ++i) { var entry = mobiles[i]; var m = entry.Mobile; if (m != null) { r.Seek(entry.Position, SeekOrigin.Begin); try { LoadingType = entry.TypeName; m.Deserialize(r); if (r.Position != (entry.Position + entry.Length)) { throw new Exception($"***** Bad serialize on {m.GetType()} *****"); } } catch (Exception e) { mobiles.RemoveAt(i); failed = e; failedMobiles = true; failedType = m.GetType(); failedTypeID = entry.TypeID; failedSerial = m.Serial; break; } } } r.Close(); } } // ITEM DATA if (!failedMobiles && File.Exists(ItemDataPath)) { using (var fs = new FileStream(ItemDataPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { var r = new BinaryFileReader(new BinaryReader(fs)); for (var i = 0; i < items.Count; ++i) { var entry = items[i]; var item = entry.Item; if (item != null) { r.Seek(entry.Position, SeekOrigin.Begin); try { LoadingType = entry.TypeName; item.Deserialize(r); if (r.Position != (entry.Position + entry.Length)) { throw new Exception($"***** Bad serialize on {item.GetType()} *****"); } } catch (Exception e) { items.RemoveAt(i); failed = e; failedItems = true; failedType = item.GetType(); failedTypeID = entry.TypeID; failedSerial = item.Serial; break; } } } r.Close(); } } LoadingType = null; // GUILD DATA if (!failedMobiles && !failedItems && File.Exists(GuildDataPath)) { using (var fs = new FileStream(GuildDataPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { var r = new BinaryFileReader(new BinaryReader(fs)); for (var i = 0; i < guilds.Count; ++i) { var entry = guilds[i]; var g = entry.Guild; if (g != null) { r.Seek(entry.Position, SeekOrigin.Begin); try { g.Deserialize(r); if (r.Position != (entry.Position + entry.Length)) { throw new Exception("***** Bad serialize on Guild {g.Id} *****"); } } catch (Exception e) { guilds.RemoveAt(i); failed = e; failedGuilds = true; failedType = typeof(BaseGuild); failedTypeID = g.Id; failedSerial = g.Id; break; } } } r.Close(); } } if (failedItems || failedMobiles || failedGuilds) { Console.WriteLine("An error was encountered while loading a saved object"); Console.WriteLine($" - Type: {failedType}"); Console.WriteLine($" - Serial: {failedSerial}"); if (!Core.Service) { Console.WriteLine("Delete the object? (y/n)"); if (Console.ReadKey(true).Key == ConsoleKey.Y) { if (failedType != typeof(BaseGuild)) { Console.WriteLine("Delete all objects of that type? (y/n)"); if (Console.ReadKey(true).Key == ConsoleKey.Y) { if (failedMobiles) { for (var i = 0; i < mobiles.Count;) { if (mobiles[i].TypeID == failedTypeID) { mobiles.RemoveAt(i); } else { ++i; } } } else if (failedItems) { for (var i = 0; i < items.Count;) { if (items[i].TypeID == failedTypeID) { items.RemoveAt(i); } else { ++i; } } } } } SaveIndex(mobiles, MobileIndexPath); SaveIndex(items, ItemIndexPath); SaveIndex(guilds, GuildIndexPath); } Console.WriteLine("After pressing return an exception will be thrown and the server will terminate."); Console.ReadLine(); } else { Console.WriteLine("An exception will be thrown and the server will terminate."); } throw new Exception($"Load failed (items={failedItems}, mobiles={failedMobiles}, guilds={failedGuilds}, type={failedType}, serial={failedSerial})", failed); } EventSink.InvokeWorldLoad(); Loading = false; ProcessSafetyQueues(); foreach (var item in Items.Values) { if (item.Parent == null) { item.UpdateTotals(); } item.ClearProperties(); } foreach (var m in Mobiles.Values) { m.UpdateRegion(); // Is this really needed? m.UpdateTotals(); m.ClearProperties(); } watch.Stop(); Console.WriteLine($"done ({watch.Elapsed.TotalSeconds} items, {Items.Count} mobiles) ({Mobiles.Count:F2} seconds)"); }