예제 #1
0
        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();
                }
            }
        }
예제 #2
0
        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)");
        }