public static bool Check(Item item) => item?.GetType().IsDefined(typeof(FurnitureAttribute), false) == true;
Beispiel #2
0
        public static void Load()
        {
            if (m_Loaded)
            {
                return;
            }

            m_Loaded      = true;
            m_LoadingType = null;

            Console.Write("World: Loading...");

            Stopwatch watch = Stopwatch.StartNew();

            m_Loading = true;

            _addQueue    = new Queue <IEntity>();
            _deleteQueue = new Queue <IEntity>();

            int mobileCount = 0, itemCount = 0, guildCount = 0;

            object[] ctorArgs = new object[1];

            List <ItemEntry>   items   = new List <ItemEntry>();
            List <MobileEntry> mobiles = new List <MobileEntry>();
            List <GuildEntry>  guilds  = new List <GuildEntry>();

            if (File.Exists(MobileIndexPath) && File.Exists(MobileTypesPath))
            {
                using (FileStream idx = new FileStream(MobileIndexPath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                    BinaryReader idxReader = new BinaryReader(idx);

                    using (FileStream tdb = new FileStream(MobileTypesPath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                        BinaryReader tdbReader = new BinaryReader(tdb);

                        List <Tuple <ConstructorInfo, string> > types = ReadTypes(tdbReader);

                        mobileCount = idxReader.ReadInt32();

                        m_Mobiles = new Dictionary <Serial, Mobile>(mobileCount);

                        for (int i = 0; i < mobileCount; ++i)
                        {
                            int  typeID = idxReader.ReadInt32();
                            int  serial = idxReader.ReadInt32();
                            long pos    = idxReader.ReadInt64();
                            int  length = idxReader.ReadInt32();

                            Tuple <ConstructorInfo, string> objs = types[typeID];

                            if (objs == null)
                            {
                                continue;
                            }

                            Mobile          m        = null;
                            ConstructorInfo ctor     = objs.Item1;
                            string          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);
                            }
                        }

                        tdbReader.Close();
                    }

                    idxReader.Close();
                }
            }
            else
            {
                m_Mobiles = new Dictionary <Serial, Mobile>();
            }

            if (File.Exists(ItemIndexPath) && File.Exists(ItemTypesPath))
            {
                using (FileStream idx = new FileStream(ItemIndexPath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                    BinaryReader idxReader = new BinaryReader(idx);

                    using (FileStream tdb = new FileStream(ItemTypesPath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                        BinaryReader tdbReader = new BinaryReader(tdb);

                        List <Tuple <ConstructorInfo, string> > types = ReadTypes(tdbReader);

                        itemCount = idxReader.ReadInt32();

                        m_Items = new Dictionary <Serial, Item>(itemCount);

                        for (int i = 0; i < itemCount; ++i)
                        {
                            int  typeID = idxReader.ReadInt32();
                            int  serial = idxReader.ReadInt32();
                            long pos    = idxReader.ReadInt64();
                            int  length = idxReader.ReadInt32();

                            Tuple <ConstructorInfo, string> objs = types[typeID];

                            if (objs == null)
                            {
                                continue;
                            }

                            Item            item     = null;
                            ConstructorInfo ctor     = objs.Item1;
                            string          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);
                            }
                        }

                        tdbReader.Close();
                    }

                    idxReader.Close();
                }
            }
            else
            {
                m_Items = new Dictionary <Serial, Item>();
            }

            if (File.Exists(GuildIndexPath))
            {
                using (FileStream idx = new FileStream(GuildIndexPath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                    BinaryReader idxReader = new BinaryReader(idx);

                    guildCount = idxReader.ReadInt32();

                    CreateGuildEventArgs createEventArgs = new CreateGuildEventArgs(-1);
                    for (int i = 0; i < guildCount; ++i)
                    {
                        idxReader.ReadInt32();                        //no typeid for guilds
                        int  id     = idxReader.ReadInt32();
                        long pos    = idxReader.ReadInt64();
                        int  length = idxReader.ReadInt32();

                        createEventArgs.Id = id;
                        EventSink.InvokeCreateGuild(createEventArgs);
                        BaseGuild guild = createEventArgs.Guild;
                        if (guild != null)
                        {
                            guilds.Add(new GuildEntry(guild, pos, length));
                        }
                    }

                    idxReader.Close();
                }
            }

            bool      failedMobiles = false, failedItems = false, failedGuilds = false;
            Type      failedType   = null;
            Serial    failedSerial = Serial.Zero;
            Exception failed       = null;
            int       failedTypeID = 0;

            if (File.Exists(MobileDataPath))
            {
                using (FileStream bin = new FileStream(MobileDataPath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                    BinaryFileReader reader = new BinaryFileReader(new BinaryReader(bin));

                    for (int i = 0; i < mobiles.Count; ++i)
                    {
                        MobileEntry entry = mobiles[i];
                        Mobile      m     = entry.Mobile;

                        if (m != null)
                        {
                            reader.Seek(entry.Position, SeekOrigin.Begin);

                            try {
                                m_LoadingType = entry.TypeName;
                                m.Deserialize(reader);

                                if (reader.Position != (entry.Position + entry.Length))
                                {
                                    throw new Exception(String.Format("***** Bad serialize on {0} *****", m.GetType()));
                                }
                            } catch (Exception e) {
                                mobiles.RemoveAt(i);

                                failed        = e;
                                failedMobiles = true;
                                failedType    = m.GetType();
                                failedTypeID  = entry.TypeID;
                                failedSerial  = m.Serial;

                                break;
                            }
                        }
                    }

                    reader.Close();
                }
            }

            if (!failedMobiles && File.Exists(ItemDataPath))
            {
                using (FileStream bin = new FileStream(ItemDataPath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                    BinaryFileReader reader = new BinaryFileReader(new BinaryReader(bin));

                    for (int i = 0; i < items.Count; ++i)
                    {
                        ItemEntry entry = items[i];
                        Item      item  = entry.Item;

                        if (item != null)
                        {
                            reader.Seek(entry.Position, SeekOrigin.Begin);

                            try {
                                m_LoadingType = entry.TypeName;
                                item.Deserialize(reader);

                                if (reader.Position != (entry.Position + entry.Length))
                                {
                                    throw new Exception(String.Format("***** Bad serialize on {0} *****", item.GetType()));
                                }
                            } catch (Exception e) {
                                items.RemoveAt(i);

                                failed       = e;
                                failedItems  = true;
                                failedType   = item.GetType();
                                failedTypeID = entry.TypeID;
                                failedSerial = item.Serial;

                                break;
                            }
                        }
                    }

                    reader.Close();
                }
            }

            m_LoadingType = null;

            if (!failedMobiles && !failedItems && File.Exists(GuildDataPath))
            {
                using (FileStream bin = new FileStream(GuildDataPath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                    BinaryFileReader reader = new BinaryFileReader(new BinaryReader(bin));

                    for (int i = 0; i < guilds.Count; ++i)
                    {
                        GuildEntry entry = guilds[i];
                        BaseGuild  g     = entry.Guild;

                        if (g != null)
                        {
                            reader.Seek(entry.Position, SeekOrigin.Begin);

                            try {
                                g.Deserialize(reader);

                                if (reader.Position != (entry.Position + entry.Length))
                                {
                                    throw new Exception(String.Format("***** Bad serialize on Guild {0} *****", g.Id));
                                }
                            } catch (Exception e) {
                                guilds.RemoveAt(i);

                                failed       = e;
                                failedGuilds = true;
                                failedType   = typeof(BaseGuild);
                                failedTypeID = g.Id;
                                failedSerial = g.Id;

                                break;
                            }
                        }
                    }

                    reader.Close();
                }
            }

            if (failedItems || failedMobiles || failedGuilds)
            {
                Console.WriteLine("An error was encountered while loading a saved object");

                Console.WriteLine(" - Type: {0}", failedType);
                Console.WriteLine(" - Serial: {0}", 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 (int i = 0; i < mobiles.Count;)
                                    {
                                        if (mobiles[i].TypeID == failedTypeID)
                                        {
                                            mobiles.RemoveAt(i);
                                        }
                                        else
                                        {
                                            ++i;
                                        }
                                    }
                                }
                                else if (failedItems)
                                {
                                    for (int i = 0; i < items.Count;)
                                    {
                                        if (items[i].TypeID == failedTypeID)
                                        {
                                            items.RemoveAt(i);
                                        }
                                        else
                                        {
                                            ++i;
                                        }
                                    }
                                }
                            }
                        }

                        SaveIndex <MobileEntry>(mobiles, MobileIndexPath);
                        SaveIndex <ItemEntry>(items, ItemIndexPath);
                        SaveIndex <GuildEntry>(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(String.Format("Load failed (items={0}, mobiles={1}, guilds={2}, type={3}, serial={4})", failedItems, failedMobiles, failedGuilds, failedType, failedSerial), failed);
            }

            EventSink.InvokeWorldLoad();

            m_Loading = false;

            ProcessSafetyQueues();

            foreach (Item item in m_Items.Values)
            {
                if (item.Parent == null)
                {
                    item.UpdateTotals();
                }

                item.ClearProperties();
            }

            foreach (Mobile m in m_Mobiles.Values)
            {
                m.UpdateRegion();                 // Is this really needed?
                m.UpdateTotals();

                m.ClearProperties();
            }

            watch.Stop();

            Console.WriteLine("done ({1} items, {2} mobiles) ({0:F2} seconds)", watch.Elapsed.TotalSeconds, m_Items.Count, m_Mobiles.Count);
        }