2013-12-10 05:31:42 -05:00
2012-06-14 09:06:06 -04:00
# include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
2012-09-23 18:09:57 -04:00
# include "RedstoneSimulator.h"
2013-05-28 15:12:47 -04:00
# include "../BlockEntities/DropSpenserEntity.h"
2013-12-14 11:52:22 -05:00
# include "../BlockEntities/NoteEntity.h"
2013-11-18 17:30:34 -05:00
# include "../Entities/TNTEntity.h"
2013-06-04 15:22:14 -04:00
# include "../Blocks/BlockTorch.h"
2013-11-18 17:30:34 -05:00
# include "../Blocks/BlockDoor.h"
2012-10-13 05:53:28 -04:00
# include "../Piston.h"
2013-12-24 10:02:55 -05:00
# include "../Tracer.h"
2012-06-14 09:06:06 -04:00
2012-10-06 16:04:58 -04:00
2012-06-14 09:06:06 -04:00
2013-03-03 10:06:01 -05:00
cRedstoneSimulator : : cRedstoneSimulator ( cWorld & a_World )
2012-06-14 09:06:06 -04:00
: super ( a_World )
{
}
cRedstoneSimulator : : ~ cRedstoneSimulator ( )
{
}
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : AddBlock ( int a_BlockX , int a_BlockY , int a_BlockZ , cChunk * a_Chunk )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
if ( ( a_Chunk = = NULL ) | | ! a_Chunk - > IsValid ( ) )
{
return ;
}
else if ( ( a_BlockY < 0 ) | | ( a_BlockY > cChunkDef : : Height ) )
2013-03-03 10:06:01 -05:00
{
return ;
}
2013-11-18 17:30:34 -05:00
2013-03-03 10:06:01 -05:00
int RelX = a_BlockX - a_Chunk - > GetPosX ( ) * cChunkDef : : Width ;
int RelZ = a_BlockZ - a_Chunk - > GetPosZ ( ) * cChunkDef : : Width ;
2013-11-18 17:30:34 -05:00
if ( ! IsAllowedBlock ( a_Chunk - > GetBlock ( RelX , a_BlockY , RelZ ) ) )
2013-03-03 10:06:01 -05:00
{
2013-11-18 17:30:34 -05:00
return ;
}
// Check for duplicates:
cRedstoneSimulatorChunkData & ChunkData = a_Chunk - > GetRedstoneSimulatorData ( ) ;
2013-12-13 20:14:09 -05:00
for ( cRedstoneSimulatorChunkData : : const_iterator itr = ChunkData . begin ( ) ; itr ! = ChunkData . end ( ) ; + + itr )
2013-11-18 17:30:34 -05:00
{
if ( ( itr - > x = = RelX ) & & ( itr - > y = = a_BlockY ) & & ( itr - > z = = RelZ ) )
2013-03-03 10:06:01 -05:00
{
2013-11-18 17:30:34 -05:00
return ;
2013-03-03 10:06:01 -05:00
}
2013-11-18 17:30:34 -05:00
}
ChunkData . push_back ( cCoordWithInt ( RelX , a_BlockY , RelZ ) ) ;
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : SimulateChunk ( float a_Dt , int a_ChunkX , int a_ChunkZ , cChunk * a_Chunk )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
cRedstoneSimulatorChunkData & ChunkData = a_Chunk - > GetRedstoneSimulatorData ( ) ;
if ( ChunkData . empty ( ) )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
return ;
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
int BaseX = a_Chunk - > GetPosX ( ) * cChunkDef : : Width ;
int BaseZ = a_Chunk - > GetPosZ ( ) * cChunkDef : : Width ;
2013-11-29 19:30:49 -05:00
// Check to see if PoweredBlocks have invalid items (source is air or unpowered)
2013-12-14 07:10:05 -05:00
for ( PoweredBlocksList : : iterator itr = m_PoweredBlocks . begin ( ) ; itr ! = m_PoweredBlocks . end ( ) ; )
2012-06-14 09:06:06 -04:00
{
2013-12-13 20:14:09 -05:00
int RelX = itr - > a_SourcePos . x - a_ChunkX * cChunkDef : : Width ;
int RelZ = itr - > a_SourcePos . z - a_ChunkZ * cChunkDef : : Width ;
2013-12-15 07:17:29 -05:00
int DestRelX = itr - > a_BlockPos . x - a_ChunkX * cChunkDef : : Width ;
int DestRelZ = itr - > a_BlockPos . z - a_ChunkZ * cChunkDef : : Width ;
2013-11-29 19:30:49 -05:00
BLOCKTYPE SourceBlockType ;
NIBBLETYPE SourceBlockMeta ;
2013-12-15 07:17:29 -05:00
BLOCKTYPE DestBlockType ;
if (
! a_Chunk - > UnboundedRelGetBlock ( RelX , itr - > a_SourcePos . y , RelZ , SourceBlockType , SourceBlockMeta ) | |
2013-12-17 18:05:42 -05:00
! a_Chunk - > UnboundedRelGetBlockType ( DestRelX , itr - > a_BlockPos . y , DestRelZ , DestBlockType )
2013-12-15 07:17:29 -05:00
)
2012-06-14 09:06:06 -04:00
{
2012-12-16 02:07:30 -05:00
continue ;
}
2013-11-18 17:30:34 -05:00
2013-12-13 20:14:09 -05:00
if ( SourceBlockType ! = itr - > a_SourceBlock )
2012-12-16 02:07:30 -05:00
{
2013-12-13 20:14:09 -05:00
LOGD ( " cRedstoneSimulator: Erased block %s from powered blocks list due to present/past block type mismatch " , ItemToFullString ( itr - > a_SourceBlock ) . c_str ( ) ) ;
2013-12-14 14:29:50 -05:00
itr = m_PoweredBlocks . erase ( itr ) ;
2013-11-29 19:30:49 -05:00
}
else if (
// Changeable sources
( ( SourceBlockType = = E_BLOCK_REDSTONE_WIRE ) & & ( SourceBlockMeta = = 0 ) ) | |
( ( SourceBlockType = = E_BLOCK_LEVER ) & & ! IsLeverOn ( SourceBlockMeta ) ) | |
( ( SourceBlockType = = E_BLOCK_DETECTOR_RAIL ) & & ( SourceBlockMeta & 0x08 ) = = 0x08 ) | |
2013-12-24 10:02:55 -05:00
( ( ( SourceBlockType = = E_BLOCK_STONE_BUTTON ) | | ( SourceBlockType = = E_BLOCK_WOODEN_BUTTON ) ) & & ( ! IsButtonOn ( SourceBlockMeta ) ) ) | |
( ( ( SourceBlockType = = E_BLOCK_STONE_PRESSURE_PLATE ) | | ( SourceBlockType = = E_BLOCK_WOODEN_PRESSURE_PLATE ) ) & & ( SourceBlockMeta = = 0 ) )
2013-11-29 19:30:49 -05:00
)
{
2013-12-13 20:14:09 -05:00
LOGD ( " cRedstoneSimulator: Erased block %s from powered blocks list due to present/past metadata mismatch " , ItemToFullString ( itr - > a_SourceBlock ) . c_str ( ) ) ;
2013-12-14 14:29:50 -05:00
itr = m_PoweredBlocks . erase ( itr ) ;
2013-11-29 19:30:49 -05:00
}
2013-12-23 10:22:05 -05:00
else if ( SourceBlockType = = E_BLOCK_DAYLIGHT_SENSOR )
{
if ( ! a_Chunk - > IsLightValid ( ) )
{
m_World . QueueLightChunk ( a_ChunkX , a_ChunkZ ) ;
itr + + ;
continue ;
}
else
{
NIBBLETYPE SkyLight ;
a_Chunk - > UnboundedRelGetBlockSkyLight ( RelX , itr - > a_SourcePos . y + 1 , RelZ , SkyLight ) ;
if ( a_Chunk - > GetTimeAlteredLight ( SkyLight ) < = 8 ) // Could use SkyLight - m_World.GetSkyDarkness();
{
LOGD ( " cRedstoneSimulator: Erased daylight sensor from powered blocks list due to insufficient light level " ) ;
itr = m_PoweredBlocks . erase ( itr ) ;
}
else
{
itr + + ;
continue ;
}
}
}
2013-12-15 07:17:29 -05:00
else if ( ( SourceBlockType = = E_BLOCK_REDSTONE_WIRE ) & & ( DestBlockType = = E_BLOCK_REDSTONE_WIRE ) )
{
// It is simply not allowed that a wire powers another wire, presuming that data here is sane and a dest and source are beside each other
2013-12-23 10:22:05 -05:00
LOGD ( " cRedstoneSimulator: Erased redstone wire from powered blocks list because its source was also wire " ) ;
2013-12-15 07:17:29 -05:00
itr = m_PoweredBlocks . erase ( itr ) ;
}
2013-11-29 19:30:49 -05:00
else
{
itr + + ;
}
}
2013-11-20 17:54:28 -05:00
2013-11-29 19:30:49 -05:00
// Check to see if LinkedPoweredBlocks have invalid items: source, block powered through, or power destination block has changed
2013-12-14 07:10:05 -05:00
for ( LinkedBlocksList : : iterator itr = m_LinkedPoweredBlocks . begin ( ) ; itr ! = m_LinkedPoweredBlocks . end ( ) ; )
2013-11-29 19:30:49 -05:00
{
2013-12-13 20:14:09 -05:00
int RelX = itr - > a_SourcePos . x - a_ChunkX * cChunkDef : : Width ;
int RelZ = itr - > a_SourcePos . z - a_ChunkZ * cChunkDef : : Width ;
int MidRelX = itr - > a_MiddlePos . x - a_ChunkX * cChunkDef : : Width ;
int MidRelZ = itr - > a_MiddlePos . z - a_ChunkZ * cChunkDef : : Width ;
2013-11-29 19:30:49 -05:00
BLOCKTYPE SourceBlockType ;
NIBBLETYPE SourceBlockMeta ;
BLOCKTYPE MiddleBlockType ;
if (
2013-12-13 20:14:09 -05:00
! a_Chunk - > UnboundedRelGetBlock ( RelX , itr - > a_SourcePos . y , RelZ , SourceBlockType , SourceBlockMeta ) | |
! a_Chunk - > UnboundedRelGetBlockType ( MidRelX , itr - > a_MiddlePos . y , MidRelZ , MiddleBlockType )
2013-11-29 19:30:49 -05:00
)
{
continue ;
}
2013-11-18 17:30:34 -05:00
2013-12-13 20:14:09 -05:00
if ( SourceBlockType ! = itr - > a_SourceBlock )
2013-11-29 19:30:49 -05:00
{
2013-12-13 20:14:09 -05:00
LOGD ( " cRedstoneSimulator: Erased block %s from linked powered blocks list due to present/past block type mismatch " , ItemToFullString ( itr - > a_SourceBlock ) . c_str ( ) ) ;
2013-12-14 14:29:50 -05:00
itr = m_LinkedPoweredBlocks . erase ( itr ) ;
2013-11-29 19:30:49 -05:00
}
2013-12-13 20:14:09 -05:00
else if ( MiddleBlockType ! = itr - > a_MiddleBlock )
2013-11-29 19:30:49 -05:00
{
2013-12-13 20:14:09 -05:00
LOGD ( " cRedstoneSimulator: Erased block %s from linked powered blocks list due to present/past middle block mismatch " , ItemToFullString ( itr - > a_SourceBlock ) . c_str ( ) ) ;
2013-12-14 14:29:50 -05:00
itr = m_LinkedPoweredBlocks . erase ( itr ) ;
2013-11-29 19:30:49 -05:00
}
else if (
// Things that can send power through a block but which depends on meta
( ( SourceBlockType = = E_BLOCK_REDSTONE_WIRE ) & & ( SourceBlockMeta = = 0 ) ) | |
( ( SourceBlockType = = E_BLOCK_LEVER ) & & ! IsLeverOn ( SourceBlockMeta ) ) | |
( ( ( SourceBlockType = = E_BLOCK_STONE_BUTTON ) | | ( SourceBlockType = = E_BLOCK_WOODEN_BUTTON ) ) & & ( ! IsButtonOn ( SourceBlockMeta ) ) )
)
{
2013-12-13 20:14:09 -05:00
LOGD ( " cRedstoneSimulator: Erased block %s from linked powered blocks list due to present/past metadata mismatch " , ItemToFullString ( itr - > a_SourceBlock ) . c_str ( ) ) ;
2013-12-14 14:29:50 -05:00
itr = m_LinkedPoweredBlocks . erase ( itr ) ;
2013-11-29 19:30:49 -05:00
}
else
{
itr + + ;
2012-12-16 02:07:30 -05:00
}
2013-11-29 19:30:49 -05:00
}
2012-06-14 09:06:06 -04:00
2013-12-14 07:10:05 -05:00
for ( SimulatedPlayerToggleableList : : iterator itr = m_SimulatedPlayerToggleableBlocks . begin ( ) ; itr ! = m_SimulatedPlayerToggleableBlocks . end ( ) ; )
2013-12-07 09:41:58 -05:00
{
2013-12-13 20:14:09 -05:00
int RelX = itr - > a_BlockPos . x - a_ChunkX * cChunkDef : : Width ;
int RelZ = itr - > a_BlockPos . z - a_ChunkZ * cChunkDef : : Width ;
2013-12-07 09:41:58 -05:00
BLOCKTYPE SourceBlockType ;
2013-12-13 20:14:09 -05:00
if ( ! a_Chunk - > UnboundedRelGetBlockType ( RelX , itr - > a_BlockPos . y , RelZ , SourceBlockType ) )
2013-12-07 09:41:58 -05:00
{
continue ;
}
else if ( ! IsAllowedBlock ( SourceBlockType ) )
{
2013-12-14 07:10:05 -05:00
LOGD ( " cRedstoneSimulator: Erased block %s from toggleable simulated list as block is no longer redstone " , ItemToFullString ( SourceBlockType ) . c_str ( ) ) ;
2013-12-07 09:41:58 -05:00
itr = m_SimulatedPlayerToggleableBlocks . erase ( itr ) ;
}
else
{
2013-12-19 10:57:15 -05:00
itr + + ;
}
}
for ( RepeatersDelayList : : iterator itr = m_RepeatersDelayList . begin ( ) ; itr ! = m_RepeatersDelayList . end ( ) ; )
{
int RelX = itr - > a_BlockPos . x - a_ChunkX * cChunkDef : : Width ;
int RelZ = itr - > a_BlockPos . z - a_ChunkZ * cChunkDef : : Width ;
BLOCKTYPE SourceBlockType ;
if ( ! a_Chunk - > UnboundedRelGetBlockType ( RelX , itr - > a_BlockPos . y , RelZ , SourceBlockType ) )
{
continue ;
}
if ( ( SourceBlockType ! = E_BLOCK_REDSTONE_REPEATER_ON ) & & ( SourceBlockType ! = E_BLOCK_REDSTONE_REPEATER_OFF ) )
{
itr = m_RepeatersDelayList . erase ( itr ) ;
continue ;
}
itr + + ;
2013-12-07 09:41:58 -05:00
}
2013-12-14 07:10:05 -05:00
for ( cRedstoneSimulatorChunkData : : iterator dataitr = ChunkData . begin ( ) , end = ChunkData . end ( ) ; dataitr ! = end ; )
2013-11-29 19:30:49 -05:00
{
BLOCKTYPE BlockType = a_Chunk - > GetBlock ( dataitr - > x , dataitr - > y , dataitr - > z ) ;
if ( ! IsAllowedBlock ( BlockType ) )
2012-12-16 02:07:30 -05:00
{
2013-11-29 19:30:49 -05:00
dataitr = ChunkData . erase ( dataitr ) ;
continue ;
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
2013-11-29 19:30:49 -05:00
// PoweredBlock and LinkedPoweredBlock list was fine, now to the actual handling
2013-11-18 17:30:34 -05:00
int a_X = BaseX + dataitr - > x ;
int a_Z = BaseZ + dataitr - > z ;
switch ( BlockType )
2012-06-14 09:06:06 -04:00
{
2013-12-20 16:19:13 -05:00
case E_BLOCK_BLOCK_OF_REDSTONE : HandleRedstoneBlock ( a_X , dataitr - > y , a_Z ) ; break ;
case E_BLOCK_LEVER : HandleRedstoneLever ( a_X , dataitr - > y , a_Z ) ; break ;
case E_BLOCK_TNT : HandleTNT ( a_X , dataitr - > y , a_Z ) ; break ;
2013-11-29 17:27:08 -05:00
case E_BLOCK_TRAPDOOR : HandleTrapdoor ( a_X , dataitr - > y , a_Z ) ; break ;
2013-12-20 16:19:13 -05:00
case E_BLOCK_REDSTONE_WIRE : HandleRedstoneWire ( a_X , dataitr - > y , a_Z ) ; break ;
2013-12-14 11:52:22 -05:00
case E_BLOCK_NOTE_BLOCK : HandleNoteBlock ( a_X , dataitr - > y , a_Z ) ; break ;
2013-12-20 16:19:13 -05:00
case E_BLOCK_DAYLIGHT_SENSOR : HandleDaylightSensor ( a_X , dataitr - > y , a_Z ) ; break ;
2013-11-18 17:30:34 -05:00
case E_BLOCK_REDSTONE_TORCH_OFF :
case E_BLOCK_REDSTONE_TORCH_ON :
{
HandleRedstoneTorch ( a_X , dataitr - > y , a_Z , BlockType ) ;
break ;
}
case E_BLOCK_STONE_BUTTON :
case E_BLOCK_WOODEN_BUTTON :
{
HandleRedstoneButton ( a_X , dataitr - > y , a_Z , BlockType ) ;
break ;
}
case E_BLOCK_REDSTONE_REPEATER_OFF :
case E_BLOCK_REDSTONE_REPEATER_ON :
{
HandleRedstoneRepeater ( a_X , dataitr - > y , a_Z , BlockType ) ;
break ;
}
case E_BLOCK_PISTON :
case E_BLOCK_STICKY_PISTON :
{
HandlePiston ( a_X , dataitr - > y , a_Z ) ;
break ;
}
case E_BLOCK_REDSTONE_LAMP_OFF :
case E_BLOCK_REDSTONE_LAMP_ON :
{
HandleRedstoneLamp ( a_X , dataitr - > y , a_Z , BlockType ) ;
break ;
}
case E_BLOCK_DISPENSER :
case E_BLOCK_DROPPER :
{
HandleDropSpenser ( a_X , dataitr - > y , a_Z ) ;
break ;
}
case E_BLOCK_WOODEN_DOOR :
case E_BLOCK_IRON_DOOR :
{
HandleDoor ( a_X , dataitr - > y , a_Z ) ;
break ;
}
case E_BLOCK_ACTIVATOR_RAIL :
case E_BLOCK_DETECTOR_RAIL :
case E_BLOCK_POWERED_RAIL :
{
HandleRail ( a_X , dataitr - > y , a_Z , BlockType ) ;
break ;
}
2013-12-24 10:02:55 -05:00
case E_BLOCK_WOODEN_PRESSURE_PLATE :
case E_BLOCK_STONE_PRESSURE_PLATE :
{
HandlePressurePlate ( a_X , dataitr - > y , a_Z , BlockType ) ;
break ;
}
2012-06-14 09:06:06 -04:00
}
2013-12-23 10:22:05 -05:00
dataitr + + ;
2012-06-14 09:06:06 -04:00
}
}
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : HandleRedstoneTorch ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_MyState )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
static const struct / / Define which directions the torch can power
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
int x , y , z ;
} gCrossCoords [ ] =
{
{ 1 , 0 , 0 } ,
{ - 1 , 0 , 0 } ,
{ 0 , 0 , 1 } ,
{ 0 , 0 , - 1 } ,
{ 0 , 1 , 0 } ,
} ;
if ( a_MyState = = E_BLOCK_REDSTONE_TORCH_ON )
{
// Check if the block the torch is on is powered
int X = a_BlockX ; int Y = a_BlockY ; int Z = a_BlockZ ;
AddFaceDirection ( X , Y , Z , cBlockTorchHandler : : MetaDataToDirection ( m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) ) , true ) ; // Inverse true to get the block torch is on
2013-12-13 21:40:54 -05:00
if ( AreCoordsDirectlyPowered ( X , Y , Z ) )
2013-11-18 17:30:34 -05:00
{
// There was a match, torch goes off
2013-12-09 18:43:26 -05:00
m_World . SetBlock ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_TORCH_OFF , m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) ) ;
2013-11-18 17:30:34 -05:00
return ;
}
// Torch still on, make all 4(X, Z) + 1(Y) sides powered
2013-12-01 07:58:04 -05:00
for ( size_t i = 0 ; i < ARRAYCOUNT ( gCrossCoords ) ; i + + )
2013-06-22 04:42:49 -04:00
{
2013-11-18 17:30:34 -05:00
BLOCKTYPE Type = m_World . GetBlock ( a_BlockX + gCrossCoords [ i ] . x , a_BlockY + gCrossCoords [ i ] . y , a_BlockZ + gCrossCoords [ i ] . z ) ;
2013-12-01 07:58:04 -05:00
if ( i + 1 < ARRAYCOUNT ( gCrossCoords ) ) // Sides of torch, not top (top is last)
2013-11-18 17:30:34 -05:00
{
if (
( ( IsMechanism ( Type ) ) | | ( Type = = E_BLOCK_REDSTONE_WIRE ) ) & & // Is it a mechanism or wire? Not block/other torch etc.
( ! Vector3i ( a_BlockX + gCrossCoords [ i ] . x , a_BlockY + gCrossCoords [ i ] . y , a_BlockZ + gCrossCoords [ i ] . z ) . Equals ( Vector3i ( X , Y , Z ) ) ) // CAN'T power block is that it is on
)
{
SetBlockPowered ( a_BlockX + gCrossCoords [ i ] . x , a_BlockY + gCrossCoords [ i ] . y , a_BlockZ + gCrossCoords [ i ] . z , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_TORCH_ON ) ;
}
}
else
{
// Top side, power whatever is there, including blocks
SetBlockPowered ( a_BlockX + gCrossCoords [ i ] . x , a_BlockY + gCrossCoords [ i ] . y , a_BlockZ + gCrossCoords [ i ] . z , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_TORCH_ON ) ;
2013-11-20 17:54:28 -05:00
// Power all blocks surrounding block above torch
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_YP , E_BLOCK_REDSTONE_TORCH_ON ) ;
2013-11-18 17:30:34 -05:00
}
2013-06-22 04:42:49 -04:00
}
2013-11-18 17:30:34 -05:00
2013-11-20 17:54:28 -05:00
if ( m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) ! = 0x5 ) // Is torch standing on ground? If NOT (i.e. on wall), power block beneath
2013-06-22 07:45:41 -04:00
{
2013-11-18 17:30:34 -05:00
BLOCKTYPE Type = m_World . GetBlock ( a_BlockX , a_BlockY - 1 , a_BlockZ ) ;
if ( ( IsMechanism ( Type ) ) | | ( Type = = E_BLOCK_REDSTONE_WIRE ) ) // Still can't make a normal block powered though!
{
SetBlockPowered ( a_BlockX , a_BlockY - 1 , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_TORCH_ON ) ;
}
2013-06-22 07:45:41 -04:00
}
2012-06-14 09:06:06 -04:00
}
else
{
2013-11-18 17:30:34 -05:00
// Check if the block the torch is on is powered
int X = a_BlockX ; int Y = a_BlockY ; int Z = a_BlockZ ;
AddFaceDirection ( X , Y , Z , cBlockTorchHandler : : MetaDataToDirection ( m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) ) , true ) ; // Inverse true to get the block torch is on
// See if off state torch can be turned on again
2013-12-13 21:40:54 -05:00
if ( AreCoordsDirectlyPowered ( X , Y , Z ) )
2013-06-22 07:45:41 -04:00
{
2013-11-18 17:30:34 -05:00
return ; // Something matches, torch still powered
2013-06-22 07:45:41 -04:00
}
2013-11-18 17:30:34 -05:00
// Block torch on not powered, can be turned on again!
2013-12-09 18:43:26 -05:00
m_World . SetBlock ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_TORCH_ON , m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) ) ;
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
}
2012-06-14 09:06:06 -04:00
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : HandleRedstoneBlock ( int a_BlockX , int a_BlockY , int a_BlockZ )
{
2013-11-20 17:54:28 -05:00
SetAllDirsAsPowered ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_BLOCK_OF_REDSTONE ) ;
SetBlockPowered ( a_BlockX , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_BLOCK_OF_REDSTONE ) ; // Set self as powered
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : HandleRedstoneLever ( int a_BlockX , int a_BlockY , int a_BlockZ )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
if ( IsLeverOn ( m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) ) )
2012-12-16 02:07:30 -05:00
{
2013-11-20 17:54:28 -05:00
SetAllDirsAsPowered ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_LEVER ) ;
2012-06-14 09:06:06 -04:00
2013-11-18 17:30:34 -05:00
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_XM , E_BLOCK_LEVER ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_XP , E_BLOCK_LEVER ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_YM , E_BLOCK_LEVER ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_YP , E_BLOCK_LEVER ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_ZM , E_BLOCK_LEVER ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_ZP , E_BLOCK_LEVER ) ;
}
}
void cRedstoneSimulator : : HandleRedstoneButton ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_BlockType )
{
if ( IsButtonOn ( m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) ) )
2012-06-14 09:06:06 -04:00
{
2013-11-20 17:54:28 -05:00
SetAllDirsAsPowered ( a_BlockX , a_BlockY , a_BlockZ , a_BlockType ) ;
2013-11-18 17:30:34 -05:00
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_XM , a_BlockType ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_XP , a_BlockType ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_YM , a_BlockType ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_YP , a_BlockType ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_ZM , a_BlockType ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_ZP , a_BlockType ) ;
}
}
2012-06-14 09:06:06 -04:00
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : HandleRedstoneWire ( int a_BlockX , int a_BlockY , int a_BlockZ )
{
static const struct / / Define which directions the wire can receive power from
{
int x , y , z ;
} gCrossCoords [ ] =
{
2013-12-14 14:11:15 -05:00
{ 1 , 0 , 0 } , /* Wires on same level start */
2013-11-18 17:30:34 -05:00
{ - 1 , 0 , 0 } ,
{ 0 , 0 , 1 } ,
2013-12-14 14:11:15 -05:00
{ 0 , 0 , - 1 } , /* Wires on same level stop */
{ 1 , 1 , 0 } , /* Wires one higher, surrounding self start */
2013-11-18 17:30:34 -05:00
{ - 1 , 1 , 0 } ,
{ 0 , 1 , 1 } ,
2013-12-14 14:11:15 -05:00
{ 0 , 1 , - 1 } , /* Wires one higher, surrounding self stop */
{ 1 , - 1 , 0 } , /* Wires one lower, surrounding self start */
2013-11-18 17:30:34 -05:00
{ - 1 , - 1 , 0 } ,
{ 0 , - 1 , 1 } ,
2013-12-14 14:11:15 -05:00
{ 0 , - 1 , - 1 } , /* Wires one lower, surrounding self stop */
2013-11-18 17:30:34 -05:00
} ;
2013-12-15 10:36:20 -05:00
static const struct / / Define which directions the wire will check for repeater prescence
{
int x , y , z ;
} gSideCoords [ ] =
{
{ 1 , 0 , 0 } ,
{ - 1 , 0 , 0 } ,
{ 0 , 0 , 1 } ,
{ 0 , 0 , - 1 } ,
{ 0 , 1 , 0 } ,
} ;
2013-11-18 17:30:34 -05:00
// Check to see if directly beside a power source
if ( AreCoordsPowered ( a_BlockX , a_BlockY , a_BlockZ ) )
{
m_World . SetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ , 15 ) ; // Maximum power
}
else
2012-06-14 09:06:06 -04:00
{
2013-12-09 18:48:06 -05:00
NIBBLETYPE MetaToSet = 0 ;
2013-11-18 17:30:34 -05:00
NIBBLETYPE MyMeta = m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) ;
int TimesMetaSmaller = 0 , TimesFoundAWire = 0 ;
2013-12-01 07:58:04 -05:00
for ( size_t i = 0 ; i < ARRAYCOUNT ( gCrossCoords ) ; i + + ) // Loop through all directions to transfer or receive power
2012-06-14 09:06:06 -04:00
{
2013-12-14 14:11:15 -05:00
if ( ( i > = 4 ) & & ( i < = 7 ) ) // If we are currently checking for wire surrounding ourself one block above...
{
if ( g_BlockIsSolid [ m_World . GetBlock ( a_BlockX , a_BlockY + 1 , a_BlockZ ) ] ) // If there is something solid above us (wire cut off)...
{
continue ; // We don't receive power from that wire
}
}
else if ( ( i > = 8 ) & & ( i < = 11 ) ) // See above, but this is for wire below us
{
if ( g_BlockIsSolid [ m_World . GetBlock ( a_BlockX + gCrossCoords [ i ] . x , a_BlockY + gCrossCoords [ i ] . y + 1 , a_BlockZ + gCrossCoords [ i ] . z ) ] )
{
continue ;
}
}
2013-11-18 17:30:34 -05:00
BLOCKTYPE SurroundType ;
NIBBLETYPE SurroundMeta ;
m_World . GetBlockTypeMeta ( a_BlockX + gCrossCoords [ i ] . x , a_BlockY + gCrossCoords [ i ] . y , a_BlockZ + gCrossCoords [ i ] . z , SurroundType , SurroundMeta ) ;
2012-06-14 09:06:06 -04:00
2013-11-18 17:30:34 -05:00
if ( SurroundType = = E_BLOCK_REDSTONE_WIRE )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
TimesFoundAWire + + ;
if ( SurroundMeta > 1 ) // Wires of power 1 or 0 cannot transfer power TO ME, don't bother checking
2012-06-14 09:06:06 -04:00
{
2013-11-29 19:30:49 -05:00
// Does surrounding wire have a higher power level than self?
// >= to fix a bug where wires bordering each other with the same power level will appear (in terms of meta) to power each other, when they aren't actually in the powered list
if ( SurroundMeta > = MyMeta )
2012-06-14 09:06:06 -04:00
{
2013-12-09 18:48:06 -05:00
MetaToSet = SurroundMeta - 1 ; // To improve performance
2012-06-14 09:06:06 -04:00
}
}
2013-11-18 17:30:34 -05:00
if ( SurroundMeta < MyMeta ) // Go through all surroundings to see if self power is larger than everyone else's
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
TimesMetaSmaller + + ;
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
}
}
2012-06-14 09:06:06 -04:00
2013-11-18 17:30:34 -05:00
if ( TimesMetaSmaller = = TimesFoundAWire )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
// All surrounding metas were smaller - self must have been a wire that was
// transferring power to other wires around.
// However, self not directly powered anymore, so source must have been removed,
// therefore, self must be set to meta zero
m_World . SetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ , 0 ) ;
2013-11-20 17:54:28 -05:00
return ; // No need to process block power sets because self not powered
}
2013-12-09 18:48:06 -05:00
else
{
m_World . SetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ , MetaToSet ) ;
}
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
if ( m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) ! = 0 ) // A powered wire
2012-06-14 09:06:06 -04:00
{
2013-12-15 10:36:20 -05:00
for ( size_t i = 0 ; i < ARRAYCOUNT ( gSideCoords ) ; i + + ) // Look for repeaters immediately surrounding self and try to power them
2013-12-15 08:08:08 -05:00
{
2013-12-15 10:36:20 -05:00
if ( m_World . GetBlock ( a_BlockX + gSideCoords [ i ] . x , a_BlockY + gSideCoords [ i ] . y , a_BlockZ + gSideCoords [ i ] . z ) = = E_BLOCK_REDSTONE_REPEATER_OFF )
2013-12-15 08:08:08 -05:00
{
2013-12-15 10:36:20 -05:00
SetBlockPowered ( a_BlockX + gSideCoords [ i ] . x , a_BlockY + gSideCoords [ i ] . y , a_BlockZ + gSideCoords [ i ] . z , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_WIRE ) ;
2013-12-15 08:08:08 -05:00
}
}
2013-12-15 10:36:20 -05:00
2013-12-14 11:52:22 -05:00
// Wire still powered, power blocks beneath
SetBlockPowered ( a_BlockX , a_BlockY - 1 , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_WIRE ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_YM , E_BLOCK_REDSTONE_WIRE ) ;
2013-11-18 17:30:34 -05:00
switch ( GetWireDirection ( a_BlockX , a_BlockY , a_BlockZ ) )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
case REDSTONE_NONE :
{
2013-11-20 17:54:28 -05:00
SetAllDirsAsPowered ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_WIRE ) ;
2013-11-18 17:30:34 -05:00
2013-11-20 17:54:28 -05:00
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_XM , E_BLOCK_REDSTONE_WIRE ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_XP , E_BLOCK_REDSTONE_WIRE ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_YM , E_BLOCK_REDSTONE_WIRE ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_YP , E_BLOCK_REDSTONE_WIRE ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_ZM , E_BLOCK_REDSTONE_WIRE ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_ZP , E_BLOCK_REDSTONE_WIRE ) ;
2013-11-18 17:30:34 -05:00
break ;
}
case REDSTONE_X_POS :
2012-06-14 09:06:06 -04:00
{
2013-12-14 14:11:15 -05:00
SetBlockPowered ( a_BlockX + 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_WIRE ) ;
2013-11-18 17:30:34 -05:00
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_XP , E_BLOCK_REDSTONE_WIRE ) ;
break ;
}
case REDSTONE_X_NEG :
{
2013-12-14 14:11:15 -05:00
SetBlockPowered ( a_BlockX - 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_WIRE ) ;
2013-11-18 17:30:34 -05:00
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_XM , E_BLOCK_REDSTONE_WIRE ) ;
2012-12-16 02:07:30 -05:00
break ;
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
case REDSTONE_Z_POS :
2012-12-26 12:16:33 -05:00
{
2013-12-14 14:11:15 -05:00
SetBlockPowered ( a_BlockX , a_BlockY , a_BlockZ + 1 , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_WIRE ) ;
2013-11-18 17:30:34 -05:00
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_ZP , E_BLOCK_REDSTONE_WIRE ) ;
break ;
}
case REDSTONE_Z_NEG :
{
2013-12-14 14:11:15 -05:00
SetBlockPowered ( a_BlockX , a_BlockY , a_BlockZ - 1 , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_WIRE ) ;
2013-11-18 17:30:34 -05:00
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_ZM , E_BLOCK_REDSTONE_WIRE ) ;
break ;
}
2012-12-26 12:16:33 -05:00
}
}
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : HandleRedstoneRepeater ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_MyState )
2012-06-14 09:06:06 -04:00
{
2013-12-17 18:05:27 -05:00
NIBBLETYPE a_Meta = m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) ;
2013-12-19 10:57:15 -05:00
bool IsOn = ( ( a_MyState = = E_BLOCK_REDSTONE_REPEATER_ON ) ? true : false ) ; // Cache if repeater is on
bool IsSelfPowered = IsRepeaterPowered ( a_BlockX , a_BlockY , a_BlockZ , a_Meta & 0x3 ) ; // Cache if repeater is pwoered
2013-12-17 18:05:27 -05:00
if ( IsSelfPowered & & ! IsOn ) // Queue a power change if I am receiving power but not on
2013-11-22 18:15:59 -05:00
{
2013-12-17 18:05:27 -05:00
QueueRepeaterPowerChange ( a_BlockX , a_BlockY , a_BlockZ , a_Meta , 0 , true ) ;
}
else if ( ! IsSelfPowered & & IsOn ) // Queue a power change if I am not receiving power but on
{
QueueRepeaterPowerChange ( a_BlockX , a_BlockY , a_BlockZ , a_Meta , 0 , false ) ;
2013-11-22 18:15:59 -05:00
}
2013-11-21 17:44:18 -05:00
2013-12-17 18:05:27 -05:00
for ( RepeatersDelayList : : iterator itr = m_RepeatersDelayList . begin ( ) ; itr ! = m_RepeatersDelayList . end ( ) ; itr + + )
2012-06-14 09:06:06 -04:00
{
2013-12-17 18:05:27 -05:00
if ( ! itr - > a_BlockPos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) )
2013-11-24 09:52:28 -05:00
{
2013-12-17 18:05:27 -05:00
continue ;
}
if ( itr - > a_ElapsedTicks > = itr - > a_DelayTicks ) // Has the elapsed ticks reached the target ticks?
{
if ( itr - > ShouldPowerOn )
2013-12-09 19:21:24 -05:00
{
2013-12-20 16:19:13 -05:00
if ( ! IsOn )
{
m_World . SetBlock ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_REPEATER_ON , a_Meta ) ; // For performance
}
2013-12-17 18:05:27 -05:00
switch ( a_Meta & 0x3 ) // We only want the direction (bottom) bits
2013-12-09 19:21:24 -05:00
{
2013-12-17 18:05:27 -05:00
case 0x0 :
{
SetBlockPowered ( a_BlockX , a_BlockY , a_BlockZ - 1 , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_REPEATER_ON ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_ZM , E_BLOCK_REDSTONE_REPEATER_ON ) ;
break ;
}
case 0x1 :
{
SetBlockPowered ( a_BlockX + 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_REPEATER_ON ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_XP , E_BLOCK_REDSTONE_REPEATER_ON ) ;
break ;
}
case 0x2 :
2013-12-09 19:21:24 -05:00
{
2013-12-17 18:05:27 -05:00
SetBlockPowered ( a_BlockX , a_BlockY , a_BlockZ + 1 , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_REPEATER_ON ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_ZP , E_BLOCK_REDSTONE_REPEATER_ON ) ;
break ;
2013-12-09 19:21:24 -05:00
}
2013-12-17 18:05:27 -05:00
case 0x3 :
2013-12-09 19:21:24 -05:00
{
2013-12-17 18:05:27 -05:00
SetBlockPowered ( a_BlockX - 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_REPEATER_ON ) ;
SetDirectionLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ , BLOCK_FACE_XM , E_BLOCK_REDSTONE_REPEATER_ON ) ;
break ;
2013-12-09 19:21:24 -05:00
}
}
2013-12-19 10:57:15 -05:00
// Removal of the data entry will be handled in SimChunk - we still want to continue trying to power blocks, even if our delay time has reached
// Otherwise, the power state of blocks in front won't update after we have powered on
2013-12-10 05:29:36 -05:00
return ;
}
2013-12-17 18:05:27 -05:00
else
2013-11-21 17:44:18 -05:00
{
2013-12-20 16:19:13 -05:00
if ( IsOn )
{
m_World . SetBlock ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_REPEATER_OFF , a_Meta ) ;
}
2013-12-19 10:57:15 -05:00
m_RepeatersDelayList . erase ( itr ) ; // We can remove off repeaters which don't need further updating
2013-12-17 18:05:27 -05:00
return ;
2012-06-14 09:06:06 -04:00
}
}
2013-12-21 19:30:21 -05:00
else
{
// Apparently, incrementing ticks only works reliably here, and not in SimChunk;
// With a world with lots of redstone, the repeaters simply do not delay
// I am confounded to say why. Perhaps optimisation failure.
LOGD ( " Incremented a repeater @ %i %i %i | Elapsed ticks: %i | Target delay: %i " , itr - > a_BlockPos . x , itr - > a_BlockPos . y , itr - > a_BlockPos . z , itr - > a_ElapsedTicks , itr - > a_DelayTicks ) ;
itr - > a_ElapsedTicks + + ;
}
2013-11-18 17:30:34 -05:00
}
}
2012-12-26 12:16:33 -05:00
2013-08-25 06:45:47 -04:00
2012-06-14 09:06:06 -04:00
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : HandlePiston ( int a_BlockX , int a_BlockY , int a_BlockZ )
{
2013-11-24 09:52:28 -05:00
cPiston Piston ( & m_World ) ;
2013-11-30 07:11:39 -05:00
if ( IsPistonPowered ( a_BlockX , a_BlockY , a_BlockZ , m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) & 0x7 ) ) // We only want the bottom three bits (4th controls extended-ness)
2013-11-18 17:30:34 -05:00
{
Piston . ExtendPiston ( a_BlockX , a_BlockY , a_BlockZ ) ;
}
else
{
Piston . RetractPiston ( a_BlockX , a_BlockY , a_BlockZ ) ;
}
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : HandleDropSpenser ( int a_BlockX , int a_BlockY , int a_BlockZ )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
class cSetPowerToDropSpenser :
public cDropSpenserCallback
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
bool m_IsPowered ;
public :
cSetPowerToDropSpenser ( bool a_IsPowered ) : m_IsPowered ( a_IsPowered ) { }
virtual bool Item ( cDropSpenserEntity * a_DropSpenser ) override
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
a_DropSpenser - > SetRedstonePower ( m_IsPowered ) ;
return false ;
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
} DrSpSP ( AreCoordsPowered ( a_BlockX , a_BlockY , a_BlockZ ) ) ;
m_World . DoWithDropSpenserAt ( a_BlockX , a_BlockY , a_BlockZ , DrSpSP ) ;
}
2012-12-16 00:52:45 -05:00
2013-08-25 06:45:47 -04:00
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : HandleRedstoneLamp ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_MyState )
{
if ( a_MyState = = E_BLOCK_REDSTONE_LAMP_OFF )
{
if ( AreCoordsPowered ( a_BlockX , a_BlockY , a_BlockZ ) )
2013-08-25 06:45:47 -04:00
{
2013-12-07 09:55:19 -05:00
m_World . SetBlock ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_LAMP_ON , 0 ) ;
2013-08-25 06:45:47 -04:00
}
2013-11-18 17:30:34 -05:00
}
else
{
if ( ! AreCoordsPowered ( a_BlockX , a_BlockY , a_BlockZ ) )
2012-06-14 09:06:06 -04:00
{
2013-12-07 09:55:19 -05:00
m_World . SetBlock ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_REDSTONE_LAMP_OFF , 0 ) ;
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
}
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : HandleTNT ( int a_BlockX , int a_BlockY , int a_BlockZ )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
if ( AreCoordsPowered ( a_BlockX , a_BlockY , a_BlockZ ) )
{
m_World . BroadcastSoundEffect ( " random.fuse " , a_BlockX * 8 , a_BlockY * 8 , a_BlockZ * 8 , 0.5f , 0.6f ) ;
m_World . SpawnPrimedTNT ( a_BlockX + 0.5 , a_BlockY + 0.5 , a_BlockZ + 0.5 , 4 ) ; // 4 seconds to boom
2013-12-07 09:55:19 -05:00
m_World . SetBlock ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_AIR , 0 ) ;
2013-11-18 17:30:34 -05:00
}
}
2012-06-14 09:06:06 -04:00
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : HandleDoor ( int a_BlockX , int a_BlockY , int a_BlockZ )
{
if ( ( m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) & 0x08 ) = = 0x08 )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
// Block position is located at top half of door
// Is Y - 1 both within world boundaries, a door block, and the bottom half of a door?
// The bottom half stores the open/closed information
if (
( a_BlockY - 1 > = 0 ) & &
( ( m_World . GetBlock ( a_BlockX , a_BlockY , a_BlockZ ) = = E_BLOCK_WOODEN_DOOR ) | | ( m_World . GetBlock ( a_BlockX , a_BlockY , a_BlockZ ) = = E_BLOCK_IRON_DOOR ) ) & &
( m_World . GetBlockMeta ( a_BlockX , a_BlockY - 1 , a_BlockZ & 0x08 ) = = 0 )
)
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
if ( ( m_World . GetBlockMeta ( a_BlockX , a_BlockY - 1 , a_BlockZ ) & 0x04 ) = = 0 ) // Closed door?
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
if ( AreCoordsPowered ( a_BlockX , a_BlockY , a_BlockZ ) ) // Powered? If so, toggle open
2012-12-16 02:07:30 -05:00
{
2013-11-18 17:30:34 -05:00
cBlockDoorHandler : : ChangeDoor ( & m_World , a_BlockX , a_BlockY , a_BlockZ ) ;
2012-12-16 02:07:30 -05:00
}
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
else // Opened door
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
if ( ! AreCoordsPowered ( a_BlockX , a_BlockY , a_BlockZ ) ) // Unpowered? Close if so
2012-12-16 02:07:30 -05:00
{
2013-11-18 17:30:34 -05:00
cBlockDoorHandler : : ChangeDoor ( & m_World , a_BlockX , a_BlockY , a_BlockZ ) ;
2012-12-16 02:07:30 -05:00
}
2012-06-14 09:06:06 -04:00
}
2012-12-16 02:07:30 -05:00
}
2013-11-18 17:30:34 -05:00
}
else
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
if ( ( m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) & 0x04 ) = = 0 ) // Closed door?
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
if ( AreCoordsPowered ( a_BlockX , a_BlockY , a_BlockZ ) ) // Powered? If so, toggle open
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
cBlockDoorHandler : : ChangeDoor ( & m_World , a_BlockX , a_BlockY , a_BlockZ ) ;
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
}
else // Opened door
{
if ( ! AreCoordsPowered ( a_BlockX , a_BlockY , a_BlockZ ) ) // Unpowered? Close if so
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
cBlockDoorHandler : : ChangeDoor ( & m_World , a_BlockX , a_BlockY , a_BlockZ ) ;
2012-06-14 09:06:06 -04:00
}
}
}
}
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : HandleRail ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_MyType )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
switch ( a_MyType )
2012-12-16 00:52:45 -05:00
{
2013-11-18 17:30:34 -05:00
case E_BLOCK_DETECTOR_RAIL :
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
if ( ( m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) & 0x08 ) = = 0x08 )
2012-06-14 09:06:06 -04:00
{
2013-11-21 17:44:18 -05:00
SetAllDirsAsPowered ( a_BlockX , a_BlockY , a_BlockZ , a_MyType ) ;
2012-06-14 09:06:06 -04:00
}
2012-12-16 02:07:30 -05:00
break ;
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
case E_BLOCK_ACTIVATOR_RAIL :
case E_BLOCK_POWERED_RAIL :
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
if ( AreCoordsPowered ( a_BlockX , a_BlockY , a_BlockZ ) )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
m_World . SetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ , m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) | 0x08 ) ;
2012-06-14 09:06:06 -04:00
}
2013-11-18 17:30:34 -05:00
else
2012-12-16 02:07:30 -05:00
{
2013-11-18 17:30:34 -05:00
m_World . SetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ , m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) & 0x07 ) ;
2012-12-16 02:07:30 -05:00
}
2013-11-18 17:30:34 -05:00
break ;
}
2013-12-20 16:19:13 -05:00
default : LOGD ( " Unhandled type of rail in %s " , __FUNCTION__ ) ;
2012-06-14 09:06:06 -04:00
}
}
2013-11-29 17:27:08 -05:00
void cRedstoneSimulator : : HandleTrapdoor ( int a_BlockX , int a_BlockY , int a_BlockZ )
{
if ( AreCoordsPowered ( a_BlockX , a_BlockY , a_BlockZ ) )
{
2013-12-07 09:41:58 -05:00
if ( ! AreCoordsSimulated ( a_BlockX , a_BlockY , a_BlockZ , true ) )
{
m_World . SetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ , m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) | 0x4 ) ;
SetPlayerToggleableBlockAsSimulated ( a_BlockX , a_BlockY , a_BlockZ , true ) ;
}
2013-11-29 17:27:08 -05:00
}
else
{
2013-12-07 09:41:58 -05:00
if ( ! AreCoordsSimulated ( a_BlockX , a_BlockY , a_BlockZ , false ) )
{
m_World . SetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ , m_World . GetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ ) & 0xB ) ; // Take into account that the fourth bit is needed for trapdoors too
SetPlayerToggleableBlockAsSimulated ( a_BlockX , a_BlockY , a_BlockZ , false ) ;
}
2013-11-29 17:27:08 -05:00
}
}
2013-12-14 11:52:22 -05:00
void cRedstoneSimulator : : HandleNoteBlock ( int a_BlockX , int a_BlockY , int a_BlockZ )
{
bool m_bAreCoordsPowered = AreCoordsPowered ( a_BlockX , a_BlockY , a_BlockZ ) ;
if ( m_bAreCoordsPowered )
{
if ( ! AreCoordsSimulated ( a_BlockX , a_BlockY , a_BlockZ , true ) )
{
class cSetPowerToNoteBlock :
public cNoteBlockCallback
{
bool m_IsPowered ;
public :
cSetPowerToNoteBlock ( bool a_IsPowered ) : m_IsPowered ( a_IsPowered ) { }
virtual bool Item ( cNoteEntity * a_NoteBlock ) override
{
if ( m_IsPowered )
{
a_NoteBlock - > MakeSound ( ) ;
}
return false ;
}
} NoteBlockSP ( m_bAreCoordsPowered ) ;
m_World . DoWithNoteBlockAt ( a_BlockX , a_BlockY , a_BlockZ , NoteBlockSP ) ;
SetPlayerToggleableBlockAsSimulated ( a_BlockX , a_BlockY , a_BlockZ , true ) ;
}
}
else
{
if ( ! AreCoordsSimulated ( a_BlockX , a_BlockY , a_BlockZ , false ) )
{
SetPlayerToggleableBlockAsSimulated ( a_BlockX , a_BlockY , a_BlockZ , false ) ;
}
}
}
2013-11-29 17:27:08 -05:00
2013-12-20 16:19:13 -05:00
void cRedstoneSimulator : : HandleDaylightSensor ( int a_BlockX , int a_BlockY , int a_BlockZ )
{
2013-12-22 18:20:43 -05:00
int a_ChunkX , a_ChunkZ ;
cChunkDef : : BlockToChunk ( a_BlockX , a_BlockZ , a_ChunkX , a_ChunkZ ) ;
if ( ! m_World . IsChunkLighted ( a_ChunkX , a_ChunkZ ) )
2013-12-21 19:30:21 -05:00
{
2013-12-22 18:20:43 -05:00
m_World . QueueLightChunk ( a_ChunkX , a_ChunkZ ) ;
2013-12-21 19:30:21 -05:00
}
2013-12-22 18:20:43 -05:00
else
2013-12-20 16:19:13 -05:00
{
2013-12-22 18:20:43 -05:00
NIBBLETYPE SkyLight = m_World . GetBlockSkyLight ( a_BlockX , a_BlockY + 1 , a_BlockZ ) - m_World . GetSkyDarkness ( ) ;
if ( SkyLight > 8 )
{
SetAllDirsAsPowered ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_DAYLIGHT_SENSOR ) ;
}
2013-12-20 16:19:13 -05:00
}
}
2013-12-24 10:02:55 -05:00
void cRedstoneSimulator : : HandlePressurePlate ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_MyType )
{
switch ( a_MyType )
{
case E_BLOCK_STONE_PRESSURE_PLATE :
{
// MCS feature - stone pressure plates can only be triggered by players :D
cPlayer * a_Player = m_World . FindClosestPlayer ( Vector3f ( a_BlockX + 0.5f , ( float ) a_BlockY , a_BlockZ + 0.5f ) , 0.5f ) ;
if ( a_Player ! = NULL )
{
m_World . SetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ , 0x1 ) ;
SetAllDirsAsPowered ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_STONE_PRESSURE_PLATE ) ;
}
else
{
m_World . SetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ , 0x0 ) ;
}
break ;
}
case E_BLOCK_WOODEN_PRESSURE_PLATE :
{
class cWoodenPressurePlateCallback :
public cEntityCallback
{
public :
cWoodenPressurePlateCallback ( int a_BlockX , int a_BlockY , int a_BlockZ , cWorld * a_World ) :
m_X ( a_BlockX ) ,
m_Y ( a_BlockY ) ,
m_Z ( a_BlockZ ) ,
m_World ( a_World ) ,
m_Entity ( NULL )
{
}
virtual bool Item ( cEntity * a_Entity ) override
{
cTracer LineOfSight ( m_World ) ;
Vector3f EntityPos = a_Entity - > GetPosition ( ) ;
Vector3f BlockPos ( m_X + 0.5f , ( float ) m_Y , m_Z + 0.5f ) ;
float Distance = ( EntityPos - BlockPos ) . Length ( ) ;
if ( Distance < 0.5 )
{
if ( ! LineOfSight . Trace ( BlockPos , ( EntityPos - BlockPos ) , ( int ) ( EntityPos - BlockPos ) . Length ( ) ) )
{
m_Entity = a_Entity ;
return true ; // Break out, we only need to know for wooden plates that at least one entity is on top
}
}
return false ;
}
bool FoundEntity ( void ) const
{
return m_Entity ! = NULL ;
}
protected :
cEntity * m_Entity ;
cWorld * m_World ;
int m_X ;
int m_Y ;
int m_Z ;
} ;
cWoodenPressurePlateCallback WoodenPressurePlateCallback ( a_BlockX , a_BlockY , a_BlockZ , & m_World ) ;
m_World . ForEachEntity ( WoodenPressurePlateCallback ) ;
if ( WoodenPressurePlateCallback . FoundEntity ( ) )
{
m_World . SetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ , 0x1 ) ;
SetAllDirsAsPowered ( a_BlockX , a_BlockY , a_BlockZ , E_BLOCK_WOODEN_PRESSURE_PLATE ) ;
}
else
{
m_World . SetBlockMeta ( a_BlockX , a_BlockY , a_BlockZ , 0x0 ) ;
}
break ;
}
default :
LOGD ( " Unimplemented pressure plate type %s in cRedstoneSimulator " , ItemToFullString ( a_MyType ) . c_str ( ) ) ;
break ;
}
}
2013-12-13 21:40:54 -05:00
bool cRedstoneSimulator : : AreCoordsDirectlyPowered ( int a_BlockX , int a_BlockY , int a_BlockZ )
2013-11-18 17:30:34 -05:00
{
2013-12-13 20:14:09 -05:00
for ( PoweredBlocksList : : const_iterator itr = m_PoweredBlocks . begin ( ) ; itr ! = m_PoweredBlocks . end ( ) ; + + itr ) // Check powered list
2012-06-14 09:06:06 -04:00
{
2013-12-13 20:14:09 -05:00
if ( itr - > a_BlockPos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
return true ;
2012-06-14 09:06:06 -04:00
}
}
2013-12-13 21:40:54 -05:00
return false ;
}
2013-11-18 17:30:34 -05:00
2013-12-13 21:40:54 -05:00
bool cRedstoneSimulator : : AreCoordsLinkedPowered ( int a_BlockX , int a_BlockY , int a_BlockZ )
{
2013-12-13 20:14:09 -05:00
for ( LinkedBlocksList : : const_iterator itr = m_LinkedPoweredBlocks . begin ( ) ; itr ! = m_LinkedPoweredBlocks . end ( ) ; + + itr ) // Check linked powered list
2012-06-14 09:06:06 -04:00
{
2013-12-13 20:14:09 -05:00
if ( itr - > a_BlockPos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) )
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
return true ;
2012-06-14 09:06:06 -04:00
}
}
2013-11-18 17:30:34 -05:00
return false ;
2012-10-06 16:04:58 -04:00
}
2013-11-18 17:30:34 -05:00
bool cRedstoneSimulator : : IsRepeaterPowered ( int a_BlockX , int a_BlockY , int a_BlockZ , NIBBLETYPE a_Meta )
2012-10-06 16:04:58 -04:00
{
2013-11-30 07:11:39 -05:00
// Repeaters cannot be powered by any face except their back; verify that this is true for a source
2013-12-13 20:14:09 -05:00
for ( PoweredBlocksList : : const_iterator itr = m_PoweredBlocks . begin ( ) ; itr ! = m_PoweredBlocks . end ( ) ; + + itr )
2012-10-06 16:04:58 -04:00
{
2013-12-13 20:14:09 -05:00
if ( ! itr - > a_BlockPos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) ) { continue ; }
2013-11-20 17:54:28 -05:00
2013-11-18 17:30:34 -05:00
switch ( a_Meta )
2012-10-06 16:04:58 -04:00
{
2013-11-18 17:30:34 -05:00
case 0x0 :
2012-10-06 16:04:58 -04:00
{
2013-11-18 17:30:34 -05:00
// Flip the coords to check the back of the repeater
2013-12-13 20:14:09 -05:00
if ( itr - > a_SourcePos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ + 1 ) ) ) { return true ; }
2013-11-18 17:30:34 -05:00
break ;
2012-10-06 16:04:58 -04:00
}
2013-11-18 17:30:34 -05:00
case 0x1 :
2012-10-06 16:04:58 -04:00
{
2013-12-13 20:14:09 -05:00
if ( itr - > a_SourcePos . Equals ( Vector3i ( a_BlockX - 1 , a_BlockY , a_BlockZ ) ) ) { return true ; }
2013-11-18 17:30:34 -05:00
break ;
2012-10-06 16:04:58 -04:00
}
2013-11-18 17:30:34 -05:00
case 0x2 :
{
2013-12-13 20:14:09 -05:00
if ( itr - > a_SourcePos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ - 1 ) ) ) { return true ; }
2013-11-18 17:30:34 -05:00
break ;
}
case 0x3 :
2012-10-06 16:04:58 -04:00
{
2013-12-13 20:14:09 -05:00
if ( itr - > a_SourcePos . Equals ( Vector3i ( a_BlockX + 1 , a_BlockY , a_BlockZ ) ) ) { return true ; }
2013-11-18 17:30:34 -05:00
break ;
2012-10-06 16:04:58 -04:00
}
}
2013-11-18 17:30:34 -05:00
}
2013-12-13 20:14:09 -05:00
for ( LinkedBlocksList : : const_iterator itr = m_LinkedPoweredBlocks . begin ( ) ; itr ! = m_LinkedPoweredBlocks . end ( ) ; + + itr )
2013-11-18 17:30:34 -05:00
{
2013-12-13 20:14:09 -05:00
if ( ! itr - > a_BlockPos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) ) { continue ; }
2013-11-20 17:54:28 -05:00
2013-11-18 17:30:34 -05:00
switch ( a_Meta )
2012-10-06 16:04:58 -04:00
{
2013-11-18 17:30:34 -05:00
case 0x0 :
2012-10-06 16:04:58 -04:00
{
2013-12-13 20:14:09 -05:00
if ( itr - > a_MiddlePos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ + 1 ) ) ) { return true ; }
2013-11-18 17:30:34 -05:00
break ;
}
case 0x1 :
{
2013-12-13 20:14:09 -05:00
if ( itr - > a_MiddlePos . Equals ( Vector3i ( a_BlockX - 1 , a_BlockY , a_BlockZ ) ) ) { return true ; }
2013-11-18 17:30:34 -05:00
break ;
}
case 0x2 :
{
2013-12-13 20:14:09 -05:00
if ( itr - > a_MiddlePos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ - 1 ) ) ) { return true ; }
2013-11-18 17:30:34 -05:00
break ;
}
case 0x3 :
{
2013-12-13 20:14:09 -05:00
if ( itr - > a_MiddlePos . Equals ( Vector3i ( a_BlockX + 1 , a_BlockY , a_BlockZ ) ) ) { return true ; }
2013-11-18 17:30:34 -05:00
break ;
2012-10-06 16:04:58 -04:00
}
}
}
2013-11-18 17:30:34 -05:00
return false ; // Couldn't find power source behind repeater
2012-10-06 16:04:58 -04:00
}
2013-11-30 07:11:39 -05:00
bool cRedstoneSimulator : : IsPistonPowered ( int a_BlockX , int a_BlockY , int a_BlockZ , NIBBLETYPE a_Meta )
{
// Pistons cannot be powered through their front face; this function verifies that a source meets this requirement
2013-11-30 10:07:21 -05:00
int OldX = a_BlockX , OldY = a_BlockY , OldZ = a_BlockZ ;
2013-12-13 20:14:09 -05:00
for ( PoweredBlocksList : : const_iterator itr = m_PoweredBlocks . begin ( ) ; itr ! = m_PoweredBlocks . end ( ) ; + + itr )
2013-11-30 07:11:39 -05:00
{
2013-12-13 20:14:09 -05:00
if ( ! itr - > a_BlockPos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) ) { continue ; }
2013-11-30 07:11:39 -05:00
2013-11-30 08:41:40 -05:00
AddFaceDirection ( a_BlockX , a_BlockY , a_BlockZ , a_Meta ) ; // Piston meta is based on what direction they face, so we can do this
2013-12-13 20:14:09 -05:00
if ( ! itr - > a_SourcePos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) )
2013-11-30 07:11:39 -05:00
{
2013-11-30 08:41:40 -05:00
return true ;
2013-11-30 07:11:39 -05:00
}
2013-11-30 10:07:21 -05:00
a_BlockX = OldX ;
a_BlockY = OldY ;
a_BlockZ = OldZ ;
2013-11-30 07:11:39 -05:00
}
2013-12-13 20:14:09 -05:00
for ( LinkedBlocksList : : const_iterator itr = m_LinkedPoweredBlocks . begin ( ) ; itr ! = m_LinkedPoweredBlocks . end ( ) ; + + itr )
2013-11-30 07:11:39 -05:00
{
2013-12-13 20:14:09 -05:00
if ( ! itr - > a_BlockPos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) ) { continue ; }
2013-11-30 07:11:39 -05:00
2013-11-30 08:41:40 -05:00
AddFaceDirection ( a_BlockX , a_BlockY , a_BlockZ , a_Meta ) ;
2013-12-13 20:14:09 -05:00
if ( ! itr - > a_MiddlePos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) )
2013-11-30 07:11:39 -05:00
{
2013-11-30 08:41:40 -05:00
return true ;
2013-11-30 07:11:39 -05:00
}
2013-11-30 10:07:21 -05:00
a_BlockX = OldX ;
a_BlockY = OldY ;
a_BlockZ = OldZ ;
2013-11-30 07:11:39 -05:00
}
return false ; // Source was in front of the piston's front face
}
2012-10-06 16:04:58 -04:00
2013-12-07 09:41:58 -05:00
bool cRedstoneSimulator : : AreCoordsSimulated ( int a_BlockX , int a_BlockY , int a_BlockZ , bool IsCurrentStatePowered )
{
2013-12-13 20:14:09 -05:00
for ( SimulatedPlayerToggleableList : : const_iterator itr = m_SimulatedPlayerToggleableBlocks . begin ( ) ; itr ! = m_SimulatedPlayerToggleableBlocks . end ( ) ; + + itr )
2013-12-07 09:41:58 -05:00
{
2013-12-13 20:14:09 -05:00
if ( itr - > a_BlockPos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) )
2013-12-07 09:41:58 -05:00
{
2013-12-13 20:14:09 -05:00
if ( itr - > WasLastStatePowered ! = IsCurrentStatePowered ) // Was the last power state different to the current?
2013-12-07 09:41:58 -05:00
{
return false ; // It was, coordinates are no longer simulated
}
else
{
return true ; // It wasn't, don't resimulate block, and allow players to toggle
}
}
}
return false ; // Block wasn't even in the list, not simulated
}
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : SetDirectionLinkedPowered ( int a_BlockX , int a_BlockY , int a_BlockZ , char a_Direction , BLOCKTYPE a_SourceType )
2012-10-06 16:04:58 -04:00
{
2013-11-18 17:30:34 -05:00
switch ( a_Direction )
2012-10-06 16:04:58 -04:00
{
2013-11-18 17:30:34 -05:00
case BLOCK_FACE_XM :
2012-10-06 16:04:58 -04:00
{
2013-11-18 17:30:34 -05:00
BLOCKTYPE MiddleBlock = m_World . GetBlock ( a_BlockX - 1 , a_BlockY , a_BlockZ ) ;
2013-12-13 19:43:05 -05:00
SetBlockLinkedPowered ( a_BlockX - 2 , a_BlockY , a_BlockZ , a_BlockX - 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX - 1 , a_BlockY + 1 , a_BlockZ , a_BlockX - 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX - 1 , a_BlockY - 1 , a_BlockZ , a_BlockX - 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX - 1 , a_BlockY , a_BlockZ + 1 , a_BlockX - 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX - 1 , a_BlockY , a_BlockZ - 1 , a_BlockX - 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
2012-10-06 16:04:58 -04:00
break ;
}
2013-11-18 17:30:34 -05:00
case BLOCK_FACE_XP :
2012-10-06 16:04:58 -04:00
{
2013-11-18 17:30:34 -05:00
BLOCKTYPE MiddleBlock = m_World . GetBlock ( a_BlockX + 1 , a_BlockY , a_BlockZ ) ;
2013-12-13 19:43:05 -05:00
SetBlockLinkedPowered ( a_BlockX + 2 , a_BlockY , a_BlockZ , a_BlockX + 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX + 1 , a_BlockY + 1 , a_BlockZ , a_BlockX + 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX + 1 , a_BlockY - 1 , a_BlockZ , a_BlockX + 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX + 1 , a_BlockY , a_BlockZ + 1 , a_BlockX + 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX + 1 , a_BlockY , a_BlockZ - 1 , a_BlockX + 1 , a_BlockY , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
2012-10-06 16:04:58 -04:00
break ;
}
2013-11-18 17:30:34 -05:00
case BLOCK_FACE_YM :
2012-10-06 16:04:58 -04:00
{
2013-11-18 17:30:34 -05:00
BLOCKTYPE MiddleBlock = m_World . GetBlock ( a_BlockX , a_BlockY - 1 , a_BlockZ ) ;
2013-12-13 19:43:05 -05:00
SetBlockLinkedPowered ( a_BlockX , a_BlockY - 2 , a_BlockZ , a_BlockX , a_BlockY - 1 , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX + 1 , a_BlockY - 1 , a_BlockZ , a_BlockX , a_BlockY - 1 , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX - 1 , a_BlockY - 1 , a_BlockZ , a_BlockX , a_BlockY - 1 , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX , a_BlockY - 1 , a_BlockZ + 1 , a_BlockX , a_BlockY - 1 , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX , a_BlockY - 1 , a_BlockZ - 1 , a_BlockX , a_BlockY - 1 , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
2012-10-06 16:04:58 -04:00
break ;
}
2013-11-18 17:30:34 -05:00
case BLOCK_FACE_YP :
2012-10-06 16:04:58 -04:00
{
2013-11-18 17:30:34 -05:00
BLOCKTYPE MiddleBlock = m_World . GetBlock ( a_BlockX , a_BlockY + 1 , a_BlockZ ) ;
2013-12-13 19:43:05 -05:00
SetBlockLinkedPowered ( a_BlockX , a_BlockY + 2 , a_BlockZ , a_BlockX , a_BlockY + 1 , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX + 1 , a_BlockY + 1 , a_BlockZ , a_BlockX , a_BlockY + 1 , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX - 1 , a_BlockY + 1 , a_BlockZ , a_BlockX , a_BlockY + 1 , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX , a_BlockY + 1 , a_BlockZ + 1 , a_BlockX , a_BlockY + 1 , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX , a_BlockY + 1 , a_BlockZ - 1 , a_BlockX , a_BlockY + 1 , a_BlockZ , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
2013-11-18 17:30:34 -05:00
break ;
}
case BLOCK_FACE_ZM :
{
BLOCKTYPE MiddleBlock = m_World . GetBlock ( a_BlockX , a_BlockY , a_BlockZ - 1 ) ;
2013-12-13 19:43:05 -05:00
SetBlockLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ - 2 , a_BlockX , a_BlockY , a_BlockZ - 1 , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX + 1 , a_BlockY , a_BlockZ - 1 , a_BlockX , a_BlockY , a_BlockZ - 1 , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX - 1 , a_BlockY , a_BlockZ - 1 , a_BlockX , a_BlockY , a_BlockZ - 1 , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX , a_BlockY + 1 , a_BlockZ - 1 , a_BlockX , a_BlockY , a_BlockZ - 1 , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX , a_BlockY - 1 , a_BlockZ - 1 , a_BlockX , a_BlockY , a_BlockZ - 1 , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
2013-11-18 17:30:34 -05:00
break ;
}
case BLOCK_FACE_ZP :
{
BLOCKTYPE MiddleBlock = m_World . GetBlock ( a_BlockX , a_BlockY , a_BlockZ + 1 ) ;
2013-12-13 19:43:05 -05:00
SetBlockLinkedPowered ( a_BlockX , a_BlockY , a_BlockZ + 2 , a_BlockX , a_BlockY , a_BlockZ + 1 , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX + 1 , a_BlockY , a_BlockZ + 1 , a_BlockX , a_BlockY , a_BlockZ + 1 , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX - 1 , a_BlockY , a_BlockZ + 1 , a_BlockX , a_BlockY , a_BlockZ + 1 , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX , a_BlockY + 1 , a_BlockZ + 1 , a_BlockX , a_BlockY , a_BlockZ + 1 , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
SetBlockLinkedPowered ( a_BlockX , a_BlockY - 1 , a_BlockZ + 1 , a_BlockX , a_BlockY , a_BlockZ + 1 , a_BlockX , a_BlockY , a_BlockZ , a_SourceType , MiddleBlock ) ;
2013-11-18 17:30:34 -05:00
break ;
}
default :
{
2013-11-20 17:54:28 -05:00
ASSERT ( ! " Unhandled face direction when attempting to set blocks as linked powered! " ) ; // Zombies, that wasn't supposed to happen...
2012-10-06 16:04:58 -04:00
break ;
}
}
}
2013-11-20 17:54:28 -05:00
void cRedstoneSimulator : : SetAllDirsAsPowered ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_SourceBlock )
{
2013-11-24 09:52:28 -05:00
static const struct
2013-11-20 17:54:28 -05:00
{
int x , y , z ;
} gCrossCoords [ ] =
{
{ 1 , 0 , 0 } ,
{ - 1 , 0 , 0 } ,
{ 0 , 0 , 1 } ,
{ 0 , 0 , - 1 } ,
{ 0 , 1 , 0 } ,
2013-11-22 18:15:59 -05:00
{ 0 , - 1 , 0 }
2013-11-20 17:54:28 -05:00
} ;
2013-12-01 07:58:04 -05:00
for ( size_t i = 0 ; i < ARRAYCOUNT ( gCrossCoords ) ; i + + ) // Loop through struct to power all directions
2013-11-20 17:54:28 -05:00
{
SetBlockPowered ( a_BlockX + gCrossCoords [ i ] . x , a_BlockY + gCrossCoords [ i ] . y , a_BlockZ + gCrossCoords [ i ] . z , a_BlockX , a_BlockY , a_BlockZ , a_SourceBlock ) ;
}
}
2013-11-18 17:30:34 -05:00
void cRedstoneSimulator : : SetBlockPowered ( int a_BlockX , int a_BlockY , int a_BlockZ , int a_SourceX , int a_SourceY , int a_SourceZ , BLOCKTYPE a_SourceBlock )
2012-10-06 16:04:58 -04:00
{
2013-12-14 14:11:15 -05:00
BLOCKTYPE Block = m_World . GetBlock ( a_BlockX , a_BlockY , a_BlockZ ) ;
if ( Block = = E_BLOCK_AIR )
2013-12-01 07:58:04 -05:00
{
// Don't set air, fixes some bugs (wires powering themselves)
return ;
}
2013-12-14 14:11:15 -05:00
if ( ( Block = = E_BLOCK_REDSTONE_WIRE ) & & ( a_SourceBlock = = E_BLOCK_REDSTONE_WIRE ) )
{
// Wires cannot power themselves normally, instead, the wire handler will manually set meta
return ;
}
2013-11-18 17:30:34 -05:00
2013-12-13 20:14:09 -05:00
for ( PoweredBlocksList : : const_iterator itr = m_PoweredBlocks . begin ( ) ; itr ! = m_PoweredBlocks . end ( ) ; + + itr ) // Check powered list
2013-12-06 15:33:48 -05:00
{
if (
2013-12-13 20:14:09 -05:00
itr - > a_BlockPos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) & &
itr - > a_SourcePos . Equals ( Vector3i ( a_SourceX , a_SourceY , a_SourceZ ) )
2013-12-06 15:33:48 -05:00
)
{
// Check for duplicates
return ;
}
}
2013-11-18 17:30:34 -05:00
sPoweredBlocks RC ;
RC . a_BlockPos = Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ;
RC . a_SourcePos = Vector3i ( a_SourceX , a_SourceY , a_SourceZ ) ;
RC . a_SourceBlock = a_SourceBlock ;
m_PoweredBlocks . push_back ( RC ) ;
2012-10-06 16:04:58 -04:00
}
2013-12-01 07:58:04 -05:00
void cRedstoneSimulator : : SetBlockLinkedPowered (
int a_BlockX , int a_BlockY , int a_BlockZ ,
2013-11-18 17:30:34 -05:00
int a_MiddleX , int a_MiddleY , int a_MiddleZ ,
int a_SourceX , int a_SourceY , int a_SourceZ ,
BLOCKTYPE a_SourceBlock , BLOCKTYPE a_MiddleBlock
2013-12-01 07:58:04 -05:00
)
2012-10-06 16:04:58 -04:00
{
2013-12-13 19:43:05 -05:00
BLOCKTYPE DestBlock = m_World . GetBlock ( a_BlockX , a_BlockY , a_BlockZ ) ;
if ( DestBlock = = E_BLOCK_AIR )
2013-12-01 07:58:04 -05:00
{
// Don't set air, fixes some bugs (wires powering themselves)
return ;
}
2013-12-13 19:43:05 -05:00
if ( ! IsViableMiddleBlock ( a_MiddleBlock ) )
{
return ;
}
if ( ( a_SourceBlock = = E_BLOCK_REDSTONE_WIRE ) & & ( DestBlock = = E_BLOCK_REDSTONE_WIRE ) )
2013-12-01 07:58:04 -05:00
{
2013-12-13 19:43:05 -05:00
// Wires cannot power another wire through a block
2013-12-01 07:58:04 -05:00
return ;
}
2013-11-18 17:30:34 -05:00
2013-12-13 20:14:09 -05:00
for ( LinkedBlocksList : : const_iterator itr = m_LinkedPoweredBlocks . begin ( ) ; itr ! = m_LinkedPoweredBlocks . end ( ) ; + + itr ) // Check linked powered list
2013-12-06 15:33:48 -05:00
{
if (
2013-12-13 20:14:09 -05:00
itr - > a_BlockPos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) & &
itr - > a_MiddlePos . Equals ( Vector3i ( a_MiddleX , a_MiddleY , a_MiddleZ ) ) & &
itr - > a_SourcePos . Equals ( Vector3i ( a_SourceX , a_SourceY , a_SourceZ ) )
2013-12-06 15:33:48 -05:00
)
{
// Check for duplicates
return ;
}
}
2013-11-18 17:30:34 -05:00
sLinkedPoweredBlocks RC ;
RC . a_BlockPos = Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ;
RC . a_MiddlePos = Vector3i ( a_MiddleX , a_MiddleY , a_MiddleZ ) ;
RC . a_SourcePos = Vector3i ( a_SourceX , a_SourceY , a_SourceZ ) ;
RC . a_SourceBlock = a_SourceBlock ;
RC . a_MiddleBlock = a_MiddleBlock ;
m_LinkedPoweredBlocks . push_back ( RC ) ;
2013-12-07 09:41:58 -05:00
}
void cRedstoneSimulator : : SetPlayerToggleableBlockAsSimulated ( int a_BlockX , int a_BlockY , int a_BlockZ , bool WasLastStatePowered )
{
2013-12-13 21:40:54 -05:00
for ( SimulatedPlayerToggleableList : : iterator itr = m_SimulatedPlayerToggleableBlocks . begin ( ) ; itr ! = m_SimulatedPlayerToggleableBlocks . end ( ) ; + + itr )
2013-12-07 09:41:58 -05:00
{
2013-12-13 21:40:54 -05:00
if ( ! itr - > a_BlockPos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) )
2013-12-07 09:41:58 -05:00
{
2013-12-13 21:40:54 -05:00
continue ;
}
if ( itr - > WasLastStatePowered ! = WasLastStatePowered )
{
// If power states different, update listing
itr - > WasLastStatePowered = WasLastStatePowered ;
return ;
}
else
{
// If states the same, just ignore
return ;
2013-12-07 09:41:58 -05:00
}
}
2013-12-13 21:40:54 -05:00
// We have arrive here; no block must be in list - add one
2013-12-07 09:41:58 -05:00
sSimulatedPlayerToggleableList RC ;
RC . a_BlockPos = Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ;
RC . WasLastStatePowered = WasLastStatePowered ;
m_SimulatedPlayerToggleableBlocks . push_back ( RC ) ;
2012-10-06 16:04:58 -04:00
}
2013-12-17 18:05:27 -05:00
void cRedstoneSimulator : : QueueRepeaterPowerChange ( int a_BlockX , int a_BlockY , int a_BlockZ , NIBBLETYPE a_Meta , short a_ElapsedTicks , bool ShouldPowerOn )
{
for ( RepeatersDelayList : : iterator itr = m_RepeatersDelayList . begin ( ) ; itr ! = m_RepeatersDelayList . end ( ) ; itr + + )
{
if ( itr - > a_BlockPos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) )
{
2013-12-19 10:57:15 -05:00
if ( ShouldPowerOn = = itr - > ShouldPowerOn ) // We are queued already for the same thing, don't replace entry
{
return ;
}
// Already in here (normal to allow repeater to continue on powering and updating blocks in front) - just update info and quit
2013-12-21 19:30:21 -05:00
itr - > a_DelayTicks = ( ( ( a_Meta & 0xC ) > > 0x2 ) + ( ShouldPowerOn ? 1 : 0 ) ) * 2 ; // See below for description
2013-12-19 10:57:15 -05:00
itr - > a_ElapsedTicks = 0 ;
itr - > ShouldPowerOn = ShouldPowerOn ;
2013-12-17 18:05:27 -05:00
return ;
}
}
// Self not in list, add self to list
sRepeatersDelayList RC ;
RC . a_BlockPos = Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ;
2013-12-20 16:19:13 -05:00
// Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.)
// * 2 because apparently, MCS ticks are way faster than vanilla ticks, so repeater aren't noticeably delayed
2013-12-21 19:30:21 -05:00
// We don't +1 when powering off because everything seems to already delay a tick when powering off, why? No idea :P
RC . a_DelayTicks = ( ( ( a_Meta & 0xC ) > > 0x2 ) + ( ShouldPowerOn ? 1 : 0 ) ) * 2 ;
2013-12-20 16:19:13 -05:00
2013-12-17 18:05:27 -05:00
RC . a_ElapsedTicks = 0 ;
RC . ShouldPowerOn = ShouldPowerOn ;
m_RepeatersDelayList . push_back ( RC ) ;
return ;
}
2013-11-18 17:30:34 -05:00
cRedstoneSimulator : : eRedstoneDirection cRedstoneSimulator : : GetWireDirection ( int a_BlockX , int a_BlockY , int a_BlockZ )
2012-12-16 00:52:45 -05:00
{
2013-11-18 17:30:34 -05:00
int Dir = REDSTONE_NONE ;
BLOCKTYPE NegX = m_World . GetBlock ( a_BlockX - 1 , a_BlockY , a_BlockZ ) ;
if ( IsPotentialSource ( NegX ) )
2012-12-16 00:52:45 -05:00
{
2013-11-18 17:30:34 -05:00
Dir | = ( REDSTONE_X_POS ) ;
2012-12-16 00:52:45 -05:00
}
2013-11-18 17:30:34 -05:00
BLOCKTYPE PosX = m_World . GetBlock ( a_BlockX + 1 , a_BlockY , a_BlockZ ) ;
if ( IsPotentialSource ( PosX ) )
{
Dir | = ( REDSTONE_X_NEG ) ;
}
BLOCKTYPE NegZ = m_World . GetBlock ( a_BlockX , a_BlockY , a_BlockZ - 1 ) ;
if ( IsPotentialSource ( NegZ ) )
{
if ( ( Dir & REDSTONE_X_POS ) & & ! ( Dir & REDSTONE_X_NEG ) ) // corner
{
Dir ^ = REDSTONE_X_POS ;
Dir | = REDSTONE_X_NEG ;
}
if ( ( Dir & REDSTONE_X_NEG ) & & ! ( Dir & REDSTONE_X_POS ) ) // corner
{
Dir ^ = REDSTONE_X_NEG ;
Dir | = REDSTONE_X_POS ;
}
Dir | = REDSTONE_Z_POS ;
}
BLOCKTYPE PosZ = m_World . GetBlock ( a_BlockX , a_BlockY , a_BlockZ + 1 ) ;
if ( IsPotentialSource ( PosZ ) )
{
if ( ( Dir & REDSTONE_X_POS ) & & ! ( Dir & REDSTONE_X_NEG ) ) // corner
{
Dir ^ = REDSTONE_X_POS ;
Dir | = REDSTONE_X_NEG ;
}
if ( ( Dir & REDSTONE_X_NEG ) & & ! ( Dir & REDSTONE_X_POS ) ) // corner
{
Dir ^ = REDSTONE_X_NEG ;
Dir | = REDSTONE_X_POS ;
}
Dir | = REDSTONE_Z_NEG ;
}
return ( eRedstoneDirection ) Dir ;
2012-12-16 02:07:30 -05:00
}
bool cRedstoneSimulator : : IsLeverOn ( NIBBLETYPE a_BlockMeta )
2012-12-16 00:52:45 -05:00
{
2012-12-16 02:07:30 -05:00
// Extract the ON bit from metadata and return if true if it is set:
return ( ( a_BlockMeta & 0x8 ) = = 0x8 ) ;
2012-12-16 00:52:45 -05:00
}
2013-11-18 17:30:34 -05:00
bool cRedstoneSimulator : : IsButtonOn ( NIBBLETYPE a_BlockMeta )
2012-10-06 16:04:58 -04:00
{
2013-11-18 17:30:34 -05:00
return IsLeverOn ( a_BlockMeta ) ;
2012-10-06 16:04:58 -04:00
}