Esempio n. 1
0
        public static void RestoreState(
            PlayerMobile m,
            Serial serial,
            bool moveExisting,
            bool logging,
            out int created,
            out int deleted,
            out int ignored,
            out int moved)
        {
            var pack = m.Backpack;

            if (pack == null || pack.Deleted)
            {
                m.AddItem(
                    pack = new Backpack
                {
                    Movable = false
                });
            }

            var bank = m.BankBox;

            if (bank == null || bank.Deleted)
            {
                m.AddItem(
                    bank = new BankBox(m)
                {
                    Movable = false
                });
            }

            if (serial == Serial.MinusOne)
            {
                serial = m.Serial;
            }

            var root = VitaNexCore.DataDirectory + "/PlayerBackup/" + m.Account.Username + "/" + serial;

            var idxFile = IOUtility.EnsureFile(root + ".idx");
            var binFile = IOUtility.EnsureFile(root + ".bin");

            var logFile = logging ? IOUtility.EnsureFile(root + ".log") : null;
            var log     = logging ? new StringBuilder() : null;

            if (log != null)
            {
                log.AppendLine();
                log.AppendLine(new String('*', 10));
                log.AppendLine();
                log.AppendLine("RESTORE:\tDate[{0}]\tMobile[{1}]", DateTime.UtcNow, m);
                log.AppendLine();
            }

            int idxCreated = 0, idxDeleted = 0, idxIgnored = 0, idxMoved = 0;

            idxFile.Deserialize(
                idx =>
            {
                idx.GetVersion();

                var ser = idx.ReadInt();

                if (ser != m.Serial.Value)
                {
                    if (log != null)
                    {
                        log.AppendLine("INVALID:\tSerial[{0:X8}]", ser);
                    }

                    return;
                }

                long idxLength;
                int idxCount;

                ReadLength(idx, false, out idxLength, out idxCount);

                if (log != null)
                {
                    log.AppendLine("INDEX:\tCount[{0}]\tLength[{1}]", idxCount, idxLength);
                }

                var items = new Tuple <Item, Serial, long, long, string> [idxCount];

                binFile.Deserialize(
                    bin =>
                {
                    bin.GetVersion();

                    var restored = new Dictionary <Item, Serial>();

                    Backpack oldPack = null;
                    BankBox oldBank  = null;

                    for (var i = 0; i < idxCount; i++)
                    {
                        Type type;
                        Serial s, parent;
                        long binIndex, binLength;

                        ReadIndex(idx, out type, out s, out parent, out binIndex, out binLength);

                        var valid  = s.IsValid && s.IsItem;
                        var exists = World.Items.ContainsKey(s);

                        Item item = null;

                        if (exists)
                        {
                            item = World.Items[s];

                            if (item == null || item.Deleted)
                            {
                                World.Items.Remove(s);
                                exists = false;
                            }
                        }

                        object logItem;
                        string status;

                        if (!exists && valid && type.IsEqualOrChildOf <Item>())
                        {
                            item = type.CreateInstanceSafe <Item>(s);

                            if (item == null)
                            {
                                ++idxIgnored;

                                logItem = s;
                                status  = "NULL";
                            }
                            else if (item.Deleted)
                            {
                                ++idxDeleted;

                                item    = null;
                                logItem = s;
                                status  = "DELETED";
                            }
                            else
                            {
                                ++idxCreated;

                                World.AddItem(item);

                                logItem = item;
                                status  = "CREATED";
                            }
                        }
                        else if (exists && valid && moveExisting && item.RootParent != m)
                        {
                            ++idxMoved;

                            logItem = item;
                            status  = "MOVE";
                        }
                        else
                        {
                            ++idxIgnored;

                            item    = null;
                            logItem = s;
                            status  = exists ? "EXISTS" : "INVALID";
                        }

                        if (log != null)
                        {
                            log.AppendLine(
                                "DATA:\tIndex[{0}]\t\tLength[{1}]\tStatus[{2}]\tItem[{3}]\t\t\tParent[{4}]",
                                //
                                binIndex,
                                binLength,
                                status,
                                logItem,
                                parent);
                        }

                        items[i] = Tuple.Create(item, parent, binIndex, binLength, status);
                    }

                    foreach (var t in items)
                    {
                        var item   = t.Item1;
                        var parent = t.Item2;
                        var index  = t.Item3;
                        var length = t.Item4;
                        var status = t.Item5;

                        bin.Seek(index, SeekOrigin.Begin);

                        if (item == null)
                        {
                            bin.Seek(index + length, SeekOrigin.Begin);
                            continue;
                        }

                        Exception x = null;

                        if (status == "MOVE")
                        {
                            bin.Seek(index + length, SeekOrigin.Begin);

                            status = "IGNORED";
                        }
                        else
                        {
                            try
                            {
                                item.Deserialize(bin);

                                status = "LOADED";
                            }
                            catch (Exception e)
                            {
                                --idxCreated;
                                ++idxDeleted;

                                item.Delete();
                                x = e;

                                status = "ERROR";
                            }
                        }

                        if (log != null)
                        {
                            log.AppendLine(
                                "READ:\tIndex[{0}]\tLength[{1}]\tStatus[{2}]\tItem[{3}]\t\t\tParent[{4}]",
                                index,
                                length,
                                status,
                                item,
                                parent);

                            if (x != null)
                            {
                                log.AppendLine();
                                log.AppendLine(new String('*', 10));
                                log.AppendLine(x.ToString());
                                log.AppendLine(new String('*', 10));
                                log.AppendLine();
                            }
                        }

                        if (parent == m.Serial)
                        {
                            if (item is BankBox)
                            {
                                oldBank = (BankBox)item;
                            }
                            else if (item is Backpack)
                            {
                                oldPack = (Backpack)item;
                            }
                        }

                        restored.Add(item, parent);
                    }

                    if (log != null)
                    {
                        log.AppendLine();
                    }

                    Point3D p;

                    foreach (var kv in restored.Where(kv => !kv.Key.Deleted).OrderBy(kv => kv.Value))
                    {
                        var item = kv.Key;

                        if ((item == oldPack || item == oldBank) && item != pack && item != bank)
                        {
                            if (item.Parent is Item)
                            {
                                ((Item)item.Parent).RemoveItem(item);
                            }
                            else if (item.Parent is Mobile)
                            {
                                ((Mobile)item.Parent).RemoveItem(item);
                            }

                            item.Parent = null;
                            continue;
                        }

                        var parent = World.FindEntity(kv.Value);

                        if (item != pack && item != bank && (item.Parent == oldPack || item.Parent == oldBank))
                        {
                            ((Item)item.Parent).RemoveItem(item);
                        }

                        if (parent != null)
                        {
                            if (item == pack || item == bank)
                            {
                                m.AddItem(item);
                            }
                            else if (parent == pack || parent == oldPack)
                            {
                                p = item.Location;
                                pack.DropItem(item);
                                item.Location = p;
                            }
                            else if (parent == bank || parent == oldBank)
                            {
                                p = item.Location;
                                bank.DropItem(item);
                                item.Location = p;
                            }
                            else if (parent is Container)
                            {
                                if (parent.Deleted)
                                {
                                    bank.DropItem(item);
                                }
                                else
                                {
                                    p = item.Location;
                                    ((Container)parent).DropItem(item);
                                    item.Location = p;
                                }
                            }
                            else if (parent is Mobile)
                            {
                                if (!m.EquipItem(item))
                                {
                                    pack.DropItem(item);
                                }
                            }
                            else
                            {
                                bank.DropItem(item);
                            }

                            item.SetLastMoved();
                            item.UpdateTotals();
                            item.Delta(ItemDelta.Update);
                        }
                        else if (Cleanup.IsBuggable(item))
                        {
                            --idxCreated;
                            ++idxDeleted;

                            item.Delete();
                        }
                        else
                        {
                            item.Internalize();
                        }
                    }

                    if (oldPack != null && oldPack != pack && !restored.ContainsKey(oldPack))
                    {
                        oldPack.Delete();
                    }

                    if (oldBank != null && oldBank != bank && !restored.ContainsKey(oldBank))
                    {
                        oldBank.Delete();
                    }

                    if (log != null)
                    {
                        log.AppendLine();
                    }

                    foreach (var kv in restored)
                    {
                        if (kv.Key.Deleted)
                        {
                            if (log != null)
                            {
                                log.AppendLine("DELETED:\tItem[{0}]\t\tParent[{1}]", kv.Key, kv.Value);
                            }
                        }
                        else if (kv.Key.RootParent == m && kv.Key.Map == Map.Internal && kv.Key.Location == Point3D.Zero)
                        {
                            if (log != null)
                            {
                                log.AppendLine("INTERNAL:\tItem[{0}]\t\tParent[{1}]", kv.Key, kv.Value);
                            }
                        }
                        else if (kv.Key.RootParent != m)
                        {
                            if (log != null)
                            {
                                log.AppendLine("IGNORED:\tItem[{0}]\t\tParent[{1}]", kv.Key, kv.Value);
                            }
                        }
                        else
                        {
                            if (log != null)
                            {
                                log.AppendLine("RESTORED:\tItem[{0}]\t\tParent[{1}]", kv.Key, kv.Key.Parent);
                            }
                        }
                    }

                    restored.Clear();

                    m.SendEverything();
                });
            });

            created = idxCreated;
            deleted = idxDeleted;
            ignored = idxIgnored;
            moved   = idxMoved;

            if (log == null)
            {
                return;
            }

            log.AppendLine();
            log.AppendLine(
                "RESULT:\tCreated[{0}]\t\tDeleted[{1}]\t\tIgnored[{2}]\t\tMoved[{3}]",
                created,
                deleted,
                ignored,
                moved);

            logFile.AppendText(false, log.ToString());
        }