Exemple #1
0
		public static void RestoreState(
			PlayerMobile m,
			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
					});
			}

			var root = VitaNexCore.DataDirectory + "/PlayerBackup/" + m.Account.Username + "/" + m.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)
					{
						if (log != null)
						{
							log.AppendLine("INVALID:\tSerial[{0}]", 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 serial, parent;
								long binIndex, binLength;

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

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

								Item item = null;

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

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

								object logItem;
								string status;

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

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

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

										item = null;
										logItem = serial;
										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 = serial;
									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());
		}