Scripts/Vivre/Commands/GM/SerializeDuper.cs
/// <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>
Primary dupe method. Will be called recursively.
Primary dupe method . Will be called recursively .
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();
			PropertyInfo[] allProps = type.GetProperties( BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public );
			foreach ( PropertyInfo thisProp in allProps )
			{
				CPA attr = Properties.GetCPA( thisProp );
				if ( attr != null && (from.AccessLevel < attr.ReadLevel || from.AccessLevel < attr.WriteLevel) )
				{
					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 );
				}
				writer.Flush();
				reader.Seek( 0, SeekOrigin.Begin ); 
				ConstructorInfo ctor = type.GetConstructor( new Type[] { typeof( Serial ) } );
				if ( toDupe is Item )
				{
					Item item = (Item)ctor.Invoke( new object[] { Serial.NewItem } );
					World.AddItem( item ); 
					serialMapping.Add( ((Item)toDupe).Serial, item.Serial );
					itemList.Insert( 0, item ); 
					item.Deserialize( reader ); 
					toReturn = item;
				}
				else if ( toDupe is Mobile )
				{
					Mobile mobile = (Mobile)ctor.Invoke( new object[] { Serial.NewMobile } );
					World.AddMobile( mobile ); 
					serialMapping.Add( ((Mobile)toDupe).Serial, mobile.Serial );
					mobileList.Insert( 0, mobile ); 
					mobile.Deserialize( reader ); 
					toReturn = mobile;
				}
				if ( !reader.End() )
				{
					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 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 ( ) ; PropertyInfo [ ] allProps = type . GetProperties ( BindingFlags . Static | BindingFlags . Instance | BindingFlags . Public ) ; foreach ( PropertyInfo thisProp in allProps ) { CPA attr = Properties . GetCPA ( thisProp ) ; if ( attr != null && ( from . AccessLevel < attr . ReadLevel || from . AccessLevel < attr . WriteLevel ) ) { if ( thisProp . DeclaringType != typeof ( BaseCreature ) && thisProp . DeclaringType != typeof ( Mobile ) ) { throw new AccessLevelTooLowException ( " " + 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 ) ; } writer . Flush ( ) ; reader . Seek ( 0 , SeekOrigin . Begin ) ; ConstructorInfo ctor = type . GetConstructor ( new Type [ ] { typeof ( Serial ) } ) ; if ( toDupe is Item ) { Item item = ( Item ) ctor . Invoke ( new object [ ] { Serial . NewItem } ) ; World . AddItem ( item ) ; serialMapping . Add ( ( ( Item ) toDupe ) . Serial , item . Serial ) ; itemList . Insert ( 0 , item ) ; item . Deserialize ( reader ) ; toReturn = item ; } else if ( toDupe is Mobile ) { Mobile mobile = ( Mobile ) ctor . Invoke ( new object [ ] { Serial . NewMobile } ) ; World . AddMobile ( mobile ) ; serialMapping . Add ( ( ( Mobile ) toDupe ) . Serial , mobile . Serial ) ; mobileList . Insert ( 0 , mobile ) ; mobile . Deserialize ( reader ) ; toReturn = mobile ; } if ( ! reader . End ( ) ) { throw new DeserializeException ( " " + toReturn . GetType ( ) . Name + " " ) ; } if ( itemList . Count + mobileList . Count > DupeCommand . MAX_ENTITIES ) { throw new EntitiesExceededException ( " " + DupeCommand . MAX_ENTITIES + " " ) ; } } finally { writer . Close ( ) ; reader . Close ( ) ; stream . Close ( ) ; } return toReturn ; }
Primary dupe method.
Primary dupe method .
// Getting all properties // Checking if the caller's AccessLevel is high enough to write those // Ignoring all properties declared by BaseCreature and Mobile // YAY! If we arrived here we are allowed to duplicate the item and have collected all necessary data // Reset position of the reader // Fetch constructor with serial as parameter // We don't want duplicate serials so we add it to the world right away to block its serial. // Insert at the beginning to reverse the recursive order // Deserialize calls Dupe again if it reaches a reference. // Konstruktor mit Serial aufrufen // We don't want duplicate serials so we add it to the world right away to block its serial. // Insert at the beginning to reverse the recursive order // Deserialize calls Dupe again if it reaches a reference. // The stream is not empty?
None
from
Mobile
Caller of the dupe command
Caller of the dupe command
toDupe
object
Item to be duped
Item to be duped
recursionDepth
int
None
itemList
List<Item>
List of items created so far
List of items created so far
mobileList
List<Mobile>
List of mobiles created so far
List of mobiles created so far
serialMapping
Dictionary<int, int>
Mapping of serials of duped items and their copied counterparts
Mapping of serials of duped items and their copied counterparts