package JAKJ . RedstoneInMotion ;

public class CarriagePackage
{
	public final net . minecraft . world . WorldServer World ;

	public final BlockRecord DriveRecord ;

	public final boolean DriveIsAnchored ;

	public final BlockRecord AnchorRecord ;

	public final Directions MotionDirection ;

	public CarriagePackage ( CarriageDriveEntity Drive , CarriageEntity Anchor , Directions MotionDirection )
	{
		World = ( net . minecraft . world . WorldServer ) Drive . worldObj ;

		DriveRecord = new BlockRecord ( Drive . xCoord , Drive . yCoord , Drive . zCoord ) ;

		DriveRecord . Identify ( World ) ;

		DriveIsAnchored = Drive . Anchored ( ) ;

		AnchorRecord = new BlockRecord ( Anchor . xCoord , Anchor . yCoord , Anchor . zCoord ) ;

		AnchorRecord . Identify ( World ) ;

		this . MotionDirection = MotionDirection ;
	}

	public boolean MatchesCarriageType ( BlockRecord Record )
	{
		if ( Record . Id == AnchorRecord . Id )
		{
			if ( Record . Meta == AnchorRecord . Meta )
			{
				return ( true ) ;
			}
		}

		return ( false ) ;
	}

	public final BlockRecordSet Blocks = new BlockRecordSet ( ) ;

	public static int MaxBlockCount ;

	public int MinX = Integer . MAX_VALUE ;
	public int MinY = Integer . MAX_VALUE ;
	public int MinZ = Integer . MAX_VALUE ;

	public int MaxX = Integer . MIN_VALUE ;
	public int MaxY = Integer . MIN_VALUE ;
	public int MaxZ = Integer . MIN_VALUE ;

	public void AddBlock ( BlockRecord Record ) throws CarriageMotionException
	{
		if ( ( MotionDirection == Directions . PosY ) && ( Record . Y >= 254 ) )
		{
			throw ( new CarriageMotionException ( "cannot move carriage above height limit" ) ) ;
		}

		if ( ( MotionDirection == Directions . NegY ) && ( Record . Y <= 0 ) )
		{
			throw ( new CarriageMotionException ( "cannot move carriage below depth limit" ) ) ;
		}

		if ( CarriagePackageBlacklist . Lookup ( Record ) )
		{
			throw ( new CarriageMotionException ( "carriage contains system-wide blacklisted block at (" + Record . X + "," + Record . Y + "," + Record . Z + ")" ) ) ;
		}

		Blocks . add ( Record ) ;

		if ( MaxBlockCount > 0 )
		{
			if ( Blocks . size ( ) > MaxBlockCount )
			{
				throw ( new CarriageMotionException ( "carriage exceeds maximum size of " + MaxBlockCount + " blocks" ) ) ;
			}
		}

		MinX = Math . min ( MinX , Record . X ) ;
		MinY = Math . min ( MinY , Record . Y ) ;
		MinZ = Math . min ( MinZ , Record . Z ) ;

		MaxX = Math . max ( MaxX , Record . X ) ;
		MaxY = Math . max ( MaxY , Record . Y ) ;
		MaxZ = Math . max ( MaxZ , Record . Z ) ;
	}

	public void FailBecauseObstructed ( BlockRecord Record , String Type ) throws CarriageMotionException
	{
		throw ( new CarriageMotionException ( "carriage motion obstructed by " + Type + " at (" + Record . X + "," + Record . Y + "," + Record . Z + ")" ) ) ;
	}

	public static boolean ObstructedByLiquids ;

	public static boolean ObstructedByFragileBlocks ;

	public void AssertNotObstruction ( BlockRecord Record ) throws CarriageMotionException
	{
		if ( Blocks . contains ( Record ) )
		{
			return ;
		}

		if ( World . isAirBlock ( Record . X , Record . Y , Record . Z ) )
		{
			return ;
		}

		if ( Block . Get ( World . getBlockId ( Record . X , Record . Y , Record . Z ) ) . blockMaterial . isLiquid ( ) )
		{
			if ( ObstructedByLiquids )
			{
				FailBecauseObstructed ( Record , "liquid" ) ;
			}

			return ;
		}

		if ( ! ( ( net . minecraft . block . BlockFlowing ) net . minecraft . block . Block . waterMoving ) . blockBlocksFlow ( World , Record . X , Record . Y , Record . Z ) )
		{
			if ( ObstructedByFragileBlocks )
			{
				FailBecauseObstructed ( Record , "fragile block" ) ;
			}

			return ;
		}

		FailBecauseObstructed ( Record , "block" ) ;
	}

	public final BlockRecordSet PotentialObstructions = new BlockRecordSet ( ) ;

	public void AddPotentialObstruction ( BlockRecord Record )
	{
		PotentialObstructions . add ( Record ) ;
	}

	public final NbtList PendingBlockUpdates = new NbtList ( ) ;

	public void StorePendingBlockUpdateRecord ( net . minecraft . world . NextTickListEntry PendingBlockUpdate , long WorldTime )
	{
		NbtCompound PendingBlockUpdateRecord = new NbtCompound ( ) ;

		PendingBlockUpdateRecord . setInteger ( "X" , PendingBlockUpdate . xCoord ) ;
		PendingBlockUpdateRecord . setInteger ( "Y" , PendingBlockUpdate . yCoord ) ;
		PendingBlockUpdateRecord . setInteger ( "Z" , PendingBlockUpdate . zCoord ) ;

		PendingBlockUpdateRecord . setInteger ( "Id" , PendingBlockUpdate . blockID ) ;

		PendingBlockUpdateRecord . setInteger ( "Delay" , ( int ) ( PendingBlockUpdate . scheduledTime - WorldTime ) ) ;

		PendingBlockUpdateRecord . setInteger ( "Foo" , PendingBlockUpdate . field_82754_f ) ;

		PendingBlockUpdates . appendTag ( PendingBlockUpdateRecord ) ;
	}

	public void Finalize ( ) throws CarriageMotionException
	{
		for ( BlockRecord PotentialObstruction : PotentialObstructions )
		{
			AssertNotObstruction ( PotentialObstruction ) ;
		}

/*MCPC-iterate over tickEntryQueue, call removeifneeded*/
		long WorldTime = World . worldInfo . getWorldTotalTime ( ) ;

		try
		{
			java . util . Iterator PendingBlockUpdateSetIterator = World . pendingTickListEntries . iterator ( ) ;

			while ( PendingBlockUpdateSetIterator . hasNext ( ) )
			{
				net . minecraft . world . NextTickListEntry PendingBlockUpdate = ( net . minecraft . world . NextTickListEntry ) PendingBlockUpdateSetIterator . next ( ) ;

				if ( Blocks . contains ( new BlockRecord ( PendingBlockUpdate . xCoord , PendingBlockUpdate . yCoord , PendingBlockUpdate . zCoord ) ) )
				{
					PendingBlockUpdateSetIterator . remove ( ) ;

					World . field_73064_N . remove ( PendingBlockUpdate ) ;

					StorePendingBlockUpdateRecord ( PendingBlockUpdate , WorldTime ) ;
				}
			}
		}
		catch ( Throwable VanillaThrowable )
		{
			try
			{
				java . lang . reflect . Field PendingBlockUpdateSetField = net . minecraft . world . WorldServer . class . getDeclaredField ( "tickEntryQueue" ) ;

				PendingBlockUpdateSetField . setAccessible ( true ) ;

				java . util . Set PendingBlockUpdateSet = ( java . util . Set ) PendingBlockUpdateSetField . get ( World ) ;

				while ( true )
				{
					net . minecraft . world . NextTickListEntry PendingBlockUpdate = null ;

					for ( Object Target : PendingBlockUpdateSet )
					{
						net . minecraft . world . NextTickListEntry TargetPendingBlockUpdate = ( net . minecraft . world . NextTickListEntry ) Target ;

						if ( Blocks . contains ( new BlockRecord ( TargetPendingBlockUpdate . xCoord , TargetPendingBlockUpdate . yCoord , TargetPendingBlockUpdate . zCoord ) ) )
						{
							PendingBlockUpdate = TargetPendingBlockUpdate ;

							break ;
						}
					}

					if ( PendingBlockUpdate == null )
					{
						break ;
					}

					StorePendingBlockUpdateRecord ( PendingBlockUpdate , WorldTime ) ;

					java . lang . reflect . Method RemovePendingBlockUpdate = net . minecraft . world . WorldServer . class . getDeclaredMethod
					(
						"removeNextTickIfNeeded" , net . minecraft . world . NextTickListEntry . class
					) ;

					RemovePendingBlockUpdate . setAccessible ( true ) ;

					RemovePendingBlockUpdate . invoke ( World , PendingBlockUpdate ) ;
				}
			}
			catch ( Throwable McpcThrowable )
			{
				McpcThrowable . printStackTrace ( ) ;

				VanillaThrowable . printStackTrace ( ) ;
			}
		}
	}
}
