RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

New Wall And Floor Tiles

FingersMcSteal

Sorceror
Fixed, totally forgot the server was using a customized version of the old tiledata.mul (pointed to by the datapath.cs on the server).

Just plan to double check the itemID's i'm using for the customizations and maybe zip it up and post it into the custom release thread, unless someone else wants to do this ? (I got work again...yuk).
 

mitty

Sorceror
hey then lets all....

Lets all work on the roofing and door and stair problems together so we can post the finished product for all to see here and help evryone along. Peo the E-mail is coming with the peerless stuff.
 

Grimklash

Wanderer
Curious if anybody else is having this problem and came up with a fix.

The interior stairs set fine but if you go up a level to customize they disapear.So far everything else is working fine except the interior stairs.

This is with 2.0 RC1.
 

mitty

Sorceror
Same problem I'm running 1.0 Hybrid shard..

No no core mods just a lot of hard work, but the crystal and elven inside stairs won't stay and the elven and crystal/shadow roof tiles dont work either. Also the elven doors wont open. I posted here what I had so far on the elven doors/with errors. Also working on stairs and roof stuff. Need some insight from everyone and we can all solve this together. :D (We'll get it guys, all of it!)
 

FingersMcSteal

Sorceror
So far i have the walls, doors and roof's all working, just the inside building stairs to fix, not sure whats causing it but they just won't drop in off the design stage, i can see them ok and move them around but nothing on the click when trying to place them.

The steps at the front of the plot are fine tho.
 

FingersMcSteal

Sorceror
The part at the end of this line in red... It's in the HouseFoundation.cs at about line 1299...

Code:
// UnrealUO - Samurai Empire roof Crystal & Shadow Added at the end
		public static bool IsRoofTile( int id )
		{
			id &= 0x3FFF;

            if ((id >= 0x05b3 && id <= 0x05a3) || (id >= 0x2148 && id <= 0x21f0) || (id >= 0x23be && id <= 0x23ff) || (id >= 0x26da && id <= 0x2935) || (id >= 0x2c24 && id <= 0x2c7d) [COLOR="Red"]|| (id >= 0x35BE && id <= 0x35D1) || (id >= 0x3623 && id <= 0x3635[/COLOR]))
				return true;

			return false;
		}

Still no luck on those internal stairs yet but i'm looking at it tonight (just in from work).
 

bryant

Sorceror
cool that works for the new roof tiles

foe some reason i cant get the leaf and bark roof tiles working though did are yours working?
 

FingersMcSteal

Sorceror
That was the wierd one, i'm not 100% sure but they started to work properly after i changed the servers tiledata.mul (which the datapath.cs pointed to) and they started to work with no problems.

The only other edit i can remember was one or two itemID's in the Housefoundation.cs needed to be altered, this is mine i'm using now...

I'm still messing round with this to try and get the stairs in but this works for me with a fully patched tiledata.mul from EA (Version 5.0.6c).

I've not made any changes to any of the Door.cs files tho.

Code:
using System;
using System.IO;
using System.Threading;
using System.Collections;
using Server;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using Server.Network;
using Server.Targeting;

namespace Server.Multis
{
	public enum FoundationType
	{
		Stone,
		DarkWood,
		LightWood,
		Dungeon,
		Brick,
        ElvenGrey,
        ElvenNatural,
        Crystal,
        Shadow
	}

	public class HouseFoundation : BaseHouse
	{
		private DesignState m_Current; // State which is currently visible.
		private DesignState m_Design;  // State of current design.
		private DesignState m_Backup;  // State at last user backup.
		private Item m_SignHanger;     // Item hanging the sign.
		private Item m_Signpost;       // Item supporting the hanger.
		private int m_SignpostGraphic; // ItemID number of the chosen signpost.
		private int m_LastRevision;    // Latest revision number.
		private ArrayList m_Fixtures;  // List of fixtures (teleporters and doors) associated with this house.
		private FoundationType m_Type; // Graphic type of this foundation.
		private Mobile m_Customizer;   // Who is currently customizing this -or- null if not customizing.

		public FoundationType Type{ get{ return m_Type; } set{ m_Type = value; } }
		public int LastRevision{ get{ return m_LastRevision; } set{ m_LastRevision = value; } }
		public ArrayList Fixtures{ get{ return m_Fixtures; } }
		public Item SignHanger{ get{ return m_SignHanger; } }
		public Item Signpost{ get{ return m_Signpost; } }
		public int SignpostGraphic{ get{ return m_SignpostGraphic; } set{ m_SignpostGraphic = value; } }
		public Mobile Customizer{ get{ return m_Customizer; } set{ m_Customizer = value; } }

		public override bool IsAosRules{ get{ return true; } }

		public bool IsFixture( Item item )
		{
			return ( m_Fixtures != null && m_Fixtures.Contains( item ) );
		}

		public override MultiComponentList Components
		{
			get
			{
				if ( m_Current == null )
					SetInitialState();

				return m_Current.Components;
			}
		}

		public override int GetMaxUpdateRange()
		{
			return 24;
		}

		public override int GetUpdateRange( Mobile m )
		{
			int w = CurrentState.Components.Width;
			int h = CurrentState.Components.Height-1;
			int v = 18 + (( w > h ? w : h ) / 2);

			if ( v > 24 )
				v = 24;
			else if ( v < 18 )
				v = 18;

			return v;
		}

		public DesignState CurrentState
		{
			get{ if ( m_Current == null ) SetInitialState(); return m_Current; }
			set{ m_Current = value; }
		}

		public DesignState DesignState
		{
			get{ if ( m_Design == null ) SetInitialState(); return m_Design; }
			set{ m_Design = value; }
		}

		public DesignState BackupState
		{
			get{ if ( m_Backup == null ) SetInitialState(); return m_Backup; }
			set{ m_Backup = value; }
		}

		public void SetInitialState()
		{
			// This is a new house, it has not yet loaded a design state
			m_Current = new DesignState( this, GetEmptyFoundation() );
			m_Design = new DesignState( m_Current );
			m_Backup = new DesignState( m_Current );
		}

		public override void OnAfterDelete()
		{
			base.OnAfterDelete();

			if ( m_SignHanger != null )
				m_SignHanger.Delete();

			if ( m_Signpost != null )
				m_Signpost.Delete();

			if ( m_Fixtures == null )
				return;

			for ( int i = 0; i < m_Fixtures.Count; ++i )
			{
				Item item = (Item)m_Fixtures[i];

				if ( item != null )
					item.Delete();
			}

			m_Fixtures.Clear();
		}

		public override void OnLocationChange( Point3D oldLocation )
		{
			base.OnLocationChange( oldLocation );

			int x = Location.X - oldLocation.X;
			int y = Location.Y - oldLocation.Y;
			int z = Location.Z - oldLocation.Z;

			if ( m_SignHanger != null )
				m_SignHanger.MoveToWorld( new Point3D( m_SignHanger.X + x, m_SignHanger.Y + y, m_SignHanger.Z + z ), Map );

			if ( m_Signpost != null )
				m_Signpost.MoveToWorld( new Point3D( m_Signpost.X + x, m_Signpost.Y + y, m_Signpost.Z + z ), Map );

			if ( m_Fixtures == null )
				return;

			for ( int i = 0; i < m_Fixtures.Count; ++i )
			{
				Item item = (Item)m_Fixtures[i];

				if ( Doors.Contains( item ) )
					continue;

				item.MoveToWorld( new Point3D( item.X + x, item.Y + y, item.Z + z ), Map );
			}
		}

		public override void OnMapChange()
		{
			base.OnMapChange();

			if ( m_SignHanger != null )
				m_SignHanger.Map = this.Map;

			if ( m_Signpost != null )
				m_Signpost.Map = this.Map;

			if ( m_Fixtures == null )
				return;

			for ( int i = 0; i < m_Fixtures.Count; ++i )
				((Item)m_Fixtures[i]).Map = this.Map;
		}

		public void ClearFixtures( Mobile from )
		{
			if ( m_Fixtures == null )
				return;

			RemoveKeys( from );

			for ( int i = 0; i < m_Fixtures.Count; ++i )
			{
				((Item)m_Fixtures[i]).Delete();
				Doors.Remove( m_Fixtures[i] );
			}

			m_Fixtures.Clear();
		}

		public void AddFixtures( Mobile from, MultiTileEntry[] list )
		{
			if ( m_Fixtures == null )
				m_Fixtures = new ArrayList();

			uint keyValue = 0;

			for ( int i = 0; i < list.Length; ++i )
			{
				MultiTileEntry mte = list[i];
				int itemID = mte.m_ItemID & 0x3FFF;

				if ( itemID >= 0x181D && itemID < 0x1829 )
				{
					HouseTeleporter tp = new HouseTeleporter( itemID );

					AddFixture( tp, mte );
				}
				else
				{
					BaseDoor door = null;

                    // MINE
                    //crystal and shadow
                    if (itemID >= 0x367B && itemID < 0x369B)
                    {
                        int type = (itemID - 0x367B) / 16;
                        DoorFacing facing = (DoorFacing)(((itemID - 0x367B) / 2) % 8);

                        switch (type)
                        {
                            case 0: door = new GenericHouseDoor(facing, 0x367B, 0xEC, 0xF3); break;
                            case 1: door = new GenericHouseDoor(facing, 0x368B, 0xEC, 0xF3); break;
                        }
                    }
                    // add else to if on next line

                    else if ( itemID >= 0x675 && itemID < 0x6F5 )
					{
						int type = (itemID - 0x675) / 16;
						DoorFacing facing = (DoorFacing)(((itemID - 0x675) / 2) % 8);

						switch ( type )
						{
							case 0: door = new GenericHouseDoor( facing, 0x675, 0xEC, 0xF3 ); break;
							case 1: door = new GenericHouseDoor( facing, 0x685, 0xEC, 0xF3 ); break;
							case 2: door = new GenericHouseDoor( facing, 0x695, 0xEB, 0xF2 ); break;
							case 3: door = new GenericHouseDoor( facing, 0x6A5, 0xEA, 0xF1 ); break;
							case 4: door = new GenericHouseDoor( facing, 0x6B5, 0xEA, 0xF1 ); break;
							case 5: door = new GenericHouseDoor( facing, 0x6C5, 0xEC, 0xF3 ); break;
							case 6: door = new GenericHouseDoor( facing, 0x6D5, 0xEA, 0xF1 ); break;
							case 7: door = new GenericHouseDoor( facing, 0x6E5, 0xEA, 0xF1 ); break;
						}
					}
					else if ( itemID >= 0x314 && itemID < 0x364 )
					{
						int type = (itemID - 0x314) / 16;
						DoorFacing facing = (DoorFacing)(((itemID - 0x314) / 2) % 8);

						switch ( type )
						{
							case 0: door = new GenericHouseDoor( facing, 0x314, 0xED, 0xF4 ); break;
							case 1: door = new GenericHouseDoor( facing, 0x324, 0xED, 0xF4 ); break;
							case 2: door = new GenericHouseDoor( facing, 0x334, 0xED, 0xF4 ); break;
							case 3: door = new GenericHouseDoor( facing, 0x344, 0xED, 0xF4 ); break;
							case 4: door = new GenericHouseDoor( facing, 0x354, 0xED, 0xF4 ); break;
						}
					}
					else if ( itemID >= 0x824 && itemID < 0x834 )
					{
						DoorFacing facing = (DoorFacing)(((itemID - 0x824) / 2) % 8);
						door = new GenericHouseDoor( facing, 0x824, 0xEC, 0xF3 );
					}
					else if ( itemID >= 0x839 && itemID < 0x849 )
					{
						DoorFacing facing = (DoorFacing)(((itemID - 0x839) / 2) % 8);
						door = new GenericHouseDoor( facing, 0x839, 0xEB, 0xF2 );
					}
					else if ( itemID >= 0x84C && itemID < 0x85C )
					{
						DoorFacing facing = (DoorFacing)(((itemID - 0x84C) / 2) % 8);
						door = new GenericHouseDoor( facing, 0x84C, 0xEC, 0xF3 );
					}
					else if ( itemID >= 0x866 && itemID < 0x876 )
					{
						DoorFacing facing = (DoorFacing)(((itemID - 0x866) / 2) % 8);
						door = new GenericHouseDoor( facing, 0x866, 0xEB, 0xF2 );
					}
					else if ( itemID >= 0xE8 && itemID < 0xF8 )
					{
						DoorFacing facing = (DoorFacing)(((itemID - 0xE8) / 2) % 8);
						door = new GenericHouseDoor( facing, 0xE8, 0xED, 0xF4 );
					}
					else if ( itemID >= 0x1FED && itemID < 0x1FFD )
					{
						DoorFacing facing = (DoorFacing)(((itemID - 0x1FED) / 2) % 8);
						door = new GenericHouseDoor( facing, 0x1FED, 0xEC, 0xF3 );
					}
					// UnrealUO - Samurai Empire doors
					else if ( itemID >= 0x2a05 && itemID < 0x2a0d )
					{
						DoorFacing facing = (DoorFacing)((((itemID - 0x2a05) / 2) % 4) + 8);
						door = new SlidingHouseDoor( facing, itemID, 0x55, 0x57 );
					}
					else if ( itemID >= 0x2a0d && itemID < 0x2a15 )
					{
						DoorFacing facing = (DoorFacing)((((itemID - 0x2a0d) / 2) % 4) + 8);
						door = new SlidingHouseDoor( facing, itemID, 0x55, 0x57 );
					}
					else if ( itemID >= 0x2a15 && itemID < 0x2a1d )
					{
						DoorFacing facing = (DoorFacing)((((itemID - 0x2a15) / 2) % 4) + 8);
						door = new SlidingHouseDoor( facing, itemID, 0x55, 0x57 );
					}
					else if ( itemID >= 0x241f && itemID < 0x2425 )
					{
						DoorFacing facing = DoorFacing.South2;
						switch ( itemID )
						{
							case 0x241f: facing = DoorFacing.South2; break;
							case 0x2423: facing = DoorFacing.East2; break;
						}
						door = new WoodenHouseDoor2( facing, itemID, 0xEB, 0xF2 );
					}

					if ( door != null )
					{
						if ( keyValue == 0 )
							keyValue = CreateKeys( from );

						door.Locked = true;
						door.KeyValue = keyValue;

						AddDoor( door, mte.m_OffsetX, mte.m_OffsetY, mte.m_OffsetZ );
						m_Fixtures.Add( door );
					}
				}
			}

			for ( int i = 0; i < m_Fixtures.Count; ++i )
			{
				Item fixture = (Item)m_Fixtures[i];

				if ( fixture is HouseTeleporter )
				{
					HouseTeleporter tp = (HouseTeleporter)fixture;

					for ( int j = 1; j <= m_Fixtures.Count; ++j )
					{
						HouseTeleporter check = m_Fixtures[(i + j) % m_Fixtures.Count] as HouseTeleporter;

						if ( check != null && check.ItemID == tp.ItemID )
						{
							tp.Target = check;
							break;
						}
					}
				}
				else if ( fixture is BaseHouseDoor )
				{
					BaseHouseDoor door = (BaseHouseDoor)fixture;

					if ( door.Link != null )
						continue;

					DoorFacing linkFacing;
					int xOffset, yOffset;

					switch ( door.Facing )
					{
						default:
						case DoorFacing.WestCW: linkFacing = DoorFacing.EastCCW; xOffset = 1; yOffset = 0; break;
						case DoorFacing.EastCCW: linkFacing = DoorFacing.WestCW; xOffset = -1; yOffset = 0; break;
						case DoorFacing.WestCCW: linkFacing = DoorFacing.EastCW; xOffset = 1; yOffset = 0; break;
						case DoorFacing.EastCW: linkFacing = DoorFacing.WestCCW; xOffset = -1; yOffset = 0; break;
						case DoorFacing.SouthCW: linkFacing = DoorFacing.NorthCCW; xOffset = 0; yOffset = -1; break;
						case DoorFacing.NorthCCW: linkFacing = DoorFacing.SouthCW; xOffset = 0; yOffset = 1; break;
						case DoorFacing.SouthCCW: linkFacing = DoorFacing.NorthCW; xOffset = 0; yOffset = -1; break;
						case DoorFacing.NorthCW: linkFacing = DoorFacing.SouthCCW; xOffset = 0; yOffset = 1; break;
						// UnrealUO - Samurai Empire doors
						case DoorFacing.SouthSW: linkFacing = DoorFacing.SouthSE; xOffset = 1; yOffset = 0; break;
						case DoorFacing.SouthSE: linkFacing = DoorFacing.SouthSW; xOffset = -1; yOffset = 0; break;
						case DoorFacing.WestSN: linkFacing = DoorFacing.WestSS; xOffset = 0; yOffset = 1; break;
						case DoorFacing.WestSS: linkFacing = DoorFacing.WestSN; xOffset = 0; yOffset = -1; break;
					}

					for ( int j = i + 1; j < m_Fixtures.Count; ++j )
					{
						BaseHouseDoor check = m_Fixtures[j] as BaseHouseDoor;

						if ( check != null && check.Link == null && check.Facing == linkFacing && (check.X - door.X) == xOffset && (check.Y - door.Y) == yOffset && (check.Z == door.Z) )
						{
							check.Link = door;
							door.Link = check;
							break;
						}
					}
				}
			}
		}

		public void AddFixture( Item item, MultiTileEntry mte )
		{
			m_Fixtures.Add( item );
			item.MoveToWorld( new Point3D( X + mte.m_OffsetX, Y + mte.m_OffsetY, Z + mte.m_OffsetZ ), Map );
		}

		public static void GetFoundationGraphics( FoundationType type, out int east, out int south, out int post, out int corner )
		{
			switch ( type )
			{
				default:
				case FoundationType.DarkWood:	corner = 0x0014; east = 0x0015; south = 0x0016; post = 0x0017; break;
				case FoundationType.LightWood:	corner = 0x00BD; east = 0x00BE; south = 0x00BF; post = 0x00C0; break;
				case FoundationType.Dungeon:	corner = 0x02FD; east = 0x02FF; south = 0x02FE; post = 0x0300; break;
				case FoundationType.Brick:	corner = 0x0041; east = 0x0043; south = 0x0042; post = 0x0044; break;
				case FoundationType.Stone:	corner = 0x0065; east = 0x0064; south = 0x0063; post = 0x0066; break;
                    // MINE
                case FoundationType.ElvenGrey: corner = 0x2dfb; east = 0x2dfd; south = 0x2dfe; post = 0x2dfc; break;
                case FoundationType.ElvenNatural: corner = 0x2df7; east = 0x2df9; south = 0x2dfa; post = 0x2df8; break;
                case FoundationType.Crystal: corner = 0x3672; east = 0x3671; south = 0x3670; post = 0x3677; break;
                case FoundationType.Shadow: corner = 0x3614; east = 0x3636; south = 0x3637; post = 0x3617; break;
			}
		}

		public static void ApplyFoundation( FoundationType type, MultiComponentList mcl )
		{
			int east, south, post, corner;

			GetFoundationGraphics( type, out east, out south, out post, out corner );

			int xCenter = mcl.Center.X;
			int yCenter = mcl.Center.Y;

			mcl.Add( post, 0 - xCenter, 0 - yCenter, 0 );
			mcl.Add( corner, mcl.Width - 1 - xCenter, mcl.Height - 2 - yCenter, 0 );

			for ( int x = 1; x < mcl.Width; ++x )
			{
				mcl.Add( south, x - xCenter, 0 - yCenter, 0 );

				if ( x < mcl.Width-1 )
					mcl.Add( south, x - xCenter, mcl.Height - 2 - yCenter, 0 );
			}

			for ( int y = 1; y < mcl.Height - 1; ++y )
			{
				mcl.Add( east, 0 - xCenter, y - yCenter, 0 );

				if ( y < mcl.Height - 2 )
					mcl.Add( east, mcl.Width - 1 - xCenter, y - yCenter, 0 );
			}
		}

		public static void AddStairsTo( ref MultiComponentList mcl )
		{
			// copy the original..
			mcl = new MultiComponentList( mcl );

			mcl.Resize( mcl.Width, mcl.Height + 1 );

			int xCenter = mcl.Center.X;
			int yCenter = mcl.Center.Y;
			int y = mcl.Height - 1;

			for ( int x = 0; x < mcl.Width; ++x )
				mcl.Add( 0x63, x - xCenter, y - yCenter, 0 );
		}

		public MultiComponentList GetEmptyFoundation()
		{
			// Copy original foundation layout
			MultiComponentList mcl = new MultiComponentList( MultiData.GetComponents( ItemID ) );

			mcl.Resize( mcl.Width, mcl.Height + 1 );

			int xCenter = mcl.Center.X;
			int yCenter = mcl.Center.Y;
			int y = mcl.Height - 1;

			ApplyFoundation( m_Type, mcl );

			for ( int x = 1; x < mcl.Width; ++x )
				mcl.Add( 0x751, x - xCenter, y - yCenter, 0 );

			return mcl;
		}

		public override Rectangle2D[] Area
		{
			get
			{
				MultiComponentList mcl = Components;

				return new Rectangle2D[]{ new Rectangle2D( mcl.Min.X, mcl.Min.Y, mcl.Width, mcl.Height ) };
			}
		}

		public void CheckSignpost()
		{
			MultiComponentList mcl = this.Components;

			int x = mcl.Min.X;
			int y = mcl.Height - 2 - mcl.Center.Y;

			if ( CheckWall( mcl, x, y ) )
			{
				if ( m_Signpost != null )
					m_Signpost.Delete();

				m_Signpost = null;
			}
			else if ( m_Signpost == null )
			{
				m_Signpost = new Static( m_SignpostGraphic );
				m_Signpost.MoveToWorld( new Point3D( X + x, Y + y, Z + 7 ), Map );
			}
			else
			{
				m_Signpost.ItemID = m_SignpostGraphic;
				m_Signpost.MoveToWorld( new Point3D( X + x, Y + y, Z + 7 ), Map );
			}
		}

		public bool CheckWall( MultiComponentList mcl, int x, int y )
		{
			x += mcl.Center.X;
			y += mcl.Center.Y;

			if ( x >= 0 && x < mcl.Width && y >= 0 && y < mcl.Height )
			{
				Tile[] tiles = mcl.Tiles[x][y];

				for ( int i = 0; i < tiles.Length; ++i )
				{
					Tile tile = tiles[i];

					if ( tile.Z == 7 && tile.Height == 20 )
						return true;
				}
			}

			return false;
		}

		public HouseFoundation( Mobile owner, int multiID, int maxLockdowns, int maxSecures ) : base( multiID, owner, maxLockdowns, maxSecures )
		{
			m_SignpostGraphic = 9;

			m_Fixtures = new ArrayList();

			int x = Components.Min.X;
			int y = Components.Height - 1 - Components.Center.Y;

			m_SignHanger = new Static( 0xB98 );
			m_SignHanger.MoveToWorld( new Point3D( X + x, Y + y, Z + 7 ), Map );

			CheckSignpost();

			SetSign( x, y, 7 );

			BanLocation = new Point3D( x, y, 0 );
		}

		public HouseFoundation( Serial serial ) : base( serial )
		{
		}

		public void BeginCustomize( Mobile m )
		{
			if ( !m.CheckAlive() )
				return;

			DesignContext.Add( m, this );
			m.Send( new BeginHouseCustomization( this ) );

			if ( m.NetState != null )
				SendInfoTo( m.NetState );

			DesignState.SendDetailedInfoTo( m.NetState );

			ArrayList list = new ArrayList( Region.Mobiles );

			foreach ( Mobile rem in list )
			{
				if ( !(rem is PlayerVendor) && !(rem is PlayerBarkeeper) && rem != m && IsInside( rem ) )
					rem.Location = BanLocation;
			}
		}

		public override void SendInfoTo( NetState state )
		{
			base.SendInfoTo( state );

			DesignContext context = DesignContext.Find( state.Mobile );
			DesignState stateToSend;

			if ( context != null && context.Foundation == this )
				stateToSend = DesignState;
			else
				stateToSend = CurrentState;

			stateToSend.SendGeneralInfoTo( state );
		}

		public override void Serialize( GenericWriter writer )
		{
			writer.Write( (int) 5 ); // version

			writer.Write( m_Signpost );
			writer.Write( (int) m_SignpostGraphic );

			writer.Write( (int) m_Type );

			writer.Write( m_SignHanger );

			writer.Write( (int) m_LastRevision );
			writer.WriteItemList( m_Fixtures, true );

			CurrentState.Serialize( writer );
			DesignState.Serialize( writer );
			BackupState.Serialize( writer );

			base.Serialize( writer );
		}

		private int m_DefaultPrice;

		public override int DefaultPrice{ get{ return m_DefaultPrice; } }

		public override void Deserialize( GenericReader reader )
		{
			int version = reader.ReadInt();

			switch ( version )
			{
				case 5:
				case 4:
				{
					m_Signpost = reader.ReadItem();
					m_SignpostGraphic = reader.ReadInt();

					goto case 3;
				}
				case 3:
				{
					m_Type = (FoundationType)reader.ReadInt();

					goto case 2;
				}
				case 2:
				{
					m_SignHanger = reader.ReadItem();

					goto case 1;
				}
				case 1:
				{
					if ( version < 5 )
						m_DefaultPrice = reader.ReadInt();

					goto case 0;
				}
				case 0:
				{
					if ( version < 3 )
						m_Type = FoundationType.Stone;

					if ( version < 4 )
						m_SignpostGraphic = 9;

					m_LastRevision = reader.ReadInt();
					m_Fixtures = reader.ReadItemList();

					m_Current = new DesignState( this, reader );
					m_Design = new DesignState( this, reader );
					m_Backup = new DesignState( this, reader );

					break;
				}
			}

			base.Deserialize( reader );
		}

		public bool IsHiddenToCustomizer( Item item )
		{
			return ( item == m_Signpost || ( m_Fixtures != null && m_Fixtures.Contains( item ) ) );
		}

		public static void Initialize()
		{
			PacketHandlers.RegisterExtended( 0x1E, true, new OnPacketReceive( QueryDesignDetails ) );

			PacketHandlers.RegisterEncoded( 0x02, true, new OnEncodedPacketReceive( Designer_Backup ) );
			PacketHandlers.RegisterEncoded( 0x03, true, new OnEncodedPacketReceive( Designer_Restore ) );
			PacketHandlers.RegisterEncoded( 0x04, true, new OnEncodedPacketReceive( Designer_Commit ) );
			PacketHandlers.RegisterEncoded( 0x05, true, new OnEncodedPacketReceive( Designer_Delete ) );
			PacketHandlers.RegisterEncoded( 0x06, true, new OnEncodedPacketReceive( Designer_Build ) );
			PacketHandlers.RegisterEncoded( 0x0C, true, new OnEncodedPacketReceive( Designer_Close ) );
			PacketHandlers.RegisterEncoded( 0x0D, true, new OnEncodedPacketReceive( Designer_Stairs ) );
			PacketHandlers.RegisterEncoded( 0x0E, true, new OnEncodedPacketReceive( Designer_Sync ) );
			PacketHandlers.RegisterEncoded( 0x10, true, new OnEncodedPacketReceive( Designer_Clear ) );
			PacketHandlers.RegisterEncoded( 0x12, true, new OnEncodedPacketReceive( Designer_Level ) );
			PacketHandlers.RegisterEncoded( 0x13, true, new OnEncodedPacketReceive( Designer_Roof ) ); // UnrealUO - Samurai Empire roof
			PacketHandlers.RegisterEncoded( 0x14, true, new OnEncodedPacketReceive( Designer_RoofDelete ) ); // UnrealUO - Samurai Empire roof
			PacketHandlers.RegisterEncoded( 0x1A, true, new OnEncodedPacketReceive( Designer_Revert ) );

			Commands.Register( "DesignInsert", AccessLevel.GameMaster, new CommandEventHandler( DesignInsert_OnCommand ) );

			EventSink.Speech += new SpeechEventHandler( EventSink_Speech );
		}

		private static void EventSink_Speech( SpeechEventArgs e )
		{
			if ( DesignContext.Find( e.Mobile ) != null )
			{
				e.Mobile.SendLocalizedMessage( 1061925 ); // You cannot speak while customizing your house.
				e.Blocked = true;
			}
		}

		public static void Designer_Sync( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				/* Client requested state synchronization
				 *  - Resend full house state
				 */

				DesignState design = context.Foundation.DesignState;

				// Resend full house state
				design.SendDetailedInfoTo( state );
			}
		}

		public static void Designer_Clear( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				/* Client chose to clear the design
				 *  - Restore empty foundation
				 *     - Construct new design state from empty foundation
				 *     - Assign constructed state to foundation
				 *  - Update revision
				 *  - Update client with new state
				 */

				// Restore empty foundation : Construct new design state from empty foundation
				DesignState newDesign = new DesignState( context.Foundation, context.Foundation.GetEmptyFoundation() );

				// Restore empty foundation : Assign constructed state to foundation
				context.Foundation.DesignState = newDesign;

				// Update revision
				newDesign.OnRevised();

				// Update client with new state
				context.Foundation.SendInfoTo( state );
				newDesign.SendDetailedInfoTo( state );
			}
		}

		public static void Designer_Restore( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				/* Client chose to restore design to the last backup state
				 *  - Restore backup
				 *     - Construct new design state from backup state
				 *     - Assign constructed state to foundation
				 *  - Update revision
				 *  - Update client with new state
				 */

				// Restore backup : Construct new design state from backup state
				DesignState backupDesign = new DesignState( context.Foundation.BackupState );

				// Restore backup : Assign constructed state to foundation
				context.Foundation.DesignState = backupDesign;

				// Update revision;
				backupDesign.OnRevised();

				// Update client with new state
				context.Foundation.SendInfoTo( state );
				backupDesign.SendDetailedInfoTo( state );
			}
		}

		public static void Designer_Backup( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				/* Client chose to backup design state
				 *  - Construct a copy of the current design state
				 *  - Assign constructed state to backup state field
				 */

				// Construct a copy of the current design state
				DesignState copyState = new DesignState( context.Foundation.DesignState );

				// Assign constructed state to backup state field
				context.Foundation.BackupState = copyState;
			}
		}

		public static void Designer_Revert( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				/* Client chose to revert design state to currently visible state
				 *  - Revert design state
				 *     - Construct a copy of the current visible state
				 *     - Freeze fixtures in constructed state
				 *     - Assign constructed state to foundation
				 *     - If a signpost is needed, add it
				 *  - Update revision
				 *  - Update client with new state
				 */

				// Revert design state : Construct a copy of the current visible state
				DesignState copyState = new DesignState( context.Foundation.CurrentState );

				// Revert design state : Freeze fixtures in constructed state
				copyState.FreezeFixtures();

				// Revert design state : Assign constructed state to foundation
				context.Foundation.DesignState = copyState;

				// Revert design state : If a signpost is needed, add it
				context.Foundation.CheckSignpost();

				// Update revision
				copyState.OnRevised();

				// Update client with new state
				context.Foundation.SendInfoTo( state );
				copyState.SendDetailedInfoTo( state );
			}
		}

		public void EndConfirmCommit( Mobile from )
		{
			int oldPrice = Price;
			int newPrice = oldPrice + 0 + ((DesignState.Components.List.Length - CurrentState.Components.List.Length) * 500);
			int cost = newPrice - oldPrice;

			if ( cost > 0 )
			{
				if ( Banker.Withdraw( from, cost ) )
				{
					from.SendLocalizedMessage( 1060398, cost.ToString() ); // ~1_AMOUNT~ gold has been withdrawn from your bank box.
				}
				else
				{
					from.SendLocalizedMessage( 1061903 ); // You cannot commit this house design, because you do not have the necessary funds in your bank box to pay for the upgrade.  Please back up your design, obtain the required funds, and commit your design again.
					return;
				}
			}
			else if ( cost < 0 )
			{
				if ( Banker.Deposit( from, -cost ) )
					from.SendLocalizedMessage( 1060397, (-cost).ToString() ); // ~1_AMOUNT~ gold has been deposited into your bank box.
				else
					return;
			}

			/* Client chose to commit current design state
				 *  - Commit design state
				 *     - Construct a copy of the current design state
				 *     - Clear visible fixtures
				 *     - Melt fixtures from constructed state
				 *     - Add melted fixtures from constructed state
				 *     - Assign constructed state to foundation
				 *  - Update house price
				 *  - Remove design context
				 *  - Notify the client that customization has ended
				 *  - Notify the core that the foundation has changed and should be resent to all clients
				 *  - Eject client from house
				 *  - If a signpost is needed, add it
				 */

			// Commit design state : Construct a copy of the current design state
			DesignState copyState = new DesignState( DesignState );

			// Commit design state : Clear visible fixtures
			ClearFixtures( from );

			// Commit design state : Melt fixtures from constructed state
			copyState.MeltFixtures();

			// Commit design state : Add melted fixtures from constructed state
			AddFixtures( from, copyState.Fixtures );

			// Commit design state : Assign constructed state to foundation
			CurrentState = copyState;

			// Update house price
			Price = newPrice - 0;

			// Remove design context
			DesignContext.Remove( from );

			// Notify the client that customization has ended
			from.Send( new EndHouseCustomization( this ) );

			// Notify the core that the foundation has changed and should be resent to all clients
			Delta( ItemDelta.Update );
			ProcessDelta();
			CurrentState.SendDetailedInfoTo( from.NetState );

			// Eject client from house
			from.RevealingAction();

			from.MoveToWorld( BanLocation, Map );

			// If a signpost is needed, add it
			CheckSignpost();
		}

		public static void Designer_Commit( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				int oldPrice = context.Foundation.Price;
				int newPrice = oldPrice + 0 + ((context.Foundation.DesignState.Components.List.Length - context.Foundation.CurrentState.Components.List.Length) * 500);
				int bankBalance = Banker.GetBalance( from );

				from.SendGump( new ConfirmCommitGump( from, context.Foundation, bankBalance, oldPrice, newPrice ) );
			}
		}

		public static bool IsSignHanger( int itemID )
		{
			itemID &= 0x3FFF;

			return ( itemID >= 0xB97 && itemID < 0xBA3 );
		}

		public static int GetLevelZ( int level )
		{
			switch ( level )
			{
				default:
				case 1: return 07;
				case 2: return 27;
				case 3: return 47;
				case 4: return 67;
			}
		}

		private static int[] m_BlockIDs = new int[]
			{
				0x3EE, 0x709, 0x71E, 0x721,
				0x738, 0x750, 0x76C, 0x788,
				0x7A3, 0x7BA,
                0x35D2
			};

		private static int[] m_StairSeqs = new int[]
			{
				0x3EF, 0x70A, 0x722, 0x739,
				0x751, 0x76D, 0x789, 0x7A4,
                0x35D3
			};

		private static int[] m_StairIDs = new int[]
			{
				0x71F, 0x736, 0x737, 0x749,
				0x7BB, 0x7BC,
                0x35D3
			};

		public static bool IsStairBlock( int id )
		{
			id &= 0x3FFF;
			int delta = -1;

			for ( int i = 0; delta < 0 && i < m_BlockIDs.Length; ++i )
				delta = ( m_BlockIDs[i] - id );

			return ( delta == 0 );
		}

		public static bool IsStair( int id, ref int dir )
		{
			id &= 0x3FFF;
			int delta = -4;

			for ( int i = 0; delta < -3 && i < m_StairSeqs.Length; ++i )
				delta = ( m_StairSeqs[i] - id );

			if ( delta >= -3 && delta <= 0 )
			{
				dir = -delta;
				return true;
			}

			delta = -1;

			for ( int i = 0; delta < 0 && i < m_StairIDs.Length; ++i )
			{
				delta = ( m_StairIDs[i] - id );
				dir = i % 4;
			}

			return ( delta == 0 );
		}

		public static bool DeleteStairs( MultiComponentList mcl, int id, int x, int y, int z )
		{
			int ax = x + mcl.Center.X;
			int ay = y + mcl.Center.Y;

			if ( ax < 0 || ay < 0 || ax >= mcl.Width || ay >= (mcl.Height - 1) || z < 7 || ((z - 7) % 5) != 0 )
				return false;

			if ( IsStairBlock( id ) )
			{
				Tile[] tiles = mcl.Tiles[ax][ay];

				for ( int i = 0; i < tiles.Length; ++i )
				{
					Tile tile = tiles[i];

					if ( tile.Z == (z + 5) )
					{
						id = tile.ID;
						z = tile.Z;

						if ( !IsStairBlock( id ) )
							break;
					}
				}
			}

			int dir = 0;

			if ( !IsStair( id, ref dir ) )
				return false;

			int height = ((z - 7) % 20) / 5;

			int xStart, yStart;
			int xInc, yInc;

			switch ( dir )
			{
				default:
				case 0: // North
				{
					xStart = x;
					yStart = y + height;
					xInc = 0;
					yInc = -1;
					break;
				}
				case 1: // West
				{
					xStart = x + height;
					yStart = y;
					xInc = -1;
					yInc = 0;
					break;
				}
				case 2: // South
				{
					xStart = x;
					yStart = y - height;
					xInc = 0;
					yInc = 1;
					break;
				}
				case 3: // East
				{
					xStart = x - height;
					yStart = y;
					xInc = 1;
					yInc = 0;
					break;
				}
			}

			int zStart = z - (height * 5);

			for ( int i = 0; i < 4; ++i )
			{
				x = xStart + (i * xInc);
				y = yStart + (i * yInc);

				for ( int j = 0; j <= i; ++j )
					mcl.RemoveXYZH( x, y, zStart + (j * 5), 5 );

				ax = x + mcl.Center.X;
				ay = y + mcl.Center.Y;

				if ( ax >= 1 && ax < mcl.Width && ay >= 1 && ay < mcl.Height - 1 )
				{
					Tile[] tiles = mcl.Tiles[ax][ay];

					bool hasBaseFloor = false;

					for ( int j = 0; !hasBaseFloor && j < tiles.Length; ++j )
						hasBaseFloor = ( tiles[j].Z == 7 && (tiles[j].ID & 0x3FFF) != 1 );

					if ( !hasBaseFloor )
						mcl.Add( 0x31F4, x, y, 7 );
				}
			}

			return true;
		}

		public static void Designer_Delete( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				/* Client chose to delete a component
				 *  - Read data detailing which component to delete
				 *  - Verify component is deletable
				 *  - Remove the component
				 *  - If needed, replace removed component with a dirt tile
				 *  - Update revision
				 */

				// Read data detailing which component to delete
				int itemID = pvSrc.ReadInt32();
				int x = pvSrc.ReadInt32();
				int y = pvSrc.ReadInt32();
				int z = pvSrc.ReadInt32();

				// Verify component is deletable
				DesignState design = context.Foundation.DesignState;
				MultiComponentList mcl = design.Components;

				int ax = x + mcl.Center.X;
				int ay = y + mcl.Center.Y;

				if ( IsSignHanger( itemID ) || (z == 0 && ax >= 0 && ax < mcl.Width && ay >= 0 && ay < (mcl.Height - 1)) )
				{
					/* Component is not deletable
					 *  - Resend design state
					 *  - Return without further processing
					 */

					design.SendDetailedInfoTo( state );
					return;
				}

				// Remove the component
				if ( !DeleteStairs( mcl, itemID, x, y, z ) )
					mcl.Remove( itemID, x, y, z );

				// If needed, replace removed component with a dirt tile
				if ( ax >= 1 && ax < mcl.Width && ay >= 1 && ay < mcl.Height - 1 )
				{
					Tile[] tiles = mcl.Tiles[ax][ay];

					bool hasBaseFloor = false;

					for ( int i = 0; !hasBaseFloor && i < tiles.Length; ++i )
						hasBaseFloor = ( tiles[i].Z == 7 && (tiles[i].ID & 0x3FFF) != 1 );

					if ( !hasBaseFloor )
					{
						// Replace with a dirt tile
						mcl.Add( 0x31F4, x, y, 7 );
					}
				}

				// Update revision
				design.OnRevised();
			}
		}

		public static void Designer_Stairs( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				/* Client chose to add stairs
				 *  - Read data detailing stair type and location
				 *  - Validate stair multi ID
				 *  - Add the stairs
				 *     - Load data describing the stair components
				 *     - Insert described components
				 *  - Update revision
				 */

				// Read data detailing stair type and location
				int itemID = pvSrc.ReadInt32();
				int x = pvSrc.ReadInt32();
				int y = pvSrc.ReadInt32();

				// Validate stair multi ID
				DesignState design = context.Foundation.DesignState;

				if ( itemID < 0x1DB0 || itemID > 0x1DD7 )
				{
					/* Specified multi ID is not a stair
					 *  - Resend design state
					 *  - Return without further processing
					 */

					design.SendDetailedInfoTo( state );
					return;
				}

				// Add the stairs
				MultiComponentList mcl = design.Components;

				// Add the stairs : Load data describing stair components
				MultiComponentList stairs = MultiData.GetComponents( itemID );

				// Add the stairs : Insert described components
				int z = GetLevelZ( context.Level );

				for ( int i = 0; i < stairs.List.Length; ++i )
				{
					MultiTileEntry entry = stairs.List[i];

					if ( (entry.m_ItemID & 0x3FFF) != 1 )
						mcl.Add( entry.m_ItemID, x + entry.m_OffsetX, y + entry.m_OffsetY, z + entry.m_OffsetZ );
				}

				// Update revision
				design.OnRevised();
			}
		}

		// UnrealUO - Samurai Empire roof
		public static void Designer_Roof( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				// Read data detailing component graphic and location
				int itemID = pvSrc.ReadInt32();
				int x = pvSrc.ReadInt32();
				int y = pvSrc.ReadInt32();
				int z = pvSrc.ReadInt32();

				// Add component
				DesignState design = context.Foundation.DesignState;

				// Validate roof tiles (rough ranges)
				if ( !IsRoofTile( itemID ) )
				{
					design.SendDetailedInfoTo( state );
					return;
				}

				MultiComponentList mcl = design.Components;

				if ( z < -3 || z > 12 || z % 3 > 0 )
					z = 0;
				z += GetLevelZ( context.Level );

				MultiTileEntry[] list = mcl.List;
				int id;
				for ( int i = 0; i < list.Length; i++ )
				{
					MultiTileEntry mte = list[i];
					id = mte.m_ItemID;
					if ( mte.m_OffsetX == x && mte.m_OffsetY == y && IsRoofTile( id ) )
						mcl.Remove( id, x, y, mte.m_OffsetZ );
				}

				mcl.Add( itemID, x, y, z );

				// Update revision
				design.OnRevised();
			}
		}

		// UnrealUO - Samurai Empire roof Crystal & Shadow Added at the end
		public static bool IsRoofTile( int id )
		{
			id &= 0x3FFF;

            if ((id >= 0x05b3 && id <= 0x05a3) || (id >= 0x2148 && id <= 0x21f0) || (id >= 0x23be && id <= 0x23ff) || (id >= 0x26da && id <= 0x2935) || (id >= 0x2c24 && id <= 0x2c7d) || (id >= 0x35BE && id <= 0x35D1) || (id >= 0x3623 && id <= 0x3635))
				return true;

			return false;
		}

		// UnrealUO - Samurai Empire roof
		public static void Designer_RoofDelete( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				// Read data detailing which component to delete
				int itemID = pvSrc.ReadInt32();
				int x = pvSrc.ReadInt32();
				int y = pvSrc.ReadInt32();
				int z = pvSrc.ReadInt32();

				// Verify component is deletable
				DesignState design = context.Foundation.DesignState;
				MultiComponentList mcl = design.Components;

				if ( !IsRoofTile( itemID ) )
				{
					design.SendDetailedInfoTo( state );
					return;
				}

				mcl.Remove( itemID, x, y, z );

				design.OnRevised();
			}
		}

		[Usage( "DesignInsert" )]
		[Description( "Inserts multiple targeted items into a customizable houses design." )]
		public static void DesignInsert_OnCommand( CommandEventArgs e )
		{
			e.Mobile.Target = new DesignInsertTarget( null );
			e.Mobile.SendMessage( "Target an item to insert it into the house design." );
		}

		private class DesignInsertTarget : Target
		{
			private HouseFoundation m_Foundation;

			public DesignInsertTarget( HouseFoundation foundation ) : base( -1, false, TargetFlags.None )
			{
				m_Foundation = foundation;
			}

			protected override void OnTargetCancel( Mobile from, TargetCancelType cancelType )
			{
				if ( m_Foundation != null )
				{
					from.SendMessage( "Your changes have been committed. Updating..." );

					m_Foundation.Delta( ItemDelta.Update );
				}
			}

			protected override void OnTarget( Mobile from, object obj )
			{
				Item item = obj as Item;

				if ( item == null )
				{
					from.Target = new DesignInsertTarget( m_Foundation );
					from.SendMessage( "That is not an item. Try again." );
				}
				else
				{
					HouseFoundation house = BaseHouse.FindHouseAt( item ) as HouseFoundation;

					if ( house == null )
					{
						from.Target = new DesignInsertTarget( m_Foundation );
						from.SendMessage( "That item is not inside a customizable house. Try again." );
					}
					else if ( m_Foundation != null && house != m_Foundation )
					{
						from.Target = new DesignInsertTarget( m_Foundation );
						from.SendMessage( "That item is not inside the current house; all targeted items must reside in the same house. You may cancel this target and repeat the command." );
					}
					else
					{
						DesignState state = house.CurrentState;
						MultiComponentList mcl = state.Components;

						int x = item.X - house.X;
						int y = item.Y - house.Y;
						int z = item.Z - house.Z;

						if ( x >= mcl.Min.X && y >= mcl.Min.Y && x <= mcl.Max.X && y <= mcl.Max.Y )
						{
							mcl.Add( item.ItemID, x, y, z );
							item.Delete();

							state.OnRevised();

							state = house.DesignState;
							mcl = state.Components;

							if ( x >= mcl.Min.X && y >= mcl.Min.Y && x <= mcl.Max.X && y <= mcl.Max.Y )
							{
								mcl.Add( item.ItemID, x, y, z );
								state.OnRevised();
							}

							from.Target = new DesignInsertTarget( house );

							if ( m_Foundation == null )
								from.SendMessage( "The item has been inserted into the house design. Press ESC when you are finished." );
							else
								from.SendMessage( "The item has been inserted into the house design." );

							m_Foundation = house;
						}
						else
						{
							from.Target = new DesignInsertTarget( m_Foundation );
							from.SendMessage( "That item is not inside a customizable house. Try again." );
						}
					}
				}
			}
		}

		public static void Designer_Build( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				/* Client chose to add a component
				 *  - Read data detailing component graphic and location
				 *  - Add component
				 *  - Update revision
				 */

				// Read data detailing component graphic and location
				int itemID = pvSrc.ReadInt32();
				int x = pvSrc.ReadInt32();
				int y = pvSrc.ReadInt32();

				// Add component
				DesignState design = context.Foundation.DesignState;
				MultiComponentList mcl = design.Components;

				int z = GetLevelZ( context.Level );

				if ( (y + mcl.Center.Y) == (mcl.Height - 1) )
					z = 0; // Tiles placed on the far-south of the house are at 0 Z

				mcl.Add( itemID, x, y, z );

				// Update revision
				design.OnRevised();
			}
		}

		public static void Designer_Close( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				/* Client closed his house design window
				 *  - Remove design context
				 *  - Notify the client that customization has ended
				 *  - Refresh client with current visable design state
				 *  - Eject client from house
				 *  - If a signpost is needed, add it
				 */

				// Remove design context
				DesignContext.Remove( from );

				// Notify the client that customization has ended
				from.Send( new EndHouseCustomization( context.Foundation ) );

				// Refresh client with current visible design state
				context.Foundation.SendInfoTo( state );
				context.Foundation.CurrentState.SendDetailedInfoTo( state );

				// Eject client from house
				from.RevealingAction();

				from.MoveToWorld( context.Foundation.BanLocation, context.Foundation.Map );

				// If a signpost is needed, add it
				context.Foundation.CheckSignpost();
			}
		}

		public static void Designer_Level( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				/* Client is moving to a new floor level
				 *  - Read data detailing the target level
				 *  - Validate target level
				 *  - Update design context with new level
				 *  - Teleport mobile to new level
				 *  - Update client
				 * 
				 * TODO: Proper validation for two-story homes
				 */

				// Read data detailing the target level
				int newLevel = pvSrc.ReadInt32();

				// Validate target level
				if ( newLevel < 1 || newLevel > 4 )
					newLevel = 1;

				// Update design context with new level
				context.Level = newLevel;

				// Teleport mobile to new level
				from.Location = new Point3D( from.X, from.Y, context.Foundation.Z + GetLevelZ( newLevel ) );

				// Update client
				context.Foundation.SendInfoTo( state );
			}
		}

		public static void QueryDesignDetails( NetState state, PacketReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			HouseFoundation foundation = World.FindItem( pvSrc.ReadInt32() ) as HouseFoundation;

			if ( foundation != null && from.Map == foundation.Map && from.InRange( foundation.GetWorldLocation(), 24 ) && from.CanSee( foundation ) )
			{
				DesignState stateToSend;

				if ( context != null && context.Foundation == foundation )
					stateToSend = foundation.DesignState;
				else
					stateToSend = foundation.CurrentState;

				stateToSend.SendDetailedInfoTo( state );
			}
		}
	}

	public class DesignState
	{
		private HouseFoundation m_Foundation;
		private MultiComponentList m_Components;
		private MultiTileEntry[] m_Fixtures;
		private int m_Revision;
		private Packet m_PacketCache;

		public Packet PacketCache{ get{ return m_PacketCache; } set{ m_PacketCache = value; } }

		public HouseFoundation Foundation{ get{ return m_Foundation; } }
		public MultiComponentList Components{ get{ return m_Components; } }
		public MultiTileEntry[] Fixtures{ get{ return m_Fixtures; } }
		public int Revision{ get{ return m_Revision; } set{ m_Revision = value; } }

		public DesignState( HouseFoundation foundation, MultiComponentList components )
		{
			m_Foundation = foundation;
			m_Components = components;
			m_Fixtures = new MultiTileEntry[0];
		}

		public DesignState( DesignState toCopy )
		{
			m_Foundation = toCopy.m_Foundation;
			m_Components = new MultiComponentList( toCopy.m_Components );
			m_Revision = toCopy.m_Revision;
			m_Fixtures = new MultiTileEntry[toCopy.m_Fixtures.Length];

			for ( int i = 0; i < m_Fixtures.Length; ++i )
				m_Fixtures[i] = toCopy.m_Fixtures[i];
		}

		public DesignState( HouseFoundation foundation, GenericReader reader )
		{
			m_Foundation = foundation;

			int version = reader.ReadInt();

			switch ( version )
			{
				case 0:
				{
					m_Components = new MultiComponentList( reader );

					int length = reader.ReadInt();

					m_Fixtures = new MultiTileEntry[length];

					for ( int i = 0; i < length; ++i )
					{
						m_Fixtures[i].m_ItemID = reader.ReadShort();
						m_Fixtures[i].m_OffsetX = reader.ReadShort();
						m_Fixtures[i].m_OffsetY = reader.ReadShort();
						m_Fixtures[i].m_OffsetZ = reader.ReadShort();
						m_Fixtures[i].m_Flags = reader.ReadInt();
					}

					m_Revision = reader.ReadInt();

					break;
				}
			}
		}

		public void Serialize( GenericWriter writer )
		{
			writer.Write( (int) 0 ); // version

			m_Components.Serialize( writer );

			writer.Write( (int) m_Fixtures.Length );

			for ( int i = 0; i < m_Fixtures.Length; ++i )
			{
				MultiTileEntry ent = m_Fixtures[i];

				writer.Write( (short) ent.m_ItemID );
				writer.Write( (short) ent.m_OffsetX );
				writer.Write( (short) ent.m_OffsetY );
				writer.Write( (short) ent.m_OffsetZ );
				writer.Write( (int) ent.m_Flags );
			}

			writer.Write( (int) m_Revision );
		}

		public void OnRevised()
		{
			lock ( this )
			{
				m_Revision = ++m_Foundation.LastRevision;
				m_PacketCache = null;
			}
		}

		public void SendGeneralInfoTo( NetState state )
		{
			if ( state != null )
				state.Send( new DesignStateGeneral( m_Foundation, this ) );
		}

		public void SendDetailedInfoTo( NetState state )
		{
			if ( state != null )
			{
				lock ( this )
				{
					if ( m_PacketCache == null )
						DesignStateDetailed.SendDetails( state, m_Foundation, this );
					else
						state.Send( m_PacketCache );
				}
			}
		}

		public void FreezeFixtures()
		{
			OnRevised();

			for ( int i = 0; i < m_Fixtures.Length; ++i )
			{
				MultiTileEntry mte = m_Fixtures[i];

				m_Components.Add( mte.m_ItemID, mte.m_OffsetX, mte.m_OffsetY, mte.m_OffsetZ );
			}

			m_Fixtures = new MultiTileEntry[0];
		}

		public void MeltFixtures()
		{
			OnRevised();

			MultiTileEntry[] list = m_Components.List;
			int length = 0;

			for ( int i = list.Length - 1; i >= 0; --i )
			{
				MultiTileEntry mte = list[i];

				if ( IsFixture( mte.m_ItemID ) )
					++length;
			}

			m_Fixtures = new MultiTileEntry[length];

			for ( int i = list.Length - 1; i >= 0; --i )
			{
				MultiTileEntry mte = list[i];

				if ( IsFixture( mte.m_ItemID ) )
				{
					m_Fixtures[--length] = mte;
					m_Components.Remove( mte.m_ItemID, mte.m_OffsetX, mte.m_OffsetY, mte.m_OffsetZ );
				}
			}
		}

		public static bool IsFixture( int itemID )
		{
			itemID &= 0x3FFF;

            // MINE
            // crystal and shadow
            if (itemID >= 0x367B && itemID < 0x369B)
                return true;
            //
            else if ( itemID >= 0x675 && itemID < 0x6F5 )
				return true;
			else if ( itemID >= 0x314 && itemID < 0x364 )
				return true;
			else if ( itemID >= 0x824 && itemID < 0x834 )
				return true;
			else if ( itemID >= 0x839 && itemID < 0x849 )
				return true;
			else if ( itemID >= 0x84C && itemID < 0x85C )
				return true;
			else if ( itemID >= 0x866 && itemID < 0x876 )
				return true;
			else if ( itemID >= 0xE8 && itemID < 0xF8 )
				return true;
			else if ( itemID >= 0x1FED && itemID < 0x1FFD )
				return true;
			else if ( itemID >= 0x181D && itemID < 0x1829 )
				return true;
			// UnrealUO - Samurai Empire doors
			else if ( itemID >= 0x2a05 && itemID < 0x2a0d )
				return true;
			else if ( itemID >= 0x2a0d && itemID < 0x2a15 )
				return true;
			else if ( itemID >= 0x2a15 && itemID < 0x2a1d )
				return true;
			else if ( itemID >= 0x241f && itemID < 0x2425 )
				return true;

			return false;
		}
	}

	public class ConfirmCommitGump : Gump
	{
		private HouseFoundation m_Foundation;

		public ConfirmCommitGump( Mobile from, HouseFoundation foundation, int bankBalance, int oldPrice, int newPrice ) : base( 50, 50 )
		{
			m_Foundation = foundation;

			AddPage( 0 );

			AddBackground( 0, 0, 320, 320, 5054 );

			AddImageTiled( 10, 10, 300, 20, 2624 );
			AddImageTiled( 10, 40, 300, 240, 2624 );
			AddImageTiled( 10, 290, 300, 20, 2624 );

			AddAlphaRegion( 10, 10, 300, 300 );

			AddHtmlLocalized( 10, 10, 300, 20, 1062060, 32736, false, false ); // <CENTER>COMMIT DESIGN</CENTER>

			AddHtmlLocalized( 10, 40, 300, 140, (newPrice - oldPrice) <= bankBalance ? 1061898 : 1061903, 1023, false, true );

			AddHtmlLocalized( 10, 190, 150, 20, 1061902, 32736, false, false ); // Bank Balance:
			AddLabel( 170, 190, 55, bankBalance.ToString() );

			AddHtmlLocalized( 10, 215, 150, 20, 1061899, 1023, false, false ); // Old Value:
			AddLabel( 170, 215, 90, oldPrice.ToString() );

			AddHtmlLocalized( 10, 235, 150, 20, 1061900, 1023, false, false ); // Cost To Commit:
			AddLabel( 170, 235, 90, newPrice.ToString() );

			AddHtmlLocalized( 10, 260, 150, 20, 1061901, 31744, false, false ); // Your Cost:
			AddLabel( 170, 260, 40, (newPrice - oldPrice).ToString() );

			AddButton( 10, 290, 4005, 4007, 1, GumpButtonType.Reply, 0 );
			AddHtmlLocalized( 45, 290, 55, 20, 1011036, 32767, false, false ); // OKAY

			AddButton( 170, 290, 4005, 4007, 0, GumpButtonType.Reply, 0 );
			AddHtmlLocalized( 195, 290, 55, 20, 1011012, 32767, false, false ); // CANCEL
		}

		public override void OnResponse( NetState sender, RelayInfo info )
		{
			if ( info.ButtonID == 1 )
				m_Foundation.EndConfirmCommit( sender.Mobile );
		}
	}

	public class DesignContext
	{
		private HouseFoundation m_Foundation;
		private int m_Level;

		public HouseFoundation Foundation{ get{ return m_Foundation; } }
		public int Level{ get{ return m_Level; } set{ m_Level = value; } }

		public DesignContext( HouseFoundation foundation )
		{
			m_Foundation = foundation;
			m_Level = 1;
		}

		private static Hashtable m_Table = new Hashtable();

		public static Hashtable Table{ get{ return m_Table; } }

		public static DesignContext Find( Mobile from )
		{
			if ( from == null )
				return null;

			return (DesignContext)m_Table[from];
		}

		public static bool Check( Mobile m )
		{
			if ( Find( m ) != null )
			{
				m.SendLocalizedMessage( 1062206 ); // You cannot do that while customizing a house.
				return false;
			}

			return true;
		}

		public static void Add( Mobile from, HouseFoundation foundation )
		{
			if ( from == null )
				return;

			DesignContext c = new DesignContext( foundation );

			m_Table[from] = c;

			if ( from is PlayerMobile )
				((PlayerMobile)from).DesignContext = c;

			foundation.Customizer = from;

			from.Hidden = true;
			from.Location = new Point3D( foundation.X, foundation.Y, foundation.Z + 7 );

			NetState state = from.NetState;

			if ( state == null )
				return;

			ArrayList fixtures = foundation.Fixtures;

			for ( int i = 0; fixtures != null && i < fixtures.Count; ++i )
			{
				Item item = (Item)fixtures[i];

				state.Send( item.RemovePacket );
			}

			if ( foundation.Signpost != null )
				state.Send( foundation.Signpost.RemovePacket );
		}

		public static void Remove( Mobile from )
		{
			if ( from == null )
				return;

			DesignContext context = (DesignContext)m_Table[from];

			m_Table.Remove( from );

			if ( from is PlayerMobile )
				((PlayerMobile)from).DesignContext = null;

			if ( context == null )
				return;

			context.Foundation.Customizer = null;

			NetState state = from.NetState;

			if ( state == null )
				return;

			ArrayList fixtures = context.Foundation.Fixtures;

			for ( int i = 0; fixtures != null && i < fixtures.Count; ++i )
			{
				Item item = (Item)fixtures[i];

				item.SendInfoTo( state );
			}

			if ( context.Foundation.Signpost != null )
				context.Foundation.Signpost.SendInfoTo( state );
		}
	}

	public class BeginHouseCustomization : Packet
	{
		public BeginHouseCustomization( HouseFoundation house ) : base( 0xBF )
		{
			EnsureCapacity( 17 );

			m_Stream.Write( (short) 0x20 );
			m_Stream.Write( (int) house.Serial );
			m_Stream.Write( (byte) 0x04 );
			m_Stream.Write( (ushort) 0x0000 );
			m_Stream.Write( (ushort) 0xFFFF );
			m_Stream.Write( (ushort) 0xFFFF );
			m_Stream.Write( (byte) 0xFF );
		}
	}

	public class EndHouseCustomization : Packet
	{
		public EndHouseCustomization( HouseFoundation house ) : base( 0xBF )
		{
			EnsureCapacity( 17 );

			m_Stream.Write( (short) 0x20 );
			m_Stream.Write( (int) house.Serial );
			m_Stream.Write( (byte) 0x05 );
			m_Stream.Write( (ushort) 0x0000 );
			m_Stream.Write( (ushort) 0xFFFF );
			m_Stream.Write( (ushort) 0xFFFF );
			m_Stream.Write( (byte) 0xFF );
		}
	}

	public class DesignStateGeneral : Packet
	{
		public DesignStateGeneral( HouseFoundation house, DesignState state ) : base( 0xBF )
		{
			EnsureCapacity( 13 );

			m_Stream.Write( (short) 0x1D );
			m_Stream.Write( (int) house.Serial );
			m_Stream.Write( (int) state.Revision );
		}
	}

	public class DesignStateDetailed : Packet
	{
		public const int MaxItemsPerStairBuffer = 750;

		private static byte[][] m_PlaneBuffers;
		private static bool[] m_PlaneUsed;

		private static byte[][] m_StairBuffers;

		private static byte[] m_PrimBuffer = new byte[4];

		public void Write( int value )
		{
			m_PrimBuffer[0] = (byte)(value >> 24);
			m_PrimBuffer[1] = (byte)(value >> 16);
			m_PrimBuffer[2] = (byte)(value >>  8);
			m_PrimBuffer[3] = (byte) value;

			m_Stream.UnderlyingStream.Write( m_PrimBuffer, 0, 4 );
		}

		public void Write( short value )
		{
			m_PrimBuffer[0] = (byte)(value >> 8);
			m_PrimBuffer[1] = (byte) value;

			m_Stream.UnderlyingStream.Write( m_PrimBuffer, 0, 2 );
		}

		public void Write( byte value )
		{
			m_Stream.UnderlyingStream.WriteByte( value );
		}

		public void Write( byte[] buffer, int offset, int size )
		{
			m_Stream.UnderlyingStream.Write( buffer, offset, size );
		}

		public static void Clear( byte[] buffer, int size )
		{
			for ( int i = 0; i < size; ++i )
				buffer[i] = 0;
		}

		public DesignStateDetailed( int serial, int revision, int xMin, int yMin, int xMax, int yMax, MultiTileEntry[] tiles ) : base( 0xD8 )
		{
			EnsureCapacity( 17 + (tiles.Length * 5) );

			Write( (byte) 0x03 ); // Compression Type
			Write( (byte) 0x00 ); // Unknown
			Write( (int) serial );
			Write( (int) revision );
			Write( (short) tiles.Length );
			Write( (short) 0 ); // Buffer length : reserved
			Write( (byte) 0 ); // Plane count : reserved

			int totalLength = 1; // includes plane count

			int width = (xMax - xMin) + 1;
			int height = (yMax - yMin) + 1;

			if ( m_PlaneBuffers == null )
			{
				m_PlaneBuffers = new byte[9][];
				m_PlaneUsed = new bool[9];

				for ( int i = 0; i < m_PlaneBuffers.Length; ++i )
					m_PlaneBuffers[i] = new byte[0x400];

				m_StairBuffers = new byte[6][];

				for ( int i = 0; i < m_StairBuffers.Length; ++i )
					m_StairBuffers[i] = new byte[MaxItemsPerStairBuffer * 5];
			}
			else
			{
				for ( int i = 0; i < m_PlaneUsed.Length; ++i )
					m_PlaneUsed[i] = false;

				Clear( m_PlaneBuffers[0], width * height * 2 );

				for ( int i = 0; i < 4; ++i )
				{
					Clear( m_PlaneBuffers[1 + i], (width - 1) * (height - 2) * 2 );
					Clear( m_PlaneBuffers[5 + i], width * (height - 1) * 2 );
				}
			}

			int totalStairsUsed = 0;

			for ( int i = 0; i < tiles.Length; ++i )
			{
				MultiTileEntry mte = tiles[i];
				int x = mte.m_OffsetX - xMin;
				int y = mte.m_OffsetY - yMin;
				int z = mte.m_OffsetZ;
				bool floor = ( TileData.ItemTable[mte.m_ItemID & 0x3FFF].Height <= 0 );
				int plane, size;

				switch ( z )
				{
					case 0: plane = 0; break;
					case 7: plane = 1; break;
					case 27: plane = 2; break;
					case 47: plane = 3; break;
					case 67: plane = 4; break;
					default:
					{
						int stairBufferIndex = ( totalStairsUsed / MaxItemsPerStairBuffer );
						byte[] stairBuffer = m_StairBuffers[stairBufferIndex];

						int byteIndex = (totalStairsUsed % MaxItemsPerStairBuffer) * 5;

						stairBuffer[byteIndex++] = (byte) ((mte.m_ItemID >> 8) & 0x3F);
						stairBuffer[byteIndex++] = (byte) mte.m_ItemID;

						stairBuffer[byteIndex++] = (byte) mte.m_OffsetX;
						stairBuffer[byteIndex++] = (byte) mte.m_OffsetY;
						stairBuffer[byteIndex++] = (byte) mte.m_OffsetZ;

						++totalStairsUsed;

						continue;
					}
				}

				if ( plane == 0 )
				{
					size = height;
				}
				else if ( floor )
				{
					size = height - 2;
					x -= 1;
					y -= 1;
				}
				else
				{
					size = height - 1;
					plane += 4;
				}

				int index = ((x * size) + y) * 2;

				m_PlaneUsed[plane] = true;
				m_PlaneBuffers[plane][index] = (byte) ((mte.m_ItemID >> 8) & 0x3F);
				m_PlaneBuffers[plane][index + 1] = (byte) mte.m_ItemID;
			}

			int planeCount = 0;

			for ( int i = 0; i < m_PlaneBuffers.Length; ++i )
			{
				if ( !m_PlaneUsed[i] )
					continue;

				++planeCount;

				int size = 0;

				if ( i == 0 )
					size = width * height * 2;
				else if ( i < 5 )
					size = (width - 1) * (height - 2) * 2;
				else
					size = width * (height - 1) * 2;

				byte[] inflatedBuffer = m_PlaneBuffers[i];

				int deflatedLength = m_DeflatedBuffer.Length;
				ZLibError ce = ZLib.compress2( m_DeflatedBuffer, ref deflatedLength, inflatedBuffer, size, ZLibCompressionLevel.Z_DEFAULT_COMPRESSION );

				if ( ce != ZLibError.Z_OK )
				{
					Console.WriteLine( "ZLib error: {0} (#{1})", ce, (int)ce );
					deflatedLength = 0;
					size = 0;
				}

				Write( (byte) (0x20 | i) );
				Write( (byte) size );
				Write( (byte) deflatedLength );
				Write( (byte) (((size >> 4) & 0xF0) | ((deflatedLength >> 8) & 0xF)) );
				Write( m_DeflatedBuffer, 0, deflatedLength );

				totalLength += 4 + deflatedLength;
			}

			int totalStairBuffersUsed = ( totalStairsUsed + (MaxItemsPerStairBuffer - 1) ) / MaxItemsPerStairBuffer;

			for ( int i = 0; i < totalStairBuffersUsed; ++i )
			{
				++planeCount;

				int count = ( totalStairsUsed - (i * MaxItemsPerStairBuffer) );

				if ( count > MaxItemsPerStairBuffer )
					count = MaxItemsPerStairBuffer;

				int size = count * 5;

				byte[] inflatedBuffer = m_StairBuffers[i];

				int deflatedLength = m_DeflatedBuffer.Length;
				ZLibError ce = ZLib.compress2( m_DeflatedBuffer, ref deflatedLength, inflatedBuffer, size, ZLibCompressionLevel.Z_DEFAULT_COMPRESSION );

				if ( ce != ZLibError.Z_OK )
				{
					Console.WriteLine( "ZLib error: {0} (#{1})", ce, (int)ce );
					deflatedLength = 0;
					size = 0;
				}

				Write( (byte) (9 + i) );
				Write( (byte) size );
				Write( (byte) deflatedLength );
				Write( (byte) (((size >> 4) & 0xF0) | ((deflatedLength >> 8) & 0xF)) );
				Write( m_DeflatedBuffer, 0, deflatedLength );

				totalLength += 4 + deflatedLength;
			}

			m_Stream.Seek( 15, System.IO.SeekOrigin.Begin );

			Write( (short) totalLength ); // Buffer length
			Write( (byte) planeCount ); // Plane count

			/*int planes = (tiles.Length + (MaxItemsPerPlane - 1)) / MaxItemsPerPlane;

			if ( planes > 255 )
				planes = 255;

			int totalLength = 0;

			m_Stream.Write( (byte) planes );
			++totalLength;

			int itemIndex = 0;

			for ( int i = 0; i < planes; ++i )
			{
				int byteIndex = 0;

				for ( int j = 0; j < MaxItemsPerPlane && itemIndex < tiles.Length; ++j, ++itemIndex )
				{
					MultiTileEntry e = tiles[itemIndex];

					m_InflatedBuffer[byteIndex++] = (byte)((e.m_ItemID >> 8) & 0x3F);
					m_InflatedBuffer[byteIndex++] = (byte)e.m_ItemID;
					m_InflatedBuffer[byteIndex++] = (byte)e.m_OffsetX;
					m_InflatedBuffer[byteIndex++] = (byte)e.m_OffsetY;
					m_InflatedBuffer[byteIndex++] = (byte)e.m_OffsetZ;
				}

				int deflatedLength = m_DeflatedBuffer.Length;
				ZLibError ce = ZLib.compress2( m_DeflatedBuffer, ref deflatedLength, m_InflatedBuffer, byteIndex, ZLibCompressionLevel.Z_DEFAULT_COMPRESSION );

				if ( ce != ZLibError.Z_OK )
				{
					Console.WriteLine( "ZLib error: {0} (#{1})", ce, (int)ce );
					deflatedLength = 0;
					byteIndex = 0;
				}

				m_Stream.Write( (byte) 0x00 );
				m_Stream.Write( (byte) byteIndex );
				m_Stream.Write( (byte) deflatedLength );
				m_Stream.Write( (byte) (((byteIndex >> 4) & 0xF0) | ((deflatedLength >> 8) & 0xF)) );
				m_Stream.Write( m_DeflatedBuffer, 0, deflatedLength );

				totalLength += 4 + deflatedLength;
			}

			m_Stream.Seek( 15, System.IO.SeekOrigin.Begin );
			m_Stream.Write( (short) totalLength ); // Buffer length*/
		}

		private static byte[] m_InflatedBuffer = new byte[0x2000];
		private static byte[] m_DeflatedBuffer = new byte[0x2000];

		private class SendQueueEntry
		{
			public NetState m_NetState;
			public int m_Serial, m_Revision;
			public int m_xMin, m_yMin, m_xMax, m_yMax;
			public DesignState m_Root;
			public MultiTileEntry[] m_Tiles;

			public SendQueueEntry( NetState ns, HouseFoundation foundation, DesignState state )
			{
				m_NetState = ns;
				m_Serial = foundation.Serial;
				m_Revision = state.Revision;
				m_Root = state;

				MultiComponentList mcl = state.Components;

				m_xMin = mcl.Min.X;
				m_yMin = mcl.Min.Y;
				m_xMax = mcl.Max.X;
				m_yMax = mcl.Max.Y;

				m_Tiles = mcl.List;
			}
		}

		private static Queue m_SendQueue;
		private static AutoResetEvent m_Sync;
		private static Thread m_Thread;

		static DesignStateDetailed()
		{
			m_SendQueue = Queue.Synchronized( new Queue() );
			m_Sync = new AutoResetEvent( false );

			m_Thread = new Thread( new ThreadStart( CompressionThread ) );
			m_Thread.Name = "AOS Compression Thread";
			m_Thread.Start();
		}

		public static void CompressionThread()
		{
			while ( !Core.Closing )
			{
				m_Sync.WaitOne();

				while ( m_SendQueue.Count > 0 )
				{
					SendQueueEntry sqe = (SendQueueEntry)m_SendQueue.Dequeue();

					try
					{
						Packet p = null;

						lock ( sqe.m_Root )
							p = sqe.m_Root.PacketCache;

						if ( p == null )
						{
							p = new DesignStateDetailed( sqe.m_Serial, sqe.m_Revision, sqe.m_xMin, sqe.m_yMin, sqe.m_xMax, sqe.m_yMax, sqe.m_Tiles );

							lock ( sqe.m_Root )
							{
								if ( sqe.m_Revision == sqe.m_Root.Revision )
									sqe.m_Root.PacketCache = p;
							}
						}

						Timer.DelayCall( TimeSpan.Zero, new TimerStateCallback( SendPacket_Sandbox ), new object[]{ sqe.m_NetState, p } );
					}
					catch ( Exception e )
					{
						Console.WriteLine( e );

						try
						{
							using ( StreamWriter op = new StreamWriter( "dsd_exceptions.txt", true ) )
								op.WriteLine( e );
						}
						catch
						{
						}
					}

					//sqe.m_NetState.Send( new DesignStateDetailed( sqe.m_Serial, sqe.m_Revision, sqe.m_xMin, sqe.m_yMin, sqe.m_xMax, sqe.m_yMax, sqe.m_Tiles ) );
				}
			}
		}

		public static void SendPacket_Sandbox( object state )
		{
			object[] states = (object[])state;
			NetState ns = (NetState)states[0];
			Packet p = (Packet)states[1];

			ns.Send( p );
		}

		public static void SendDetails( NetState ns, HouseFoundation house, DesignState state )
		{
			m_SendQueue.Enqueue( new SendQueueEntry( ns, house, state ) );
			m_Sync.Set();
		}
}
}
 

bryant

Sorceror
wierd

even if i patch your foundation into the server i still cant use the bark and twisted vine roof tiles by chance did u change anything in the gump or that prolly wouldnt matter
 

FingersMcSteal

Sorceror
I've finally got my stairs working :)

In HouseFoundation.cs look for the following...

Code:
public static void Designer_Stairs( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				/* Client chose to add stairs
				 *  - Read data detailing stair type and location
				 *  - Validate stair multi ID
				 *  - Add the stairs
				 *     - Load data describing the stair components
				 *     - Insert described components
				 *  - Update revision
				 */

				// Read data detailing stair type and location
				int itemID = pvSrc.ReadInt32();
				int x = pvSrc.ReadInt32();
				int y = pvSrc.ReadInt32();

				// Validate stair multi ID
				DesignState design = context.Foundation.DesignState;

				if ( itemID < 0x1DB0 || [COLOR="Red"]itemID > 0x1DDF ) // Was 0x1DD7[/COLOR]

Can't believe i missed it but there again thats nothing new for me :)

Thats it for me... all working now, any one's still got a problem i'll try to help, just post here. (Off for some home building now to test it all).

EDIT
The only things i've added into the gump code are all within this post so you have as much info as i do here. The only other thing i've done myself was to make sure all if the itemID's were pointing to the right bit of art, as i've mentioned before when i last patched from EA (in the last 7 days i think it was) some of the normal crystal art had moved along in the file, hence changing the item ID numbers by a few but it was enough to throw some of my own items out (tables turning into statues etc etc).

Other things you might consider are using the ML client (not sure if that would help tho tbh)
Make sure the clients fully patched (From EA)
Check itemID's are using the correct bit of art (InsideUO to view it)
 

FingersMcSteal

Sorceror
All i did was used this edit...

Code:
//crystal and shadow
                    if (itemID >= 0x367B && itemID < 0x369B)
                    {
                        int type = (itemID - 0x367B) / 16;
                        DoorFacing facing = (DoorFacing)(((itemID - 0x367B) / 2) % 8);

                        switch (type)
                        {
                            case 0: door = new GenericHouseDoor(facing, 0x367B, 0xEC, 0xF3); break;
                            case 1: door = new GenericHouseDoor(facing, 0x368B, 0xEC, 0xF3); break;
                        }
                    }
                    // add else to if on next line

From this thread, as you'll see there added as a generic door (0x367B is the starting door and 0x368B is where these doors end in the art file). Those numbers refer to the doors graphic ID (which can be viewed with InsideUO).

Does your server use custom maps at all or custom art ? All i had to do was to place the latest version of the tiledata.mul into the folder where the Datapath.cs points to (Since the tiledata.mul has been updated from EA).

And don't forget to RESET any patches if you log in using UOG.

EDIT
The other thing i did was this part... again, all in the housefoundation.cs...

Code:
[COLOR="Red"]case FoundationType.ElvenGrey: corner = 0x2dfb; east = 0x2dfd; south = 0x2dfe; post = 0x2dfc; break;
                case FoundationType.ElvenNatural: corner = 0x2df7; east = 0x2df9; south = 0x2dfa; post = 0x2df8; break;[/COLOR]
                case FoundationType.Crystal: corner = 0x3672; east = 0x3671; south = 0x3670; post = 0x3677; break;
                case FoundationType.Shadow: corner = 0x3614; east = 0x3636; south = 0x3637; post = 0x3617; break;

The 2 extra lines in red were not mentioned in an above post i think. And that was it.
 

bryant

Sorceror
well everything working but

the 5 ml doors the last 2 crystal and shadow do, but rest still dont do anything im fully patched not sure what im missing .i have the same foundation shown a few messages up but with all the new adds:)
 

Erica

Knight
I think once you got everything working then you should post what to add for the doors ,roof , stairs that way no one keeps getting confused just a thought.
 

FingersMcSteal

Sorceror
Pretty much everything i've done to get things working has been added to this thread with as much detail as i can give really, not sure what else i can add but i'll try.

First off, getting the server to deal with the features your after...

Snicker7 covered this one with the part about making a new CS file with the following code in it...

Code:
using System;
using Server;

namespace Server.Misc
{
	public class NewHousingTiles
	{
		public static void Initialize() {
			Server.Network.SupportedFeatures.Value = 0x280; //[s7] 20061025: Adds support for ML and 9th anniversary housing tile sets.
		}
	}
}

The name of this new file you create doesn't matter 'NewHousingTiles.cs' makes sence tho.

The next part by Thistle covered how to add the new house foundations to the house sign gump, so you can select the type of house foundation you wanted. These edits were in the 'HouseFoundation.cs' file...

1st edit...

Code:
public enum FoundationType
	{
		Stone,
		DarkWood,
		LightWood,
		Dungeon,
		Brick,
        ElvenGrey,
        ElvenNatural,
        Crystal,
        Shadow
	}

2nd edit...

Code:
public static void GetFoundationGraphics( FoundationType type, out int east, out int south, out int post, out int corner )
		{
			switch ( type )
			{
				default:
				case FoundationType.DarkWood:	corner = 0x0014; east = 0x0015; south = 0x0016; post = 0x0017; break;
				case FoundationType.LightWood:	corner = 0x00BD; east = 0x00BE; south = 0x00BF; post = 0x00C0; break;
				case FoundationType.Dungeon:	corner = 0x02FD; east = 0x02FF; south = 0x02FE; post = 0x0300; break;
				case FoundationType.Brick:	corner = 0x0041; east = 0x0043; south = 0x0042; post = 0x0044; break;
				case FoundationType.Stone:	corner = 0x0065; east = 0x0064; south = 0x0063; post = 0x0066; break;
                    // MINE
                case FoundationType.ElvenGrey: corner = 0x2dfb; east = 0x2dfd; south = 0x2dfe; post = 0x2dfc; break;
                case FoundationType.ElvenNatural: corner = 0x2df7; east = 0x2df9; south = 0x2dfa; post = 0x2df8; break;
                case FoundationType.Crystal: corner = 0x3672; east = 0x3671; south = 0x3670; post = 0x3677; break;
                case FoundationType.Shadow: corner = 0x3614; east = 0x3636; south = 0x3637; post = 0x3617; break;
			}
		}

3rd edit... This was in HouseGumpAOS.cs...

Code:
private static int[] m_FoundationNumbers = new int[]
			{
				20, 189, 765, 65, 101, 11771, 11767, 0x3672, 0x3614
			};

*** EDIT *** 3.5 rd 1/2 edit :) (ok i'm blind)... in HouseGumpAOS.cs...

around lines 1236...
Code:
[COLOR="Purple"]case 8:
				{
					if ( isOwner && isCustomizable )
					{
						FoundationType newType;

						switch ( index )
						{
							case 0: newType = FoundationType.DarkWood; break;
							case 1: newType = FoundationType.LightWood; break;
							case 2: newType = FoundationType.Dungeon; break;
							case 3: newType = FoundationType.Brick; break;
							case 4: newType = FoundationType.Stone; break;
                                // EDITS HERE
                            case 5: newType = FoundationType.ElvenGrey; break;
                            case 6: newType = FoundationType.ElvenNatural; break;
                            case 7: newType = FoundationType.Crystal; break;
                            case 8: newType = FoundationType.Shadow; break;
							default: return;
						}

						foundation.Type = newType;

						DesignState state = foundation.BackupState;
						HouseFoundation.ApplyFoundation( newType, state.Components );
						state.OnRevised();[/COLOR]

4th edit... Back to the HouseFoundation.cs...

Code:
public void AddFixtures( Mobile from, MultiTileEntry[] list )
		{
			if ( m_Fixtures == null )
				m_Fixtures = new ArrayList();

			uint keyValue = 0;

			for ( int i = 0; i < list.Length; ++i )
			{
				MultiTileEntry mte = list[i];
				int itemID = mte.m_ItemID & 0x3FFF;

				if ( itemID >= 0x181D && itemID < 0x1829 )
				{
					HouseTeleporter tp = new HouseTeleporter( itemID );

					AddFixture( tp, mte );
				}
				else
				{
					BaseDoor door = null;

                    // MINE
                    //crystal and shadow
                    if (itemID >= 0x367B && itemID < 0x369B)
                    {
                        int type = (itemID - 0x367B) / 16;
                        DoorFacing facing = (DoorFacing)(((itemID - 0x367B) / 2) % 8);

                        switch (type)
                        {
                            case 0: door = new GenericHouseDoor(facing, 0x367B, 0xEC, 0xF3); break;
                            case 1: door = new GenericHouseDoor(facing, 0x368B, 0xEC, 0xF3); break;
                        }
                    }
                    // add else to if on next line

                    else if ( itemID >= 0x675 && itemID < 0x6F5 )
					{

5th edit... HouseFoundation.cs again...

Code:
public static bool IsFixture( int itemID )
		{
			itemID &= 0x3FFF;

            // MINE
            // crystal and shadow
            if (itemID >= 0x367B && itemID < 0x369B)
                return true;
            //

6th edit... Roofs, again in HouseFoundation.cs...

Code:
public static bool IsRoofTile( int id )
		{
			id &= 0x3FFF;

            if ((id >= 0x05b3 && id <= 0x05a3) || (id >= 0x2148 && id <= 0x21f0) || (id >= 0x23be && id <= 0x23ff) || (id >= 0x26da && id <= 0x2935) || (id >= 0x2c24 && id <= 0x2c7d) || (id >= 0x35BE && id <= 0x35D1) || (id >= 0x3623 && id <= 0x3635) || (id >= 0x2B81 && id <= 0x2BA8))
				return true;

			return false;
		}

7th edit... Got the stairs to work...

Code:
public static void Designer_Stairs( NetState state, IEntity e, EncodedReader pvSrc )
		{
			Mobile from = state.Mobile;
			DesignContext context = DesignContext.Find( from );

			if ( context != null )
			{
				/* Client chose to add stairs
				 *  - Read data detailing stair type and location
				 *  - Validate stair multi ID
				 *  - Add the stairs
				 *     - Load data describing the stair components
				 *     - Insert described components
				 *  - Update revision
				 */

				// Read data detailing stair type and location
				int itemID = pvSrc.ReadInt32();
				int x = pvSrc.ReadInt32();
				int y = pvSrc.ReadInt32();

				// Validate stair multi ID
				DesignState design = context.Foundation.DesignState;

				if ( itemID < 0x1DB0 || itemID > 0x1DDF ) // Was 0x1DD7
				{

And thats basically all i've done to get things working.

Bare in mind that you will need to make sure you have an up to date tiledata.mul which came with the latest patches from EA (There client version is 5.0.6c now) and also if you have any custom art added it may throw the art ID numbers out by a few digits.

I've posted pretty much straight forward what i've done to my server but you'll have to remember not all free servers are the same, like some have custom art added so thats going to (I imagine) cause a few issues but nothing to complicated to figure out.

I also had InsideUO running at the same time i went through the file to make sure the tileID's and art work all matched up, as i've explained, the last few patches from EA did 'shunt' the art a few ID numbers across for some of the crystal items.

I did forget myself a couple of times after running the test server to reset the patches, which meant the server kept using an old version of the tiledata.mul (if you dont use custom maps this shouldn't effect you too much) but thats what had me stumped a couple times. The tiledata.mul tells the art how to function, I.E. thats a surface, thats a wall etc etc, which i tripped over a couple of times on.

It's pretty much a case of if the tileID's are picking the right art and you have the up to date files then you shouldnt have too many problems, however if you run a heavily art customized shard it could turn out you might have a few 'hickups' along the way, but most of the information you looking for is here, just a case of going through it one step at a time.

Hope this helps.
 

mitty

Sorceror
silly question....

I can't find my Tiledata.mul only a Tiledata file in my files.C:program files\EAGames\SamuraiEmpire\. I'm running everything exactly like it was posted here, my ongoing problem is the Elven doors place, but on commiting the design they dissapear?? I'm running a 1.0 hybrid shard no custom artwork. Yes I followed everything posted here to a T and everything compiles and works except these things i just described. Any Insight is great guys, so can you point me there? TY :D (Yes I'm patched up totally cause I play real UO)
 

Kenko

Page
what runuo version do you use? :S

I don't have the IsRoofTile method, neither a line like:
Code:
if ( itemID < 0x1DB0 || itemID > 0x1DDF ) // Was 0x1DD7
it actually says:
Code:
if ( !Verification.IsMultiValid( itemID ) )
in my files.. (svn 104)
 
Top