/// <summary> /// Primary dupe method. Will be called recursively. /// </summary> /// <param name="from">Caller of the dupe command</param> /// <param name="toDupe">Item to be duped</param> /// <param name="recursionDepth">Recursions left</param> /// <param name="itemList">List of items created so far</param> /// <param name="mobileList">List of mobiles created so far</param> /// <param name="serialMapping">Mapping of serials of duped items and their copied counterparts</param> /// <returns>Duplicated entity</returns> public static object Dupe(Mobile from, object toDupe, int recursionDepth, List <Item> itemList, List <Mobile> mobileList, Dictionary <int, int> serialMapping) { object toReturn = null; Type type = toDupe.GetType(); // Getting all properties PropertyInfo[] allProps = type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); // Checking if the caller's AccessLevel is high enough to write those foreach (PropertyInfo thisProp in allProps) { CPA attr = Properties.GetCPA(thisProp); if (attr != null && (from.AccessLevel < attr.ReadLevel || from.AccessLevel < attr.WriteLevel)) { // Ignoring all properties declared by BaseCreature and Mobile if (thisProp.DeclaringType != typeof(BaseCreature) && thisProp.DeclaringType != typeof(Mobile)) { throw new AccessLevelTooLowException("Your AccessLevel is too low to dupe this: " + thisProp.Name); } } } MemoryStream stream = new MemoryStream(); DupeWriter writer = new DupeWriter(stream, recursionDepth); DupeReader reader = new DupeReader(stream, from, itemList, mobileList, serialMapping); try { if (toDupe is Item) { Item item = (Item)toDupe; item.Serialize(writer); } else { Mobile mobile = (Mobile)toDupe; mobile.Serialize(writer); } // YAY! If we arrived here we are allowed to duplicate the item and have collected all necessary data writer.Flush(); reader.Seek(0, SeekOrigin.Begin); // Reset position of the reader // Fetch constructor with serial as parameter ConstructorInfo ctor = type.GetConstructor(new Type[] { typeof(Serial) }); if (toDupe is Item) { Item item = (Item)ctor.Invoke(new object[] { Serial.NewItem }); World.AddItem(item); // We don't want duplicate serials so we add it to the world right away to block its serial. serialMapping.Add(((Item)toDupe).Serial, item.Serial); itemList.Insert(0, item); // Insert at the beginning to reverse the recursive order item.Deserialize(reader); // Deserialize calls Dupe again if it reaches a reference. toReturn = item; } else if (toDupe is Mobile) { // Konstruktor mit Serial aufrufen Mobile mobile = (Mobile)ctor.Invoke(new object[] { Serial.NewMobile }); World.AddMobile(mobile); // We don't want duplicate serials so we add it to the world right away to block its serial. serialMapping.Add(((Mobile)toDupe).Serial, mobile.Serial); mobileList.Insert(0, mobile); // Insert at the beginning to reverse the recursive order mobile.Deserialize(reader); // Deserialize calls Dupe again if it reaches a reference. toReturn = mobile; } if (!reader.End()) { // The stream is not empty? throw new DeserializeException("Cannot dupe " + toReturn.GetType().Name + ". Serialize/Deserialize is either broken or uses hacks."); } if (itemList.Count + mobileList.Count > DupeCommand.MAX_ENTITIES) { throw new EntitiesExceededException("Cannot dupe more than " + DupeCommand.MAX_ENTITIES + " Items/Mobiles!"); } } finally { writer.Close(); reader.Close(); stream.Close(); } return(toReturn); }
public IEntity Dupe() { MemoryStream stream = new MemoryStream(); DupeWriter writer = new DupeWriter(stream, this); DupeReader reader = new DupeReader(stream, this); try { m_From.SendMessage("Objects Found: {0}", m_Entities.Count); foreach (IEntity entity in m_Entities) { //We add it at the same time we serialize, makes for less looping IEntity newent = AddEntity(entity.GetType()); m_NewEntities.Add(newent); if (entity is Item) { ((Item)entity).Serialize(writer); } else //Its a mob! { ((Mobile)entity).Serialize(writer); } } writer.Flush(); reader.Seek(0, SeekOrigin.Begin); for (int i = 0; i < m_NewEntities.Count; i++) { IEntity entity = m_NewEntities[i]; if (entity is Item) { ((Item)entity).Deserialize(reader); } else //Its a mob! { ((Mobile)entity).Deserialize(reader); } } if (!reader.End()) { m_From.SendMessage("The buffer is not empty. There was an error in deserialization."); return(null); } } catch (Exception e) { m_From.SendMessage(e.Message); Console.WriteLine(e); for (int i = m_NewEntities.Count - 1; i >= 0; i--) { m_NewEntities[i].Delete(); } m_NewEntities.Clear(); } finally { writer.Close(); reader.Close(); stream.Close(); } if (m_NewEntities.Count > 0) { return(m_NewEntities[0]); } else { m_From.SendMessage("Error duping objects. No objects duped."); return(null); } }