2012-03-01 10:18:59 -05:00
# include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
# include "cRedstoneSimulator.h"
# include "cPiston.h"
# include "cWorld.h"
# include "BlockID.h"
# include "cCriticalSection.h"
# include "cTorch.h"
# include "cRedstone.h"
cRedstoneSimulator : : cRedstoneSimulator ( cWorld * a_World )
: super ( a_World )
{
}
cRedstoneSimulator : : ~ cRedstoneSimulator ( )
{
}
void cRedstoneSimulator : : WakeUp ( int a_X , int a_Y , int a_Z )
{
if ( cRedstone : : s_UseRedstone ) return ; // Using the other/broken simulator
cCSLock Lock ( m_CS ) ;
m_Blocks . push_back ( Vector3i ( a_X , a_Y , a_Z ) ) ;
}
void cRedstoneSimulator : : Simulate ( float a_Dt )
{
if ( cRedstone : : s_UseRedstone ) return ; // Using the other/broken simulator
// Toggle torches on/off
while ( ! m_RefreshTorchesAround . empty ( ) )
{
2012-03-06 16:06:51 -05:00
Vector3i pos = m_RefreshTorchesAround . front ( ) ;
m_RefreshTorchesAround . pop_front ( ) ;
2012-03-01 10:18:59 -05:00
RefreshTorchesAround ( pos ) ;
}
2012-03-06 16:06:51 -05:00
// Set repeaters to correct values, and decrement ticks
for ( RepeaterList : : iterator itr = m_SetRepeaters . begin ( ) ; itr ! = m_SetRepeaters . end ( ) ; )
{
( * itr ) . Ticks - - ;
if ( ( * itr ) . Ticks < = 0 )
{
char Block = m_World - > GetBlock ( ( * itr ) . Position ) ;
if ( ( * itr ) . bPowerOn = = true & & Block = = E_BLOCK_REDSTONE_REPEATER_OFF )
{
m_World - > FastSetBlock ( ( * itr ) . Position . x , ( * itr ) . Position . y , ( * itr ) . Position . z , E_BLOCK_REDSTONE_REPEATER_ON , m_World - > GetBlockMeta ( ( * itr ) . Position ) ) ;
m_Blocks . push_back ( ( * itr ) . Position ) ;
}
else if ( ( * itr ) . bPowerOn = = false & & Block = = E_BLOCK_REDSTONE_REPEATER_ON )
{
m_World - > FastSetBlock ( ( * itr ) . Position . x , ( * itr ) . Position . y , ( * itr ) . Position . z , E_BLOCK_REDSTONE_REPEATER_OFF , m_World - > GetBlockMeta ( ( * itr ) . Position ) ) ;
m_Blocks . push_back ( ( * itr ) . Position ) ;
}
if ( ( * itr ) . bPowerOffNextTime )
{
( * itr ) . bPowerOn = false ;
( * itr ) . bPowerOffNextTime = false ;
( * itr ) . Ticks = 10 ; // TODO: Look up actual ticks from block metadata
+ + itr ;
}
else
{
itr = m_SetRepeaters . erase ( itr ) ;
}
}
else
{
+ + itr ;
}
}
2012-03-01 10:18:59 -05:00
// Handle changed blocks
{
cCSLock Lock ( m_CS ) ;
std : : swap ( m_Blocks , m_BlocksBuffer ) ;
}
for ( BlockList : : iterator itr = m_BlocksBuffer . begin ( ) ; itr ! = m_BlocksBuffer . end ( ) ; + + itr )
{
HandleChange ( * itr ) ;
}
m_BlocksBuffer . clear ( ) ;
}
void cRedstoneSimulator : : RefreshTorchesAround ( const Vector3i & a_BlockPos )
{
static Vector3i Surroundings [ ] = {
Vector3i ( - 1 , 0 , 0 ) ,
Vector3i ( 1 , 0 , 0 ) ,
Vector3i ( 0 , 0 , - 1 ) ,
Vector3i ( 0 , 0 , 1 ) ,
Vector3i ( 0 , 1 , 0 ) , // Also toggle torch on top
} ;
char TargetBlockID = E_BLOCK_REDSTONE_TORCH_ON ;
2012-03-06 16:06:51 -05:00
char TargetRepeaterID = E_BLOCK_REDSTONE_REPEATER_OFF ;
2012-03-01 10:18:59 -05:00
if ( IsPowered ( a_BlockPos , true ) )
{
TargetBlockID = E_BLOCK_REDSTONE_TORCH_OFF ;
2012-03-06 16:06:51 -05:00
TargetRepeaterID = E_BLOCK_REDSTONE_REPEATER_ON ;
2012-03-04 11:59:39 -05:00
//if( m_World->GetBlock( a_BlockPos ) == E_BLOCK_DIRT )
//{
// m_World->FastSetBlock( a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_STONE, 0 );
//}
2012-03-01 10:18:59 -05:00
}
else
{
2012-03-04 11:59:39 -05:00
//if( m_World->GetBlock( a_BlockPos ) == E_BLOCK_STONE )
//{
// m_World->FastSetBlock( a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_DIRT, 0 );
//}
2012-03-01 10:18:59 -05:00
}
for ( unsigned int i = 0 ; i < ARRAYCOUNT ( Surroundings ) ; + + i )
{
Vector3i TorchPos = a_BlockPos + Surroundings [ i ] ;
const char Block = m_World - > GetBlock ( TorchPos ) ;
2012-03-06 16:06:51 -05:00
switch ( Block )
2012-03-01 10:18:59 -05:00
{
2012-03-06 16:06:51 -05:00
case E_BLOCK_REDSTONE_TORCH_ON :
case E_BLOCK_REDSTONE_TORCH_OFF :
2012-03-01 10:18:59 -05:00
if ( Block ! = TargetBlockID )
{
char TorchMeta = m_World - > GetBlockMeta ( TorchPos ) ;
if ( cTorch : : IsAttachedTo ( TorchPos , TorchMeta , a_BlockPos ) )
{
m_World - > FastSetBlock ( TorchPos . x , TorchPos . y , TorchPos . z , TargetBlockID , m_World - > GetBlockMeta ( TorchPos ) ) ;
m_Blocks . push_back ( TorchPos ) ;
}
}
2012-03-06 16:06:51 -05:00
break ;
case E_BLOCK_REDSTONE_REPEATER_ON :
case E_BLOCK_REDSTONE_REPEATER_OFF :
if ( Block ! = TargetRepeaterID & & cRedstone : : IsRepeaterPointingAway ( TorchPos , m_World - > GetBlockMeta ( TorchPos ) , a_BlockPos ) )
{
SetRepeater ( TorchPos , 10 , TargetRepeaterID = = E_BLOCK_REDSTONE_REPEATER_ON ) ;
}
break ;
default :
break ;
} ;
2012-03-01 10:18:59 -05:00
}
}
void cRedstoneSimulator : : HandleChange ( const Vector3i & a_BlockPos )
{
std : : deque < Vector3i > SpreadStack ;
Vector3i Surroundings [ ] = {
Vector3i ( 1 , 0 , 0 ) ,
Vector3i ( 1 , 1 , 0 ) ,
Vector3i ( 1 , - 1 , 0 ) ,
Vector3i ( - 1 , 0 , 0 ) ,
Vector3i ( - 1 , 1 , 0 ) ,
Vector3i ( - 1 , - 1 , 0 ) ,
Vector3i ( 0 , 0 , 1 ) ,
Vector3i ( 0 , 1 , 1 ) ,
Vector3i ( 0 , - 1 , 1 ) ,
Vector3i ( 0 , 0 , - 1 ) ,
Vector3i ( 0 , 1 , - 1 ) ,
Vector3i ( 0 , - 1 , - 1 ) ,
Vector3i ( 0 , - 1 , 0 ) ,
} ;
char Block = m_World - > GetBlock ( a_BlockPos ) ;
// First check whether torch should be on or off
if ( Block = = E_BLOCK_REDSTONE_TORCH_ON | | Block = = E_BLOCK_REDSTONE_TORCH_OFF )
{
static Vector3i Surroundings [ ] = {
Vector3i ( - 1 , 0 , 0 ) ,
Vector3i ( 1 , 0 , 0 ) ,
Vector3i ( 0 , 0 , - 1 ) ,
Vector3i ( 0 , 0 , 1 ) ,
Vector3i ( 0 , - 1 , 0 ) ,
} ;
for ( unsigned int i = 0 ; i < ARRAYCOUNT ( Surroundings ) ; + + i )
{
Vector3i pos = a_BlockPos + Surroundings [ i ] ;
char OtherBlock = m_World - > GetBlock ( pos ) ;
if ( ( OtherBlock ! = E_BLOCK_AIR ) & & ( OtherBlock ! = E_BLOCK_REDSTONE_TORCH_ON ) & & ( OtherBlock ! = E_BLOCK_REDSTONE_TORCH_OFF ) )
{
RefreshTorchesAround ( pos ) ;
}
}
Block = m_World - > GetBlock ( a_BlockPos ) ; // Make sure we got the updated block
}
2012-03-06 16:06:51 -05:00
else if ( Block = = E_BLOCK_REDSTONE_REPEATER_ON | | Block = = E_BLOCK_REDSTONE_REPEATER_OFF ) // Check if repeater is powered by a 'powered block' (not wires/torch)
{
Vector3i Direction = cRedstone : : GetRepeaterDirection ( m_World - > GetBlockMeta ( a_BlockPos ) ) ;
Vector3i pos = a_BlockPos - Direction ; // NOTE: It's minus Direction
char OtherBlock = m_World - > GetBlock ( pos ) ;
if ( ( OtherBlock ! = E_BLOCK_AIR ) & & ( OtherBlock ! = E_BLOCK_REDSTONE_TORCH_ON ) & & ( OtherBlock ! = E_BLOCK_REDSTONE_TORCH_OFF ) & & ( OtherBlock ! = E_BLOCK_REDSTONE_WIRE ) )
{
RefreshTorchesAround ( pos ) ;
}
else
{
SetRepeater ( a_BlockPos , 10 , IsPowered ( a_BlockPos , false ) ) ;
}
Block = m_World - > GetBlock ( a_BlockPos ) ;
}
2012-03-01 10:18:59 -05:00
BlockList Sources ;
// If torch is still on, use it as a source
if ( Block = = E_BLOCK_REDSTONE_TORCH_ON )
{
Sources . push_back ( a_BlockPos ) ;
}
2012-03-06 16:06:51 -05:00
else if ( Block = = E_BLOCK_REDSTONE_REPEATER_ON )
{
static Vector3i Surroundings [ ] = { // It only spreads right in front, and one block up
Vector3i ( 0 , 0 , 0 ) ,
Vector3i ( 0 , 1 , 0 ) ,
} ;
Vector3i Direction = cRedstone : : GetRepeaterDirection ( m_World - > GetBlockMeta ( a_BlockPos ) ) ;
for ( unsigned int i = 0 ; i < ARRAYCOUNT ( Surroundings ) ; + + i )
{
Vector3i pos = a_BlockPos + Direction + Surroundings [ i ] ;
if ( PowerBlock ( pos , a_BlockPos , 0xf ) )
{
SpreadStack . push_back ( pos ) ;
}
}
}
2012-03-01 10:18:59 -05:00
// Power all blocks legally connected to the sources
2012-03-06 16:06:51 -05:00
if ( Block ! = E_BLOCK_REDSTONE_REPEATER_ON )
2012-03-01 10:18:59 -05:00
{
BlockList NewSources = RemoveCurrent ( a_BlockPos ) ;
Sources . insert ( Sources . end ( ) , NewSources . begin ( ) , NewSources . end ( ) ) ;
while ( ! Sources . empty ( ) )
{
Vector3i SourcePos = Sources . back ( ) ;
2012-03-06 16:06:51 -05:00
Sources . pop_back ( ) ;
char Block = m_World - > GetBlock ( SourcePos ) ;
switch ( Block )
2012-03-01 10:18:59 -05:00
{
2012-03-06 16:06:51 -05:00
case E_BLOCK_REDSTONE_TORCH_OFF :
case E_BLOCK_REDSTONE_TORCH_ON :
2012-03-01 10:18:59 -05:00
{
2012-03-06 16:06:51 -05:00
static Vector3i Surroundings [ ] = {
Vector3i ( - 1 , 0 , 0 ) ,
Vector3i ( 1 , 0 , 0 ) ,
Vector3i ( 0 , 0 , - 1 ) ,
Vector3i ( 0 , 0 , 1 ) ,
} ;
for ( unsigned int i = 0 ; i < ARRAYCOUNT ( Surroundings ) ; + + i )
{
Vector3i OtherPos = SourcePos + Surroundings [ i ] ;
if ( PowerBlock ( OtherPos , a_BlockPos , 0xf ) )
{
SpreadStack . push_back ( OtherPos ) ; // Changed, so add to stack
}
}
2012-03-01 10:18:59 -05:00
}
2012-03-06 16:06:51 -05:00
break ;
case E_BLOCK_REDSTONE_REPEATER_OFF :
case E_BLOCK_REDSTONE_REPEATER_ON :
{
static Vector3i Surroundings [ ] = {
Vector3i ( 0 , 0 , 0 ) ,
Vector3i ( 0 , 1 , 0 ) ,
} ;
Vector3i Direction = cRedstone : : GetRepeaterDirection ( m_World - > GetBlockMeta ( SourcePos ) ) ;
for ( unsigned int i = 0 ; i < ARRAYCOUNT ( Surroundings ) ; + + i )
{
Vector3i pos = SourcePos + Direction + Surroundings [ i ] ;
if ( PowerBlock ( pos , a_BlockPos , 0xf ) )
{
SpreadStack . push_back ( pos ) ;
}
}
}
break ;
} ;
2012-03-01 10:18:59 -05:00
}
}
// Do a floodfill
while ( ! SpreadStack . empty ( ) )
{
Vector3i pos = SpreadStack . back ( ) ;
SpreadStack . pop_back ( ) ;
char Meta = m_World - > GetBlockMeta ( pos ) ;
for ( unsigned int i = 0 ; i < ARRAYCOUNT ( Surroundings ) ; + + i )
{
Vector3i OtherPos = pos + Surroundings [ i ] ;
if ( PowerBlock ( OtherPos , pos , Meta - 1 ) )
{
SpreadStack . push_back ( OtherPos ) ; // Changed, so add to stack
}
}
}
// Only after a redstone area has been completely simulated the redstone entities can react
while ( ! m_RefreshPistons . empty ( ) )
{
Vector3i pos = m_RefreshPistons . back ( ) ;
m_RefreshPistons . pop_back ( ) ;
char Block = m_World - > GetBlock ( pos ) ;
switch ( Block )
{
case E_BLOCK_PISTON :
if ( IsPowered ( pos ) )
{
cPiston Piston ( m_World ) ;
Piston . ExtendPiston ( pos . x , pos . y , pos . z ) ;
}
else
{
cPiston Piston ( m_World ) ;
Piston . RetractPiston ( pos . x , pos . y , pos . z ) ;
}
break ;
default :
break ;
} ;
}
}
bool cRedstoneSimulator : : PowerBlock ( const Vector3i & a_BlockPos , const Vector3i & a_FromBlock , char a_Power )
{
char Block = m_World - > GetBlock ( a_BlockPos ) ;
switch ( Block )
{
case E_BLOCK_REDSTONE_WIRE :
{
if ( m_World - > GetBlockMeta ( a_BlockPos ) < a_Power )
{
m_World - > SetBlockMeta ( a_BlockPos , a_Power ) ;
return true ;
}
}
break ;
case E_BLOCK_PISTON :
{
m_RefreshPistons . push_back ( a_BlockPos ) ;
}
break ;
2012-03-06 16:06:51 -05:00
case E_BLOCK_REDSTONE_REPEATER_OFF :
case E_BLOCK_REDSTONE_REPEATER_ON :
{
if ( cRedstone : : IsRepeaterPointingAway ( a_BlockPos , m_World - > GetBlockMeta ( a_BlockPos ) , a_FromBlock ) )
{
SetRepeater ( a_BlockPos , 10 , true ) ;
}
}
break ;
2012-03-01 10:18:59 -05:00
default :
{
if ( Block ! = E_BLOCK_AIR & & Block ! = E_BLOCK_REDSTONE_TORCH_ON & & Block ! = E_BLOCK_REDSTONE_TORCH_OFF )
{
if ( IsPowered ( a_BlockPos , true ) )
{
m_RefreshTorchesAround . push_back ( a_BlockPos ) ;
}
}
}
break ;
} ;
return false ;
}
2012-03-06 16:06:51 -05:00
int cRedstoneSimulator : : UnPowerBlock ( const Vector3i & a_BlockPos , const Vector3i & a_FromBlock )
2012-03-01 10:18:59 -05:00
{
char Block = m_World - > GetBlock ( a_BlockPos ) ;
switch ( Block )
{
case E_BLOCK_REDSTONE_WIRE :
{
if ( m_World - > GetBlockMeta ( a_BlockPos ) > 0 )
{
m_World - > SetBlockMeta ( a_BlockPos , 0 ) ;
return 1 ;
}
}
break ;
case E_BLOCK_PISTON :
{
m_RefreshPistons . push_back ( a_BlockPos ) ;
}
break ;
case E_BLOCK_REDSTONE_TORCH_ON :
{
return 2 ;
}
break ;
2012-03-06 16:06:51 -05:00
case E_BLOCK_REDSTONE_REPEATER_ON :
{
if ( cRedstone : : IsRepeaterPointingTo ( a_BlockPos , m_World - > GetBlockMeta ( a_BlockPos ) , a_FromBlock )
| | cRedstone : : IsRepeaterPointingTo ( a_BlockPos , m_World - > GetBlockMeta ( a_BlockPos ) , a_FromBlock - Vector3i ( 0 , 1 , 0 ) ) ) // Check if repeater is next/below wire
{
return 2 ;
}
else if ( cRedstone : : IsRepeaterPointingAway ( a_BlockPos , m_World - > GetBlockMeta ( a_BlockPos ) , a_FromBlock ) )
{
SetRepeater ( a_BlockPos , 10 , false ) ;
}
}
case E_BLOCK_REDSTONE_REPEATER_OFF :
if ( cRedstone : : IsRepeaterPointingAway ( a_BlockPos , m_World - > GetBlockMeta ( a_BlockPos ) , a_FromBlock ) )
{
SetRepeater ( a_BlockPos , 10 , false ) ;
}
break ;
2012-03-01 10:18:59 -05:00
default :
if ( Block ! = E_BLOCK_AIR & & Block ! = E_BLOCK_REDSTONE_TORCH_ON & & Block ! = E_BLOCK_REDSTONE_TORCH_OFF )
{
if ( ! IsPowered ( a_BlockPos , true ) )
{
m_RefreshTorchesAround . push_back ( a_BlockPos ) ;
}
}
break ;
} ;
return 0 ;
}
// Removes current from all powered redstone wires until it reaches an energy source.
// Also returns all energy sources it encountered
cRedstoneSimulator : : BlockList cRedstoneSimulator : : RemoveCurrent ( const Vector3i & a_BlockPos )
{
2012-03-06 16:06:51 -05:00
2012-03-01 10:18:59 -05:00
std : : deque < Vector3i > SpreadStack ;
std : : deque < Vector3i > FoundSources ;
Vector3i Surroundings [ ] = {
Vector3i ( 1 , 0 , 0 ) ,
Vector3i ( 1 , 1 , 0 ) ,
Vector3i ( 1 , - 1 , 0 ) ,
Vector3i ( - 1 , 0 , 0 ) ,
Vector3i ( - 1 , 1 , 0 ) ,
Vector3i ( - 1 , - 1 , 0 ) ,
Vector3i ( 0 , 0 , 1 ) ,
Vector3i ( 0 , 1 , 1 ) ,
Vector3i ( 0 , - 1 , 1 ) ,
Vector3i ( 0 , 0 , - 1 ) ,
Vector3i ( 0 , 1 , - 1 ) ,
Vector3i ( 0 , - 1 , - 1 ) ,
Vector3i ( 0 , - 1 , 0 ) ,
} ;
char Block = m_World - > GetBlock ( a_BlockPos ) ;
2012-03-06 16:06:51 -05:00
if ( Block = = E_BLOCK_REDSTONE_REPEATER_ON | | Block = = E_BLOCK_REDSTONE_REPEATER_OFF )
{
static Vector3i Surroundings [ ] = { // Repeaters only spread right in front and 1 block up
Vector3i ( 0 , 0 , 0 ) ,
Vector3i ( 0 , 1 , 0 ) ,
} ;
Vector3i Direction = cRedstone : : GetRepeaterDirection ( m_World - > GetBlockMeta ( a_BlockPos ) ) ;
for ( unsigned int i = 0 ; i < ARRAYCOUNT ( Surroundings ) ; + + i )
{
Vector3i pos = a_BlockPos + Direction + Surroundings [ i ] ;
int RetVal = UnPowerBlock ( pos , a_BlockPos ) ;
if ( RetVal = = 1 )
{
SpreadStack . push_back ( pos ) ; // Changed, so add to stack
}
else if ( RetVal = = 2 )
{
FoundSources . push_back ( pos ) ;
}
}
}
else if ( Block = = E_BLOCK_REDSTONE_TORCH_OFF | | Block = = E_BLOCK_REDSTONE_TORCH_ON )
2012-03-01 10:18:59 -05:00
{
static Vector3i Surroundings [ ] = { // Torches only spread on the same level
Vector3i ( - 1 , 0 , 0 ) ,
Vector3i ( 1 , 0 , 0 ) ,
Vector3i ( 0 , 0 , - 1 ) ,
Vector3i ( 0 , 0 , 1 ) ,
} ;
for ( unsigned int i = 0 ; i < ARRAYCOUNT ( Surroundings ) ; + + i )
{
Vector3i pos = Vector3i ( a_BlockPos ) + Surroundings [ i ] ;
2012-03-06 16:06:51 -05:00
int RetVal = UnPowerBlock ( pos , a_BlockPos ) ;
2012-03-01 10:18:59 -05:00
if ( RetVal = = 1 )
{
SpreadStack . push_back ( pos ) ; // Changed, so add to stack
}
else if ( RetVal = = 2 )
{
FoundSources . push_back ( pos ) ;
}
}
}
else
{
SpreadStack . push_back ( a_BlockPos ) ;
}
while ( ! SpreadStack . empty ( ) )
{
Vector3i pos = SpreadStack . back ( ) ;
SpreadStack . pop_back ( ) ;
for ( unsigned int i = 0 ; i < ARRAYCOUNT ( Surroundings ) ; + + i )
{
Vector3i OtherPos = pos + Surroundings [ i ] ;
2012-03-06 16:06:51 -05:00
int RetVal = UnPowerBlock ( OtherPos , pos ) ;
2012-03-01 10:18:59 -05:00
if ( RetVal = = 1 )
{
SpreadStack . push_back ( OtherPos ) ; // Changed, so add to stack
}
else if ( RetVal = = 2 )
{
FoundSources . push_back ( OtherPos ) ;
}
}
}
return FoundSources ;
}
2012-03-06 16:06:51 -05:00
bool cRedstoneSimulator : : IsPowering ( const Vector3i & a_PowerPos , const Vector3i & a_BlockPos , eRedstoneDirection a_WireDirection , bool a_bOnlyByWire )
2012-03-01 10:18:59 -05:00
{
2012-03-06 16:06:51 -05:00
char PowerBlock = m_World - > GetBlock ( a_PowerPos ) ;
if ( ! a_bOnlyByWire & & PowerBlock = = E_BLOCK_REDSTONE_TORCH_ON ) return true ;
if ( PowerBlock = = E_BLOCK_REDSTONE_REPEATER_ON ) // A repeater pointing towards block is regarded as wire
2012-03-01 10:18:59 -05:00
{
2012-03-06 16:06:51 -05:00
if ( cRedstone : : IsRepeaterPointingTo ( a_PowerPos , m_World - > GetBlockMeta ( a_PowerPos ) , a_BlockPos ) )
2012-03-01 10:18:59 -05:00
{
2012-03-06 16:06:51 -05:00
return true ;
2012-03-01 10:18:59 -05:00
}
}
2012-03-06 16:06:51 -05:00
if ( PowerBlock = = E_BLOCK_REDSTONE_WIRE )
2012-03-01 10:18:59 -05:00
{
2012-03-06 16:06:51 -05:00
if ( m_World - > GetBlockMeta ( a_PowerPos ) > 0 )
2012-03-01 10:18:59 -05:00
{
2012-03-06 16:06:51 -05:00
if ( GetDirection ( a_PowerPos ) = = a_WireDirection )
2012-03-01 10:18:59 -05:00
{
return true ;
}
}
}
2012-03-06 16:06:51 -05:00
return false ;
}
bool cRedstoneSimulator : : IsPowered ( const Vector3i & a_BlockPos , bool a_bOnlyByWire /* = false */ )
{
char Block = m_World - > GetBlock ( a_BlockPos ) ;
if ( Block = = E_BLOCK_REDSTONE_REPEATER_OFF | | Block = = E_BLOCK_REDSTONE_REPEATER_ON )
2012-03-01 10:18:59 -05:00
{
2012-03-06 16:06:51 -05:00
Vector3i Behind = a_BlockPos - cRedstone : : GetRepeaterDirection ( m_World - > GetBlockMeta ( a_BlockPos ) ) ;
char BehindBlock = m_World - > GetBlock ( Behind ) ;
if ( BehindBlock = = E_BLOCK_REDSTONE_TORCH_ON )
2012-03-01 10:18:59 -05:00
{
2012-03-06 16:06:51 -05:00
return true ;
}
if ( BehindBlock = = E_BLOCK_REDSTONE_WIRE )
{
if ( m_World - > GetBlockMeta ( Behind ) > 0 )
2012-03-01 10:18:59 -05:00
{
return true ;
}
}
2012-03-06 16:06:51 -05:00
if ( BehindBlock = = E_BLOCK_REDSTONE_REPEATER_ON )
2012-03-01 10:18:59 -05:00
{
2012-03-06 16:06:51 -05:00
if ( cRedstone : : IsRepeaterPointingTo ( Behind , m_World - > GetBlockMeta ( Behind ) , a_BlockPos ) )
2012-03-01 10:18:59 -05:00
{
return true ;
}
}
2012-03-06 16:06:51 -05:00
return false ;
2012-03-01 10:18:59 -05:00
}
2012-03-06 16:06:51 -05:00
if ( IsPowering ( Vector3i ( a_BlockPos . x - 1 , a_BlockPos . y , a_BlockPos . z ) , a_BlockPos , REDSTONE_X_POS , a_bOnlyByWire ) )
return true ;
if ( IsPowering ( Vector3i ( a_BlockPos . x + 1 , a_BlockPos . y , a_BlockPos . z ) , a_BlockPos , REDSTONE_X_NEG , a_bOnlyByWire ) )
return true ;
if ( IsPowering ( Vector3i ( a_BlockPos . x , a_BlockPos . y , a_BlockPos . z - 1 ) , a_BlockPos , REDSTONE_Z_POS , a_bOnlyByWire ) )
return true ;
if ( IsPowering ( Vector3i ( a_BlockPos . x , a_BlockPos . y , a_BlockPos . z + 1 ) , a_BlockPos , REDSTONE_Z_NEG , a_bOnlyByWire ) )
return true ;
2012-03-01 10:18:59 -05:00
// Only wires can power the bottom block
char PosY = m_World - > GetBlock ( a_BlockPos . x , a_BlockPos . y + 1 , a_BlockPos . z ) ;
if ( PosY = = E_BLOCK_REDSTONE_WIRE )
{
if ( m_World - > GetBlockMeta ( a_BlockPos . x , a_BlockPos . y + 1 , a_BlockPos . z ) > 0 )
{
return true ;
}
}
return false ;
}
2012-03-06 16:06:51 -05:00
// Believe me, it works!! TODO: Add repeaters and low/high wires
2012-03-01 10:18:59 -05:00
cRedstoneSimulator : : eRedstoneDirection cRedstoneSimulator : : GetDirection ( int a_X , int a_Y , int a_Z )
{
int Dir = REDSTONE_NONE ;
char NegX = m_World - > GetBlock ( a_X - 1 , a_Y , a_Z ) ;
if ( NegX = = E_BLOCK_REDSTONE_WIRE | | NegX = = E_BLOCK_REDSTONE_TORCH_ON )
{
Dir | = ( REDSTONE_X_POS ) ;
}
char PosX = m_World - > GetBlock ( a_X + 1 , a_Y , a_Z ) ;
if ( PosX = = E_BLOCK_REDSTONE_WIRE | | PosX = = E_BLOCK_REDSTONE_TORCH_ON )
{
Dir | = ( REDSTONE_X_NEG ) ;
}
char NegZ = m_World - > GetBlock ( a_X , a_Y , a_Z - 1 ) ;
if ( NegZ = = E_BLOCK_REDSTONE_WIRE | | NegZ = = E_BLOCK_REDSTONE_TORCH_ON )
{
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 ;
}
char PosZ = m_World - > GetBlock ( a_X , a_Y , a_Z + 1 ) ;
if ( PosZ = = E_BLOCK_REDSTONE_WIRE | | PosZ = = E_BLOCK_REDSTONE_TORCH_ON )
{
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 ;
}