context: using System;
  using System.Collections;
  using System.IO;
  using System.Xml;
  using Server;
  using Server.Mobiles;
  using Server.Items;
  using System.Collections.Generic;
  
  namespace Server.Regions
  {
  	public abstract class SpawnDefinition
  	{
  		protected SpawnDefinition()
  		{
  		}
  
  		public abstract object Spawn( SpawnEntry entry );
  
  		public abstract bool CanSpawn( params Type[] types );
  
  		public static SpawnDefinition GetSpawnDefinition( XmlElement xml )
  		{
  			switch ( xml.Name )
  			{
  				case "object":
  				{
  					Type type = null;
  					if ( !Region.ReadType( xml, "type", ref type ) )
  						return null;
  
  					if ( typeof( Mobile ).IsAssignableFrom( type ) )
  					{
  						return SpawnMobile.Get( type );
  					}
  					else if ( typeof( Item ).IsAssignableFrom( type ) )
  					{
  						return SpawnItem.Get( type );
  					}
  					else
  					{
  						Console.WriteLine( "Invalid type '{0}' in a SpawnDefinition", type.FullName );
  						return null;
  					}
  				}
  				case "group":
  				{
  					string group = null;
  					if ( !Region.ReadString( xml, "name", ref group ) )
  						return null;
  
  					SpawnDefinition def = (SpawnDefinition) SpawnGroup.Table[group];
  
  					if ( def == null )
  					{
  						Console.WriteLine( "Could not find group '{0}' in a SpawnDefinition", group );
  						return null;
  					}
  					else
  					{
  						return def;
  					}
  				}
  				case "treasureChest":
  				{
  					int itemID = 0xE43;
  					Region.ReadInt32( xml, "itemID", ref itemID, false );
  
  					BaseTreasureChest.TreasureLevel level = BaseTreasureChest.TreasureLevel.Level2;
  
  					Region.ReadEnum( xml, "level", ref level, false );
  
  					return new SpawnTreasureChest( itemID, level );
  				}
  				default:
  				{
  					return null;
  				}
  			}
  		}
  	}
  
  	public abstract class SpawnType : SpawnDefinition
  	{
  		private Type m_Type;
  		private bool m_Init;
  
  		public Type Type{ get{ return m_Type; } }
  
  		public abstract int Height{ get; }
  		public abstract bool Land{ get; }
  		public abstract bool Water{ get; }
  
  		protected SpawnType( Type type )
  		{
  			m_Type = type;
  			m_Init = false;
  		}
  
  		protected void EnsureInit()
  		{
  			if ( m_Init )
  				return;
  
  			Init();
  			m_Init = true;
  		}
  
  		protected virtual void Init()
  		{
  		}
  
  		public override object Spawn( SpawnEntry entry )
  		{
  			BaseRegion region = entry.Region;
  			Map map = region.Map;
  
  			Point3D loc = entry.RandomSpawnLocation( this.Height, this.Land, this.Water );
  			if ( loc == Point3D.Zero )
  				return null;
  
  			return Construct( entry, loc, map );
  		}
  
  		protected abstract object Construct( SpawnEntry entry, Point3D loc, Map map );
  
  		public override bool CanSpawn( params Type[] types )
  		{
  			for ( int i = 0; i < types.Length; i++ )
  			{
  				if ( types[i] == m_Type )
  					return true;
  			}
  
  			return false;
  		}
  	}
  
  	public class SpawnMobile : SpawnType
  	{
  		private static Hashtable m_Table = new Hashtable();
  
  		public static SpawnMobile Get( Type type )
  		{
  			SpawnMobile sm = (SpawnMobile) m_Table[type];
  
  			if ( sm == null )
  			{
  				sm = new SpawnMobile( type );
  				m_Table[type] = sm;
  			}
  
  			return sm;
  		}
  
  		protected bool m_Land;
  		protected bool m_Water;
  
  		public override int Height{ get{ return 16; } }
  		public override bool Land{ get{ EnsureInit(); return m_Land; } }
  		public override bool Water{ get{ EnsureInit(); return m_Water; } }
  
  		protected SpawnMobile( Type type ) : base( type )
  		{
  		}
  
  		protected override void Init()
  		{
  			Mobile mob = (Mobile) Activator.CreateInstance( Type );
  
  			m_Land = !mob.CantWalk;
  			m_Water = mob.CanSwim;
  
  			mob.Delete();
  		}
  
  		protected override object Construct( SpawnEntry entry, Point3D loc, Map map )
  		{
  			Mobile mobile = CreateMobile();
  
  			BaseCreature creature = mobile as BaseCreature;
  			if ( creature != null )
  			{
  				creature.Home = entry.Home;
  				creature.RangeHome = entry.Range;
  			}
  
  			if ( entry.Direction != SpawnEntry.InvalidDirection )
  				mobile.Direction = entry.Direction;
  
  			mobile.OnBeforeSpawn( loc, map );
  			mobile.MoveToWorld( loc, map );
  			mobile.OnAfterSpawn();
  
  			return mobile;
  		}
  
  		protected virtual Mobile CreateMobile()
  		{
  			return (Mobile) Activator.CreateInstance( Type );
  		}
  	}
  
  	public class SpawnItem : SpawnType
  	{
  		private static Hashtable m_Table = new Hashtable();
  
  		public static SpawnItem Get( Type type )
  		{
  			SpawnItem si = (SpawnItem) m_Table[type];
  
  			if ( si == null )
  			{
  
gt: 				si = new SpawnItem( type );