2014-04-08 13:49:53 -04:00
2014-02-07 16:59:08 -05:00
# include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
# include "IncrementalRedstoneSimulator.h"
2014-06-28 15:44:34 -04:00
# include "BoundingBox.h"
2014-02-07 16:59:08 -05:00
# include "../BlockEntities/DropSpenserEntity.h"
# include "../BlockEntities/NoteEntity.h"
# include "../BlockEntities/CommandBlockEntity.h"
# include "../Entities/TNTEntity.h"
2014-02-20 13:07:32 -05:00
# include "../Entities/Pickup.h"
2014-02-07 16:59:08 -05:00
# include "../Blocks/BlockTorch.h"
# include "../Blocks/BlockDoor.h"
2014-05-04 09:00:59 -04:00
# include "../Blocks/BlockButton.h"
# include "../Blocks/BlockLever.h"
2014-05-25 08:46:34 -04:00
# include "../Blocks/BlockPiston.h"
2014-06-28 15:44:34 -04:00
# include "../Blocks/BlockTripwireHook.h"
# define WAKE_SIMULATOR_IF_DIRTY(a_Chunk, a_BlockX, a_BlockY, a_BlockZ) if (a_Chunk->IsRedstoneDirty()) WakeUp(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
2014-02-07 16:59:08 -05:00
2014-06-04 04:20:20 -04:00
cIncrementalRedstoneSimulator : : cIncrementalRedstoneSimulator ( cWorld & a_World ) :
super ( a_World ) ,
m_RedstoneSimulatorChunkData ( ) ,
m_PoweredBlocks ( ) ,
m_LinkedPoweredBlocks ( ) ,
m_SimulatedPlayerToggleableBlocks ( ) ,
m_RepeatersDelayList ( ) ,
m_Chunk ( )
2014-02-07 16:59:08 -05:00
{
}
cIncrementalRedstoneSimulator : : ~ cIncrementalRedstoneSimulator ( )
{
}
2014-02-15 14:56:45 -05:00
void cIncrementalRedstoneSimulator : : RedstoneAddBlock ( int a_BlockX , int a_BlockY , int a_BlockZ , cChunk * a_Chunk , cChunk * a_OtherChunk )
2014-02-07 16:59:08 -05:00
{
if ( ( a_Chunk = = NULL ) | | ! a_Chunk - > IsValid ( ) )
{
return ;
}
else if ( ( a_BlockY < 0 ) | | ( a_BlockY > cChunkDef : : Height ) )
{
return ;
}
2014-02-15 14:56:45 -05:00
// We may be called with coordinates in a chunk that is not the first chunk parameter
// In that case, the actual chunk (which the coordinates are in), will be passed as the second parameter
// Use that Chunk pointer to get a relative position
int RelX = 0 ;
int RelZ = 0 ;
2014-02-07 16:59:08 -05:00
BLOCKTYPE Block ;
NIBBLETYPE Meta ;
2014-06-22 10:04:23 -04:00
cChunk * OtherChunk = a_Chunk ;
2014-02-15 14:56:45 -05:00
if ( a_OtherChunk ! = NULL )
{
RelX = a_BlockX - a_OtherChunk - > GetPosX ( ) * cChunkDef : : Width ;
RelZ = a_BlockZ - a_OtherChunk - > GetPosZ ( ) * cChunkDef : : Width ;
a_OtherChunk - > GetBlockTypeMeta ( RelX , a_BlockY , RelZ , Block , Meta ) ;
2014-06-22 10:04:23 -04:00
OtherChunk = a_OtherChunk ;
2014-02-15 14:56:45 -05:00
}
else
{
RelX = a_BlockX - a_Chunk - > GetPosX ( ) * cChunkDef : : Width ;
RelZ = a_BlockZ - a_Chunk - > GetPosZ ( ) * cChunkDef : : Width ;
a_Chunk - > GetBlockTypeMeta ( RelX , a_BlockY , RelZ , Block , Meta ) ;
}
2014-02-07 16:59:08 -05:00
// Every time a block is changed (AddBlock called), we want to go through all lists and check to see if the coordiantes stored within are still valid
// Checking only when a block is changed, as opposed to every tick, also improves performance
2014-02-15 10:51:49 -05:00
PoweredBlocksList * PoweredBlocks = a_Chunk - > GetRedstoneSimulatorPoweredBlocksList ( ) ;
2014-04-15 08:15:56 -04:00
for ( PoweredBlocksList : : iterator itr = PoweredBlocks - > begin ( ) ; itr ! = PoweredBlocks - > end ( ) ; )
2014-02-07 16:59:08 -05:00
{
if ( ! itr - > a_SourcePos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) )
{
2014-04-15 08:15:56 -04:00
+ + itr ;
2014-02-07 16:59:08 -05:00
continue ;
}
if ( ! IsPotentialSource ( Block ) )
{
LOGD ( " cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list as it no longer connected to a source " , itr - > a_BlockPos . x , itr - > a_BlockPos . y , itr - > a_BlockPos . z ) ;
2014-04-15 08:15:56 -04:00
itr = PoweredBlocks - > erase ( itr ) ;
2014-06-22 10:04:23 -04:00
a_Chunk - > SetIsRedstoneDirty ( true ) ;
OtherChunk - > SetIsRedstoneDirty ( true ) ;
2014-04-15 08:15:56 -04:00
continue ;
2014-02-07 16:59:08 -05:00
}
else if (
// Changeable sources
( ( Block = = E_BLOCK_REDSTONE_WIRE ) & & ( Meta = = 0 ) ) | |
( ( Block = = E_BLOCK_LEVER ) & & ! IsLeverOn ( Meta ) ) | |
2014-06-28 15:44:34 -04:00
( ( Block = = E_BLOCK_DETECTOR_RAIL ) & & ( ( Meta & 0x08 ) = = 0 ) ) | |
2014-02-07 16:59:08 -05:00
( ( ( Block = = E_BLOCK_STONE_BUTTON ) | | ( Block = = E_BLOCK_WOODEN_BUTTON ) ) & & ( ! IsButtonOn ( Meta ) ) ) | |
2014-02-20 13:07:32 -05:00
( ( ( Block = = E_BLOCK_STONE_PRESSURE_PLATE ) | | ( Block = = E_BLOCK_WOODEN_PRESSURE_PLATE ) ) & & ( Meta = = 0 ) ) | |
2014-06-28 15:44:34 -04:00
( ( ( Block = = E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE ) | | ( Block = = E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE ) ) & & ( Meta = = 0 ) ) | |
( ( Block = = E_BLOCK_TRIPWIRE_HOOK ) & & ( ( Meta & 0x08 ) = = 0 ) )
2014-02-07 16:59:08 -05:00
)
{
LOGD ( " cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch " , itr - > a_BlockPos . x , itr - > a_BlockPos . y , itr - > a_BlockPos . z ) ;
2014-04-15 08:15:56 -04:00
itr = PoweredBlocks - > erase ( itr ) ;
2014-06-22 10:04:23 -04:00
a_Chunk - > SetIsRedstoneDirty ( true ) ;
OtherChunk - > SetIsRedstoneDirty ( true ) ;
2014-04-15 08:15:56 -04:00
continue ;
2014-02-07 16:59:08 -05:00
}
2014-06-16 10:12:50 -04:00
else if ( Block = = E_BLOCK_DAYLIGHT_SENSOR )
{
2014-06-22 10:04:23 -04:00
if ( ! m_World . IsChunkLighted ( OtherChunk - > GetPosX ( ) , OtherChunk - > GetPosZ ( ) ) )
2014-06-16 10:12:50 -04:00
{
2014-06-22 10:04:23 -04:00
m_World . QueueLightChunk ( OtherChunk - > GetPosX ( ) , OtherChunk - > GetPosZ ( ) ) ;
2014-06-16 10:12:50 -04:00
}
else
{
2014-06-22 10:04:23 -04:00
if ( OtherChunk - > GetTimeAlteredLight ( OtherChunk - > GetSkyLight ( RelX , a_BlockY + 1 , RelZ ) ) < = 7 )
2014-06-16 10:12:50 -04:00
{
itr = PoweredBlocks - > erase ( itr ) ;
2014-06-22 10:04:23 -04:00
a_Chunk - > SetIsRedstoneDirty ( true ) ;
OtherChunk - > SetIsRedstoneDirty ( true ) ;
2014-06-16 10:12:50 -04:00
continue ;
}
}
}
2014-04-15 08:15:56 -04:00
+ + itr ;
2014-02-07 16:59:08 -05:00
}
2014-02-15 10:51:49 -05:00
LinkedBlocksList * LinkedPoweredBlocks = a_Chunk - > GetRedstoneSimulatorLinkedBlocksList ( ) ;
2014-02-15 14:56:45 -05:00
// We loop through all values (insteading of breaking out at the first) to make sure everything is gone, as there can be multiple SourceBlock entries for one AddBlock coordinate
for ( LinkedBlocksList : : iterator itr = LinkedPoweredBlocks - > begin ( ) ; itr ! = LinkedPoweredBlocks - > end ( ) ; )
2014-02-07 16:59:08 -05:00
{
if ( itr - > a_SourcePos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) )
{
if ( ! IsPotentialSource ( Block ) )
{
LOGD ( " cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer connected to a source " , itr - > a_BlockPos . x , itr - > a_BlockPos . y , itr - > a_BlockPos . z ) ;
2014-02-15 14:56:45 -05:00
itr = LinkedPoweredBlocks - > erase ( itr ) ;
2014-06-22 10:04:23 -04:00
a_Chunk - > SetIsRedstoneDirty ( true ) ;
OtherChunk - > SetIsRedstoneDirty ( true ) ;
2014-02-15 14:56:45 -05:00
continue ;
2014-02-07 16:59:08 -05:00
}
else if (
// Things that can send power through a block but which depends on meta
( ( Block = = E_BLOCK_REDSTONE_WIRE ) & & ( Meta = = 0 ) ) | |
( ( Block = = E_BLOCK_LEVER ) & & ! IsLeverOn ( Meta ) ) | |
2014-05-03 19:39:03 -04:00
( ( ( Block = = E_BLOCK_STONE_BUTTON ) | | ( Block = = E_BLOCK_WOODEN_BUTTON ) ) & & ( ! IsButtonOn ( Meta ) ) ) | |
( ( ( Block = = E_BLOCK_STONE_PRESSURE_PLATE ) | | ( Block = = E_BLOCK_WOODEN_PRESSURE_PLATE ) ) & & ( Meta = = 0 ) ) | |
( ( ( Block = = E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE ) | | ( Block = = E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE ) ) & & ( Meta = = 0 ) )
2014-02-07 16:59:08 -05:00
)
{
LOGD ( " cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list due to present/past metadata mismatch " , itr - > a_BlockPos . x , itr - > a_BlockPos . y , itr - > a_BlockPos . z ) ;
2014-02-15 14:56:45 -05:00
itr = LinkedPoweredBlocks - > erase ( itr ) ;
2014-06-22 10:04:23 -04:00
a_Chunk - > SetIsRedstoneDirty ( true ) ;
OtherChunk - > SetIsRedstoneDirty ( true ) ;
2014-02-15 14:56:45 -05:00
continue ;
2014-02-07 16:59:08 -05:00
}
}
else if ( itr - > a_MiddlePos . Equals ( Vector3i ( a_BlockX , a_BlockY , a_BlockZ ) ) )
{
if ( ! IsViableMiddleBlock ( Block ) )
{
LOGD ( " cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer powered through a valid middle block " , itr - > a_BlockPos . x , itr - > a_BlockPos . y , itr - > a_BlockPos . z ) ;
2014-02-15 14:56:45 -05:00
itr = LinkedPoweredBlocks - > erase ( itr ) ;
2014-06-22 10:04:23 -04:00
a_Chunk - > SetIsRedstoneDirty ( true ) ;
OtherChunk - > SetIsRedstoneDirty ( true ) ;
2014-02-15 14:56:45 -05:00
continue ;
2014-02-07 16:59:08 -05:00
}
}
2014-02-15 14:56:45 -05:00
+ + itr ;
2014-02-07 16:59:08 -05:00
}
2014-02-15 14:56:45 -05:00
SimulatedPlayerToggleableList * SimulatedPlayerToggleableBlocks = a_Chunk - > GetRedstoneSimulatorSimulatedPlayerToggleableList ( ) ;
2014-02-15 10:51:49 -05:00
for ( SimulatedPlayerToggleableList : : iterator itr = SimulatedPlayerToggleableBlocks - > begin ( ) ; itr ! = SimulatedPlayerToggleableBlocks - > end ( ) ; + + itr )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( ! itr - > a_RelBlockPos . Equals ( Vector3i ( RelX , a_BlockY , RelZ ) ) )
2014-02-07 16:59:08 -05:00
{
continue ;
}
if ( ! IsAllowedBlock ( Block ) )
{
2014-04-27 12:35:41 -04:00
LOGD ( " cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from toggleable simulated list as it is no longer redstone " , itr - > a_RelBlockPos . x , itr - > a_RelBlockPos . y , itr - > a_RelBlockPos . z ) ;
2014-02-15 14:56:45 -05:00
SimulatedPlayerToggleableBlocks - > erase ( itr ) ;
2014-02-07 16:59:08 -05:00
break ;
}
}
2014-02-15 10:51:49 -05:00
RepeatersDelayList * RepeatersDelayList = a_Chunk - > GetRedstoneSimulatorRepeatersDelayList ( ) ;
for ( RepeatersDelayList : : iterator itr = RepeatersDelayList - > begin ( ) ; itr ! = RepeatersDelayList - > end ( ) ; + + itr )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( ! itr - > a_RelBlockPos . Equals ( Vector3i ( RelX , a_BlockY , RelZ ) ) )
2014-02-07 16:59:08 -05:00
{
continue ;
}
if ( ( Block ! = E_BLOCK_REDSTONE_REPEATER_ON ) & & ( Block ! = E_BLOCK_REDSTONE_REPEATER_OFF ) )
{
2014-02-15 14:56:45 -05:00
RepeatersDelayList - > erase ( itr ) ;
2014-02-07 16:59:08 -05:00
break ;
}
}
2014-02-15 19:45:14 -05:00
if ( a_OtherChunk ! = NULL )
{
// DO NOT touch our chunk's data structure if we are being called with coordinates from another chunk - this one caused me massive grief :P
return ;
}
2014-02-15 10:51:49 -05:00
cRedstoneSimulatorChunkData * RedstoneSimulatorChunkData = a_Chunk - > GetRedstoneSimulatorData ( ) ;
for ( cRedstoneSimulatorChunkData : : iterator itr = RedstoneSimulatorChunkData - > begin ( ) ; itr ! = RedstoneSimulatorChunkData - > end ( ) ; + + itr )
2014-02-07 16:59:08 -05:00
{
if ( ( itr - > x = = RelX ) & & ( itr - > y = = a_BlockY ) & & ( itr - > z = = RelZ ) ) // We are at an entry matching the current (changed) block
{
if ( ! IsAllowedBlock ( Block ) )
{
itr - > DataTwo = true ; // The new blocktype is not redstone; it must be queued to be removed from this list
}
else
{
2014-06-12 12:13:39 -04:00
itr - > DataTwo = false ;
2014-02-07 16:59:08 -05:00
itr - > Data = Block ; // Update block information
}
return ;
}
}
if ( ! IsAllowedBlock ( Block ) )
{
return ;
}
2014-06-06 15:36:50 -04:00
for ( cRedstoneSimulatorChunkData : : iterator itr = a_Chunk - > GetRedstoneSimulatorQueuedData ( ) - > begin ( ) ; itr ! = a_Chunk - > GetRedstoneSimulatorQueuedData ( ) - > end ( ) ; + + itr )
{
if ( ( itr - > x = = RelX ) & & ( itr - > y = = a_BlockY ) & & ( itr - > z = = RelZ ) )
{
// Can't have duplicates in here either, in case something adds the block again before the structure can written to the main chunk data
return ;
}
}
2014-06-04 18:23:09 -04:00
a_Chunk - > GetRedstoneSimulatorQueuedData ( ) - > push_back ( cCoordWithBlockAndBool ( RelX , a_BlockY , RelZ , Block , false ) ) ;
2014-02-07 16:59:08 -05:00
}
void cIncrementalRedstoneSimulator : : SimulateChunk ( float a_Dt , int a_ChunkX , int a_ChunkZ , cChunk * a_Chunk )
{
2014-02-15 10:51:49 -05:00
m_RedstoneSimulatorChunkData = a_Chunk - > GetRedstoneSimulatorData ( ) ;
2014-06-04 18:23:09 -04:00
if ( m_RedstoneSimulatorChunkData - > empty ( ) & & a_Chunk - > GetRedstoneSimulatorQueuedData ( ) - > empty ( ) )
2014-02-07 16:59:08 -05:00
{
return ;
}
2014-06-04 18:23:09 -04:00
m_RedstoneSimulatorChunkData - > insert ( m_RedstoneSimulatorChunkData - > end ( ) , a_Chunk - > GetRedstoneSimulatorQueuedData ( ) - > begin ( ) , a_Chunk - > GetRedstoneSimulatorQueuedData ( ) - > end ( ) ) ;
a_Chunk - > GetRedstoneSimulatorQueuedData ( ) - > clear ( ) ;
2014-02-15 10:51:49 -05:00
m_PoweredBlocks = a_Chunk - > GetRedstoneSimulatorPoweredBlocksList ( ) ;
m_RepeatersDelayList = a_Chunk - > GetRedstoneSimulatorRepeatersDelayList ( ) ;
m_SimulatedPlayerToggleableBlocks = a_Chunk - > GetRedstoneSimulatorSimulatedPlayerToggleableList ( ) ;
m_LinkedPoweredBlocks = a_Chunk - > GetRedstoneSimulatorLinkedBlocksList ( ) ;
m_Chunk = a_Chunk ;
2014-06-04 18:23:09 -04:00
bool ShouldUpdateSimulateOnceBlocks = false ;
if ( a_Chunk - > IsRedstoneDirty ( ) )
{
// Simulate the majority of devices only if something (blockwise or power-wise) has changed
// Make sure to allow the chunk to resimulate after the initial run if there was a power change (ShouldUpdateSimulateOnceBlocks helps to do this)
2014-06-06 15:36:50 -04:00
a_Chunk - > SetIsRedstoneDirty ( false ) ;
2014-06-04 18:23:09 -04:00
ShouldUpdateSimulateOnceBlocks = true ;
}
2014-02-15 10:51:49 -05:00
2014-06-16 10:07:41 -04:00
HandleRedstoneRepeaterDelays ( ) ;
2014-02-15 10:51:49 -05:00
for ( cRedstoneSimulatorChunkData : : iterator dataitr = m_RedstoneSimulatorChunkData - > begin ( ) ; dataitr ! = m_RedstoneSimulatorChunkData - > end ( ) ; )
2014-02-07 16:59:08 -05:00
{
if ( dataitr - > DataTwo )
{
2014-02-15 10:51:49 -05:00
dataitr = m_RedstoneSimulatorChunkData - > erase ( dataitr ) ;
2014-02-07 16:59:08 -05:00
continue ;
}
switch ( dataitr - > Data )
{
2014-06-06 15:36:50 -04:00
case E_BLOCK_DAYLIGHT_SENSOR : HandleDaylightSensor ( dataitr - > x , dataitr - > y , dataitr - > z ) ; break ;
2014-06-28 15:44:34 -04:00
case E_BLOCK_TRIPWIRE : HandleTripwire ( dataitr - > x , dataitr - > y , dataitr - > z ) ; break ;
case E_BLOCK_TRIPWIRE_HOOK : HandleTripwireHook ( dataitr - > x , dataitr - > y , dataitr - > z ) ; break ;
2014-02-07 16:59:08 -05:00
case E_BLOCK_WOODEN_PRESSURE_PLATE :
case E_BLOCK_STONE_PRESSURE_PLATE :
2014-02-20 13:07:32 -05:00
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE :
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE :
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
HandlePressurePlate ( dataitr - > x , dataitr - > y , dataitr - > z , dataitr - > Data ) ;
2014-02-07 16:59:08 -05:00
break ;
}
2014-06-04 18:23:09 -04:00
default : break ;
}
if ( ShouldUpdateSimulateOnceBlocks )
{
switch ( dataitr - > Data )
{
2014-06-06 15:36:50 -04:00
case E_BLOCK_REDSTONE_WIRE : HandleRedstoneWire ( dataitr - > x , dataitr - > y , dataitr - > z ) ; break ;
2014-06-04 18:23:09 -04:00
case E_BLOCK_COMMAND_BLOCK : HandleCommandBlock ( dataitr - > x , dataitr - > y , dataitr - > z ) ; break ;
case E_BLOCK_NOTE_BLOCK : HandleNoteBlock ( dataitr - > x , dataitr - > y , dataitr - > z ) ; break ;
2014-06-06 15:36:50 -04:00
case E_BLOCK_BLOCK_OF_REDSTONE : HandleRedstoneBlock ( dataitr - > x , dataitr - > y , dataitr - > z ) ; break ;
case E_BLOCK_LEVER : HandleRedstoneLever ( dataitr - > x , dataitr - > y , dataitr - > z ) ; break ;
2014-06-04 18:23:09 -04:00
case E_BLOCK_FENCE_GATE : HandleFenceGate ( dataitr - > x , dataitr - > y , dataitr - > z ) ; break ;
case E_BLOCK_TNT : HandleTNT ( dataitr - > x , dataitr - > y , dataitr - > z ) ; break ;
case E_BLOCK_TRAPDOOR : HandleTrapdoor ( dataitr - > x , dataitr - > y , dataitr - > z ) ; break ;
case E_BLOCK_ACTIVATOR_RAIL :
case E_BLOCK_DETECTOR_RAIL :
case E_BLOCK_POWERED_RAIL :
{
HandleRail ( dataitr - > x , dataitr - > y , dataitr - > z , dataitr - > Data ) ;
break ;
}
case E_BLOCK_WOODEN_DOOR :
case E_BLOCK_IRON_DOOR :
{
HandleDoor ( dataitr - > x , dataitr - > y , dataitr - > z ) ;
break ;
}
case E_BLOCK_REDSTONE_LAMP_OFF :
case E_BLOCK_REDSTONE_LAMP_ON :
{
HandleRedstoneLamp ( dataitr - > x , dataitr - > y , dataitr - > z , dataitr - > Data ) ;
break ;
}
case E_BLOCK_DISPENSER :
case E_BLOCK_DROPPER :
{
HandleDropSpenser ( dataitr - > x , dataitr - > y , dataitr - > z ) ;
break ;
}
case E_BLOCK_PISTON :
case E_BLOCK_STICKY_PISTON :
{
HandlePiston ( dataitr - > x , dataitr - > y , dataitr - > z ) ;
break ;
}
2014-06-16 10:07:41 -04:00
case E_BLOCK_REDSTONE_REPEATER_OFF :
case E_BLOCK_REDSTONE_REPEATER_ON :
{
HandleRedstoneRepeater ( dataitr - > x , dataitr - > y , dataitr - > z , dataitr - > Data ) ;
2014-06-22 09:17:07 -04:00
break ;
2014-06-16 10:07:41 -04:00
}
2014-06-04 18:23:09 -04:00
case E_BLOCK_REDSTONE_TORCH_OFF :
case E_BLOCK_REDSTONE_TORCH_ON :
{
HandleRedstoneTorch ( dataitr - > x , dataitr - > y , dataitr - > z , dataitr - > Data ) ;
break ;
}
case E_BLOCK_STONE_BUTTON :
case E_BLOCK_WOODEN_BUTTON :
{
HandleRedstoneButton ( dataitr - > x , dataitr - > y , dataitr - > z ) ;
break ;
}
default : break ;
}
2014-02-07 16:59:08 -05:00
}
+ + dataitr ;
}
}
2014-02-15 10:51:49 -05:00
void cIncrementalRedstoneSimulator : : WakeUp ( int a_BlockX , int a_BlockY , int a_BlockZ , cChunk * a_Chunk )
{
if (
2014-02-15 19:45:14 -05:00
( ( a_BlockX % cChunkDef : : Width ) < = 1 ) | |
( ( a_BlockX % cChunkDef : : Width ) > = 14 ) | |
( ( a_BlockZ % cChunkDef : : Width ) < = 1 ) | |
( ( a_BlockZ % cChunkDef : : Width ) > = 14 )
2014-02-20 16:17:01 -05:00
) // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks
2014-02-15 10:51:49 -05:00
{
// On a chunk boundary, alert all four sides (i.e. at least one neighbouring chunk)
AddBlock ( a_BlockX , a_BlockY , a_BlockZ , a_Chunk ) ;
2014-02-15 19:45:14 -05:00
2014-02-15 14:56:45 -05:00
// Pass the original coordinates, because when adding things to our simulator lists, we get the chunk that they are in, and therefore any updates need to preseve their position
2014-02-20 16:17:01 -05:00
// RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordiantes are in and +- 2 in GetNeighbour() to accomodate for LinkedPowered blocks being 2 away from chunk boundaries
2014-02-15 19:45:14 -05:00
RedstoneAddBlock ( a_BlockX , a_BlockY , a_BlockZ , a_Chunk - > GetNeighborChunk ( a_BlockX - 2 , a_BlockZ ) , a_Chunk ) ;
RedstoneAddBlock ( a_BlockX , a_BlockY , a_BlockZ , a_Chunk - > GetNeighborChunk ( a_BlockX + 2 , a_BlockZ ) , a_Chunk ) ;
RedstoneAddBlock ( a_BlockX , a_BlockY , a_BlockZ , a_Chunk - > GetNeighborChunk ( a_BlockX , a_BlockZ - 2 ) , a_Chunk ) ;
RedstoneAddBlock ( a_BlockX , a_BlockY , a_BlockZ , a_Chunk - > GetNeighborChunk ( a_BlockX , a_BlockZ + 2 ) , a_Chunk ) ;
2014-02-15 10:51:49 -05:00
return ;
}
// Not on boundary, just alert this chunk for speed
AddBlock ( a_BlockX , a_BlockY , a_BlockZ , a_Chunk ) ;
}
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleRedstoneTorch ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , BLOCKTYPE a_MyState )
2014-02-07 16:59:08 -05:00
{
static const struct / / Define which directions the torch can power
{
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
2014-04-27 12:35:41 -04:00
int X = a_RelBlockX ; int Y = a_RelBlockY ; int Z = a_RelBlockZ ;
AddFaceDirection ( X , Y , Z , cBlockTorchHandler : : MetaDataToDirection ( m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ) , true ) ; // Inverse true to get the block torch is on
2014-02-07 16:59:08 -05:00
if ( AreCoordsDirectlyPowered ( X , Y , Z ) )
{
// There was a match, torch goes off
2014-04-27 12:35:41 -04:00
m_Chunk - > SetBlock ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , E_BLOCK_REDSTONE_TORCH_OFF , m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ) ;
2014-02-07 16:59:08 -05:00
return ;
}
// Torch still on, make all 4(X, Z) + 1(Y) sides powered
for ( size_t i = 0 ; i < ARRAYCOUNT ( gCrossCoords ) ; i + + )
{
2014-04-27 12:35:41 -04:00
BLOCKTYPE Type = 0 ;
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX + gCrossCoords [ i ] . x , a_RelBlockY + gCrossCoords [ i ] . y , a_RelBlockZ + gCrossCoords [ i ] . z , Type ) )
{
continue ;
}
2014-02-07 16:59:08 -05:00
if ( i + 1 < ARRAYCOUNT ( gCrossCoords ) ) // Sides of torch, not top (top is last)
{
if (
( ( IsMechanism ( Type ) ) | | ( Type = = E_BLOCK_REDSTONE_WIRE ) ) & & // Is it a mechanism or wire? Not block/other torch etc.
2014-04-27 12:35:41 -04:00
( ! Vector3i ( a_RelBlockX + gCrossCoords [ i ] . x , a_RelBlockY + gCrossCoords [ i ] . y , a_RelBlockZ + gCrossCoords [ i ] . z ) . Equals ( Vector3i ( X , Y , Z ) ) ) // CAN'T power block is that it is on
2014-02-07 16:59:08 -05:00
)
{
2014-04-27 12:35:41 -04:00
SetBlockPowered ( a_RelBlockX + gCrossCoords [ i ] . x , a_RelBlockY + gCrossCoords [ i ] . y , a_RelBlockZ + gCrossCoords [ i ] . z , a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
}
}
else
{
// Top side, power whatever is there, including blocks
2014-04-27 12:35:41 -04:00
SetBlockPowered ( a_RelBlockX + gCrossCoords [ i ] . x , a_RelBlockY + gCrossCoords [ i ] . y , a_RelBlockZ + gCrossCoords [ i ] . z , a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
// Power all blocks surrounding block above torch
2014-04-27 12:35:41 -04:00
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_YP ) ;
2014-02-07 16:59:08 -05:00
}
}
2014-04-27 12:35:41 -04:00
if ( m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ! = 0x5 ) // Is torch standing on ground? If NOT (i.e. on wall), power block beneath
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
BLOCKTYPE Type = m_Chunk - > GetBlock ( a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
if ( ( IsMechanism ( Type ) ) | | ( Type = = E_BLOCK_REDSTONE_WIRE ) ) // Still can't make a normal block powered though!
{
2014-04-27 12:35:41 -04:00
SetBlockPowered ( a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
}
}
}
else
{
// Check if the block the torch is on is powered
2014-04-27 12:35:41 -04:00
int X = a_RelBlockX ; int Y = a_RelBlockY ; int Z = a_RelBlockZ ;
AddFaceDirection ( X , Y , Z , cBlockTorchHandler : : MetaDataToDirection ( m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ) , true ) ; // Inverse true to get the block torch is on
2014-02-07 16:59:08 -05:00
// See if off state torch can be turned on again
if ( AreCoordsDirectlyPowered ( X , Y , Z ) )
{
return ; // Something matches, torch still powered
}
// Block torch on not powered, can be turned on again!
2014-04-27 12:35:41 -04:00
m_Chunk - > SetBlock ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , E_BLOCK_REDSTONE_TORCH_ON , m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ) ;
2014-02-07 16:59:08 -05:00
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleRedstoneBlock ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
SetAllDirsAsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
SetBlockPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ; // Set self as powered
2014-02-07 16:59:08 -05:00
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleRedstoneLever ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
2014-05-04 09:00:59 -04:00
NIBBLETYPE Meta = m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
if ( IsLeverOn ( Meta ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
SetAllDirsAsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-05-04 09:42:12 -04:00
2014-06-16 10:07:41 -04:00
eBlockFace Dir = cBlockLeverHandler : : BlockMetaDataToBlockFace ( Meta ) ;
2014-06-16 12:55:58 -04:00
Dir = ReverseBlockFace ( Dir ) ;
2014-05-04 09:42:12 -04:00
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , Dir ) ;
2014-02-07 16:59:08 -05:00
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleFenceGate ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-11 09:01:24 -05:00
{
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
2014-06-16 18:22:57 -04:00
NIBBLETYPE MetaData = m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-02-15 10:51:49 -05:00
2014-04-27 12:35:41 -04:00
if ( AreCoordsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) )
2014-02-11 09:01:24 -05:00
{
2014-04-27 12:35:41 -04:00
if ( ! AreCoordsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , true ) )
2014-02-11 09:01:24 -05:00
{
2014-06-17 13:47:32 -04:00
if ( ( MetaData & 0x4 ) = = 0 )
{
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , MetaData | 0x4 ) ;
m_Chunk - > BroadcastSoundParticleEffect ( 1003 , BlockX , a_RelBlockY , BlockZ , 0 ) ;
}
2014-04-27 12:35:41 -04:00
SetPlayerToggleableBlockAsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , true ) ;
2014-02-15 10:51:49 -05:00
}
2014-02-11 09:01:24 -05:00
}
else
{
2014-04-27 12:35:41 -04:00
if ( ! AreCoordsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , false ) )
2014-02-11 09:01:24 -05:00
{
2014-06-17 13:47:32 -04:00
if ( ( MetaData & 0x4 ) ! = 0 )
{
2014-06-22 11:29:02 -04:00
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , MetaData & ~ 0x04 ) ;
2014-06-17 13:47:32 -04:00
m_Chunk - > BroadcastSoundParticleEffect ( 1003 , BlockX , a_RelBlockY , BlockZ , 0 ) ;
}
2014-04-27 12:35:41 -04:00
SetPlayerToggleableBlockAsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , false ) ;
2014-02-11 09:01:24 -05:00
}
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleRedstoneButton ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
2014-05-04 09:00:59 -04:00
NIBBLETYPE Meta = m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
if ( IsButtonOn ( Meta ) )
2014-02-07 16:59:08 -05:00
{
2014-05-05 10:43:45 -04:00
SetAllDirsAsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-06-16 10:07:41 -04:00
eBlockFace Dir = cBlockButtonHandler : : BlockMetaDataToBlockFace ( Meta ) ;
2014-06-16 13:06:09 -04:00
Dir = ReverseBlockFace ( Dir ) ;
2014-05-04 09:42:12 -04:00
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , Dir ) ;
2014-02-07 16:59:08 -05:00
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleRedstoneWire ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
static const struct / / Define which directions the wire can receive power from
{
int x , y , z ;
} gCrossCoords [ ] =
{
{ 1 , 0 , 0 } , /* Wires on same level start */
{ - 1 , 0 , 0 } ,
{ 0 , 0 , 1 } ,
{ 0 , 0 , - 1 } , /* Wires on same level stop */
{ 1 , 1 , 0 } , /* Wires one higher, surrounding self start */
{ - 1 , 1 , 0 } ,
{ 0 , 1 , 1 } ,
{ 0 , 1 , - 1 } , /* Wires one higher, surrounding self stop */
{ 1 , - 1 , 0 } , /* Wires one lower, surrounding self start */
{ - 1 , - 1 , 0 } ,
{ 0 , - 1 , 1 } ,
{ 0 , - 1 , - 1 } , /* Wires one lower, surrounding self stop */
} ;
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 } ,
} ;
// Check to see if directly beside a power source
2014-04-15 08:15:56 -04:00
unsigned char MyPower ;
2014-04-27 12:35:41 -04:00
if ( ! IsWirePowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , 0 ) ;
m_World . WakeUpSimulators ( BlockX , a_RelBlockY , BlockZ ) ;
2014-04-15 08:15:56 -04:00
return ;
2014-02-07 16:59:08 -05:00
}
2014-04-15 08:15:56 -04:00
2014-04-27 12:35:41 -04:00
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) ;
2014-04-15 08:15:56 -04:00
2014-04-17 07:11:31 -04:00
if ( MyPower < 1 )
2014-02-07 16:59:08 -05:00
{
2014-04-15 08:15:56 -04:00
return ;
}
MyPower - - ;
2014-02-07 16:59:08 -05:00
2014-04-15 08:15:56 -04:00
for ( size_t i = 0 ; i < ARRAYCOUNT ( gCrossCoords ) ; i + + ) // Loop through all directions to transfer or receive power
{
if ( ( i > = 4 ) & & ( i < = 7 ) ) // If we are currently checking for wire surrounding ourself one block above...
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
BLOCKTYPE Type = 0 ;
if ( a_RelBlockY + 1 > = cChunkDef : : Height )
{
continue ;
}
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX , a_RelBlockY + 1 , a_RelBlockZ , Type ) )
{
continue ;
}
if ( cBlockInfo : : IsSolid ( Type ) ) // If there is something solid above us (wire cut off)...
2014-02-07 16:59:08 -05:00
{
2014-04-15 08:15:56 -04:00
continue ; // We don't receive power from that wire
2014-02-07 16:59:08 -05:00
}
2014-04-15 08:15:56 -04:00
}
else if ( ( i > = 8 ) & & ( i < = 11 ) ) // See above, but this is for wire below us
{
2014-04-27 12:35:41 -04:00
BLOCKTYPE Type = 0 ;
2014-05-06 18:05:14 -04:00
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX + gCrossCoords [ i ] . x , a_RelBlockY , a_RelBlockZ + gCrossCoords [ i ] . z , Type ) )
2014-04-27 12:35:41 -04:00
{
continue ;
}
if ( cBlockInfo : : IsSolid ( Type ) )
2014-02-07 16:59:08 -05:00
{
2014-04-15 08:15:56 -04:00
continue ;
2014-02-07 16:59:08 -05:00
}
}
2014-04-27 12:35:41 -04:00
BLOCKTYPE Type = 0 ;
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX + gCrossCoords [ i ] . x , a_RelBlockY + gCrossCoords [ i ] . y , a_RelBlockZ + gCrossCoords [ i ] . z , Type ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
continue ;
}
if ( Type = = E_BLOCK_REDSTONE_WIRE )
{
SetBlockPowered ( a_RelBlockX + gCrossCoords [ i ] . x , a_RelBlockY + gCrossCoords [ i ] . y , a_RelBlockZ + gCrossCoords [ i ] . z , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) ;
2014-02-07 16:59:08 -05:00
}
}
2014-04-15 08:15:56 -04:00
for ( size_t i = 0 ; i < ARRAYCOUNT ( gSideCoords ) ; i + + ) // Look for repeaters immediately surrounding self and try to power them
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
BLOCKTYPE Type = 0 ;
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX + gSideCoords [ i ] . x , a_RelBlockY + gSideCoords [ i ] . y , a_RelBlockZ + gSideCoords [ i ] . z , Type ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
continue ;
}
if ( Type = = E_BLOCK_REDSTONE_REPEATER_OFF )
{
SetBlockPowered ( a_RelBlockX + gSideCoords [ i ] . x , a_RelBlockY + gSideCoords [ i ] . y , a_RelBlockZ + gSideCoords [ i ] . z , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) ;
2014-02-07 16:59:08 -05:00
}
2014-04-15 08:15:56 -04:00
}
2014-02-07 16:59:08 -05:00
2014-04-15 08:15:56 -04:00
// Wire still powered, power blocks beneath
2014-04-27 12:35:41 -04:00
SetBlockPowered ( a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) ;
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_YM , MyPower ) ;
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
switch ( GetWireDirection ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) )
2014-04-15 08:15:56 -04:00
{
case REDSTONE_NONE :
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
SetBlockPowered ( a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) ;
SetBlockPowered ( a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) ;
SetBlockPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) ;
SetBlockPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) ;
2014-04-15 08:15:56 -04:00
2014-04-27 12:35:41 -04:00
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_XM , MyPower ) ;
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_XP , MyPower ) ;
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_ZM , MyPower ) ;
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_ZP , MyPower ) ;
2014-04-15 08:15:56 -04:00
break ;
}
case REDSTONE_X_POS :
{
2014-04-27 12:35:41 -04:00
SetBlockPowered ( a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) ;
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_XP , MyPower ) ;
2014-04-15 08:15:56 -04:00
break ;
}
case REDSTONE_X_NEG :
{
2014-04-27 12:35:41 -04:00
SetBlockPowered ( a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) ;
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_XM , MyPower ) ;
2014-04-15 08:15:56 -04:00
break ;
}
case REDSTONE_Z_POS :
{
2014-04-27 12:35:41 -04:00
SetBlockPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) ;
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_ZP , MyPower ) ;
2014-04-15 08:15:56 -04:00
break ;
}
case REDSTONE_Z_NEG :
{
2014-04-27 12:35:41 -04:00
SetBlockPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MyPower ) ;
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_ZM , MyPower ) ;
2014-04-15 08:15:56 -04:00
break ;
2014-02-07 16:59:08 -05:00
}
}
}
2014-06-16 10:07:41 -04:00
void cIncrementalRedstoneSimulator : : HandleRedstoneRepeater ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , BLOCKTYPE a_MyState )
2014-02-07 16:59:08 -05:00
{
2014-04-08 13:49:53 -04:00
/* Repeater Orientation Mini Guide:
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
| Z Axis
V
X Axis - - - - >
2014-04-27 12:35:41 -04:00
Repeater directions , values from a cWorld : : GetBlockMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) lookup :
2014-04-08 13:49:53 -04:00
East ( Right ) ( X + ) : 0x1
West ( Left ) ( X - ) : 0x3
North ( Up ) ( Z - ) : 0x2
South ( Down ) ( Z + ) : 0x0
// TODO: Add E_META_XXX enum entries for all meta values and update project with them
Sun rises from East ( X + )
*/
2014-04-07 12:37:53 -04:00
// Create a variable holding my meta to avoid multiple lookups.
2014-04-27 12:35:41 -04:00
NIBBLETYPE a_Meta = m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-04-08 13:49:53 -04:00
bool IsOn = ( a_MyState = = E_BLOCK_REDSTONE_REPEATER_ON ) ;
2014-06-06 18:23:28 -04:00
2014-04-27 12:35:41 -04:00
if ( ! IsRepeaterLocked ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , a_Meta ) ) // If we're locked, change nothing. Otherwise:
2014-04-08 13:49:53 -04:00
{
2014-04-27 12:35:41 -04:00
bool IsSelfPowered = IsRepeaterPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , a_Meta ) ;
2014-04-07 13:26:23 -04:00
if ( IsSelfPowered & & ! IsOn ) // Queue a power change if powered, but not on and not locked.
2014-04-07 12:55:17 -04:00
{
2014-06-16 10:07:41 -04:00
QueueRepeaterPowerChange ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , a_Meta , true ) ;
2014-04-07 12:55:17 -04:00
}
2014-04-07 13:26:23 -04:00
else if ( ! IsSelfPowered & & IsOn ) // Queue a power change if unpowered, on, and not locked.
2014-04-07 12:55:17 -04:00
{
2014-06-16 10:07:41 -04:00
QueueRepeaterPowerChange ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , a_Meta , false ) ;
2014-04-07 12:55:17 -04:00
}
2014-02-07 16:59:08 -05:00
}
2014-06-16 10:07:41 -04:00
}
2014-04-07 13:00:38 -04:00
2014-06-16 10:07:41 -04:00
void cIncrementalRedstoneSimulator : : HandleRedstoneRepeaterDelays ( )
{
2014-06-22 09:15:41 -04:00
for ( RepeatersDelayList : : iterator itr = m_RepeatersDelayList - > begin ( ) ; itr ! = m_RepeatersDelayList - > end ( ) ; )
2014-02-07 16:59:08 -05:00
{
2014-06-16 10:07:41 -04:00
if ( itr - > a_ElapsedTicks > = itr - > a_DelayTicks ) // Has the elapsed ticks reached the target ticks?
2014-02-07 16:59:08 -05:00
{
2014-06-16 10:07:41 -04:00
int RelBlockX = itr - > a_RelBlockPos . x ;
int RelBlockY = itr - > a_RelBlockPos . y ;
int RelBlockZ = itr - > a_RelBlockPos . z ;
NIBBLETYPE Meta = m_Chunk - > GetMeta ( RelBlockX , RelBlockY , RelBlockZ ) ;
if ( itr - > ShouldPowerOn )
2014-02-07 16:59:08 -05:00
{
2014-06-16 10:07:41 -04:00
m_Chunk - > SetBlock ( itr - > a_RelBlockPos , E_BLOCK_REDSTONE_REPEATER_ON , Meta ) ; // For performance
2014-06-06 18:23:28 -04:00
2014-06-16 10:07:41 -04:00
switch ( Meta & 0x3 ) // We only want the direction (bottom) bits
2014-06-06 18:23:28 -04:00
{
2014-06-16 10:07:41 -04:00
case 0x0 :
{
SetBlockPowered ( RelBlockX , RelBlockY , RelBlockZ - 1 , RelBlockX , RelBlockY , RelBlockZ ) ;
SetDirectionLinkedPowered ( RelBlockX , RelBlockY , RelBlockZ , BLOCK_FACE_ZM ) ;
break ;
}
case 0x1 :
{
SetBlockPowered ( RelBlockX + 1 , RelBlockY , RelBlockZ , RelBlockX , RelBlockY , RelBlockZ ) ;
SetDirectionLinkedPowered ( RelBlockX , RelBlockY , RelBlockZ , BLOCK_FACE_XP ) ;
break ;
}
case 0x2 :
{
SetBlockPowered ( RelBlockX , RelBlockY , RelBlockZ + 1 , RelBlockX , RelBlockY , RelBlockZ ) ;
SetDirectionLinkedPowered ( RelBlockX , RelBlockY , RelBlockZ , BLOCK_FACE_ZP ) ;
break ;
}
case 0x3 :
{
SetBlockPowered ( RelBlockX - 1 , RelBlockY , RelBlockZ , RelBlockX , RelBlockY , RelBlockZ ) ;
SetDirectionLinkedPowered ( RelBlockX , RelBlockY , RelBlockZ , BLOCK_FACE_XM ) ;
break ;
}
2014-02-07 16:59:08 -05:00
}
}
2014-06-16 10:07:41 -04:00
else
{
m_Chunk - > SetBlock ( RelBlockX , RelBlockY , RelBlockZ , E_BLOCK_REDSTONE_REPEATER_OFF , Meta ) ;
}
2014-06-22 09:15:41 -04:00
itr = m_RepeatersDelayList - > erase ( itr ) ;
2014-02-07 16:59:08 -05:00
}
else
{
2014-06-16 10:07:41 -04:00
// 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_RelBlockPos . x , itr - > a_RelBlockPos . y , itr - > a_RelBlockPos . z , itr - > a_ElapsedTicks , itr - > a_DelayTicks ) ;
itr - > a_ElapsedTicks + + ;
2014-06-22 09:15:41 -04:00
itr + + ;
2014-02-07 16:59:08 -05:00
}
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandlePiston ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
if ( IsPistonPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) & 0x7 ) ) // We only want the bottom three bits (4th controls extended-ness)
2014-02-07 16:59:08 -05:00
{
2014-05-25 08:46:34 -04:00
cBlockPistonHandler : : ExtendPiston ( BlockX , a_RelBlockY , BlockZ , & m_World ) ;
2014-02-07 16:59:08 -05:00
}
else
{
2014-05-25 08:46:34 -04:00
cBlockPistonHandler : : RetractPiston ( BlockX , a_RelBlockY , BlockZ , & m_World ) ;
2014-02-07 16:59:08 -05:00
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleDropSpenser ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
class cSetPowerToDropSpenser :
public cDropSpenserCallback
{
bool m_IsPowered ;
public :
cSetPowerToDropSpenser ( bool a_IsPowered ) : m_IsPowered ( a_IsPowered ) { }
virtual bool Item ( cDropSpenserEntity * a_DropSpenser ) override
{
a_DropSpenser - > SetRedstonePower ( m_IsPowered ) ;
return false ;
}
2014-04-27 12:35:41 -04:00
} DrSpSP ( AreCoordsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ) ;
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
m_Chunk - > DoWithDropSpenserAt ( BlockX , a_RelBlockY , BlockZ , DrSpSP ) ;
2014-02-07 16:59:08 -05:00
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleRedstoneLamp ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , BLOCKTYPE a_MyState )
2014-02-07 16:59:08 -05:00
{
if ( a_MyState = = E_BLOCK_REDSTONE_LAMP_OFF )
{
2014-04-27 12:35:41 -04:00
if ( AreCoordsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
m_Chunk - > SetBlock ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , E_BLOCK_REDSTONE_LAMP_ON , 0 ) ;
2014-02-07 16:59:08 -05:00
}
}
else
{
2014-04-27 12:35:41 -04:00
if ( ! AreCoordsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
m_Chunk - > SetBlock ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , E_BLOCK_REDSTONE_LAMP_OFF , 0 ) ;
2014-02-07 16:59:08 -05:00
}
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleTNT ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
if ( AreCoordsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
m_Chunk - > BroadcastSoundEffect ( " game.tnt.primed " , BlockX * 8 , a_RelBlockY * 8 , BlockZ * 8 , 0.5f , 0.6f ) ;
m_Chunk - > SetBlock ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , E_BLOCK_AIR , 0 ) ;
m_World . SpawnPrimedTNT ( BlockX + 0.5 , a_RelBlockY + 0.5 , BlockZ + 0.5 ) ; // 80 ticks to boom
2014-02-07 16:59:08 -05:00
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleDoor ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
if ( AreCoordsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( ! AreCoordsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , true ) )
2014-02-07 16:59:08 -05:00
{
cChunkInterface ChunkInterface ( m_World . GetChunkMap ( ) ) ;
2014-05-29 13:21:56 -04:00
if ( ! cBlockDoorHandler : : IsOpen ( ChunkInterface , BlockX , a_RelBlockY , BlockZ ) )
{
cBlockDoorHandler : : SetOpen ( ChunkInterface , BlockX , a_RelBlockY , BlockZ , true ) ;
m_Chunk - > BroadcastSoundParticleEffect ( 1003 , BlockX , a_RelBlockY , BlockZ , 0 ) ;
}
2014-04-27 12:35:41 -04:00
SetPlayerToggleableBlockAsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , true ) ;
2014-02-07 16:59:08 -05:00
}
}
else
{
2014-04-27 12:35:41 -04:00
if ( ! AreCoordsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , false ) )
2014-02-07 16:59:08 -05:00
{
cChunkInterface ChunkInterface ( m_World . GetChunkMap ( ) ) ;
2014-05-29 13:21:56 -04:00
if ( cBlockDoorHandler : : IsOpen ( ChunkInterface , BlockX , a_RelBlockY , BlockZ ) )
{
cBlockDoorHandler : : SetOpen ( ChunkInterface , BlockX , a_RelBlockY , BlockZ , false ) ;
m_Chunk - > BroadcastSoundParticleEffect ( 1003 , BlockX , a_RelBlockY , BlockZ , 0 ) ;
}
2014-04-27 12:35:41 -04:00
SetPlayerToggleableBlockAsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , false ) ;
2014-02-07 16:59:08 -05:00
}
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleCommandBlock ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
class cSetPowerToCommandBlock :
public cCommandBlockCallback
{
bool m_IsPowered ;
public :
cSetPowerToCommandBlock ( bool a_IsPowered ) : m_IsPowered ( a_IsPowered ) { }
virtual bool Item ( cCommandBlockEntity * a_CommandBlock ) override
{
a_CommandBlock - > SetRedstonePower ( m_IsPowered ) ;
return false ;
}
2014-04-27 12:35:41 -04:00
} CmdBlockSP ( AreCoordsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ) ;
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
m_Chunk - > DoWithCommandBlockAt ( BlockX , a_RelBlockY , BlockZ , CmdBlockSP ) ;
2014-02-07 16:59:08 -05:00
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleRail ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , BLOCKTYPE a_MyType )
2014-02-07 16:59:08 -05:00
{
switch ( a_MyType )
{
case E_BLOCK_DETECTOR_RAIL :
{
2014-04-27 12:35:41 -04:00
if ( ( m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) & 0x08 ) = = 0x08 )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
SetAllDirsAsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , a_MyType ) ;
2014-02-07 16:59:08 -05:00
}
break ;
}
case E_BLOCK_ACTIVATOR_RAIL :
case E_BLOCK_POWERED_RAIL :
{
2014-04-27 12:35:41 -04:00
if ( AreCoordsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) | 0x08 ) ;
2014-02-07 16:59:08 -05:00
}
else
{
2014-04-27 12:35:41 -04:00
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) & 0x07 ) ;
2014-02-07 16:59:08 -05:00
}
break ;
}
default : LOGD ( " Unhandled type of rail in %s " , __FUNCTION__ ) ;
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleTrapdoor ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
if ( AreCoordsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( ! AreCoordsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , true ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
m_World . SetTrapdoorOpen ( BlockX , a_RelBlockY , BlockZ , true ) ;
SetPlayerToggleableBlockAsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , true ) ;
2014-03-02 10:01:37 -05:00
}
2014-02-07 16:59:08 -05:00
}
else
{
2014-04-27 12:35:41 -04:00
if ( ! AreCoordsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , false ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
m_World . SetTrapdoorOpen ( BlockX , a_RelBlockY , BlockZ , false ) ;
SetPlayerToggleableBlockAsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , false ) ;
2014-02-07 16:59:08 -05:00
}
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleNoteBlock ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
bool m_bAreCoordsPowered = AreCoordsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
if ( m_bAreCoordsPowered )
{
2014-04-27 12:35:41 -04:00
if ( ! AreCoordsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , true ) )
2014-02-07 16:59:08 -05:00
{
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 ) ;
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
m_Chunk - > DoWithNoteBlockAt ( BlockX , a_RelBlockY , BlockZ , NoteBlockSP ) ;
SetPlayerToggleableBlockAsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , true ) ;
2014-02-07 16:59:08 -05:00
}
}
else
{
2014-04-27 12:35:41 -04:00
if ( ! AreCoordsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , false ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
SetPlayerToggleableBlockAsSimulated ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , false ) ;
2014-02-07 16:59:08 -05:00
}
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandleDaylightSensor ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
2014-06-22 10:04:23 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX , BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
int ChunkX , ChunkZ ;
cChunkDef : : BlockToChunk ( BlockX , BlockZ , ChunkX , ChunkZ ) ;
2014-02-07 16:59:08 -05:00
2014-06-22 10:04:23 -04:00
if ( ! m_World . IsChunkLighted ( ChunkX , ChunkZ ) )
2014-02-07 16:59:08 -05:00
{
2014-06-22 10:04:23 -04:00
m_World . QueueLightChunk ( ChunkX , ChunkZ ) ;
2014-02-07 16:59:08 -05:00
}
else
{
2014-06-22 10:04:23 -04:00
if ( m_Chunk - > GetTimeAlteredLight ( m_World . GetBlockSkyLight ( BlockX , a_RelBlockY + 1 , BlockZ ) ) > 8 )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
SetAllDirsAsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
}
2014-06-16 10:12:50 -04:00
else
{
WakeUp ( BlockX , a_RelBlockY , BlockZ , m_Chunk ) ;
}
2014-02-07 16:59:08 -05:00
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : HandlePressurePlate ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , BLOCKTYPE a_MyType )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
2014-02-07 16:59:08 -05:00
switch ( a_MyType )
{
case E_BLOCK_STONE_PRESSURE_PLATE :
{
// MCS feature - stone pressure plates can only be triggered by players :D
2014-06-28 15:44:34 -04:00
cPlayer * a_Player = m_World . FindClosestPlayer ( Vector3f ( BlockX + 0.5f , ( float ) a_RelBlockY , BlockZ + 0.5f ) , 0.5f , false ) ;
2014-02-07 16:59:08 -05:00
if ( a_Player ! = NULL )
{
2014-04-27 12:35:41 -04:00
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , 0x1 ) ;
SetAllDirsAsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-05-04 09:15:10 -04:00
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_YM , a_MyType ) ;
2014-02-07 16:59:08 -05:00
}
else
{
2014-04-27 12:35:41 -04:00
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , 0x0 ) ;
2014-06-28 15:44:34 -04:00
WAKE_SIMULATOR_IF_DIRTY ( m_Chunk , BlockX , a_RelBlockY , BlockZ ) ;
2014-02-07 16:59:08 -05:00
}
break ;
}
2014-02-20 13:07:32 -05:00
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE :
2014-04-17 07:11:31 -04:00
{
class cPressurePlateCallback :
public cEntityCallback
{
public :
cPressurePlateCallback ( int a_BlockX , int a_BlockY , int a_BlockZ ) :
m_NumberOfEntities ( 0 ) ,
m_X ( a_BlockX ) ,
m_Y ( a_BlockY ) ,
m_Z ( a_BlockZ )
{
}
virtual bool Item ( cEntity * a_Entity ) override
{
Vector3f EntityPos = a_Entity - > GetPosition ( ) ;
Vector3f BlockPos ( m_X + 0.5f , ( float ) m_Y , m_Z + 0.5f ) ;
double Distance = ( EntityPos - BlockPos ) . Length ( ) ;
2014-06-28 15:44:34 -04:00
if ( Distance < = 0.5 )
2014-04-17 07:11:31 -04:00
{
m_NumberOfEntities + + ;
}
return false ;
}
bool GetPowerLevel ( unsigned char & a_PowerLevel ) const
{
a_PowerLevel = std : : min ( m_NumberOfEntities , MAX_POWER_LEVEL ) ;
return ( a_PowerLevel > 0 ) ;
}
protected :
int m_NumberOfEntities ;
int m_X ;
int m_Y ;
int m_Z ;
} ;
2014-04-27 12:35:41 -04:00
cPressurePlateCallback PressurePlateCallback ( BlockX , a_RelBlockY , BlockZ ) ;
2014-06-28 15:44:34 -04:00
m_World . ForEachEntityInChunk ( m_Chunk - > GetPosX ( ) , m_Chunk - > GetPosZ ( ) , PressurePlateCallback ) ;
2014-04-17 07:11:31 -04:00
unsigned char Power ;
2014-04-27 12:35:41 -04:00
NIBBLETYPE Meta = m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-04-17 07:11:31 -04:00
if ( PressurePlateCallback . GetPowerLevel ( Power ) )
{
if ( Meta = = E_META_PRESSURE_PLATE_RAISED )
{
2014-04-27 12:35:41 -04:00
m_Chunk - > BroadcastSoundEffect ( " random.click " , ( int ) ( ( BlockX + 0.5 ) * 8.0 ) , ( int ) ( ( a_RelBlockY + 0.1 ) * 8.0 ) , ( int ) ( ( BlockZ + 0.5 ) * 8.0 ) , 0.3F , 0.5F ) ;
2014-04-17 07:11:31 -04:00
}
2014-04-27 12:35:41 -04:00
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , E_META_PRESSURE_PLATE_DEPRESSED ) ;
SetAllDirsAsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , Power ) ;
2014-05-04 09:15:10 -04:00
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_YM , a_MyType ) ;
2014-04-17 07:11:31 -04:00
}
else
{
if ( Meta = = E_META_PRESSURE_PLATE_DEPRESSED )
{
2014-04-27 12:35:41 -04:00
m_Chunk - > BroadcastSoundEffect ( " random.click " , ( int ) ( ( BlockX + 0.5 ) * 8.0 ) , ( int ) ( ( a_RelBlockY + 0.1 ) * 8.0 ) , ( int ) ( ( BlockZ + 0.5 ) * 8.0 ) , 0.3F , 0.6F ) ;
2014-04-17 07:11:31 -04:00
}
2014-04-27 12:35:41 -04:00
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , E_META_PRESSURE_PLATE_RAISED ) ;
2014-06-28 15:44:34 -04:00
WAKE_SIMULATOR_IF_DIRTY ( m_Chunk , BlockX , a_RelBlockY , BlockZ ) ;
2014-04-17 07:11:31 -04:00
}
break ;
}
2014-02-20 13:07:32 -05:00
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE :
2014-04-17 07:11:31 -04:00
{
2014-04-27 12:35:41 -04:00
class cPressurePlateCallback :
public cEntityCallback
2014-04-17 07:11:31 -04:00
{
2014-04-27 12:35:41 -04:00
public :
cPressurePlateCallback ( int a_BlockX , int a_BlockY , int a_BlockZ ) :
m_NumberOfEntities ( 0 ) ,
m_X ( a_BlockX ) ,
m_Y ( a_BlockY ) ,
m_Z ( a_BlockZ )
{
}
2014-04-17 07:11:31 -04:00
2014-04-27 12:35:41 -04:00
virtual bool Item ( cEntity * a_Entity ) override
2014-04-17 07:11:31 -04:00
{
2014-04-27 12:35:41 -04:00
Vector3f EntityPos = a_Entity - > GetPosition ( ) ;
Vector3f BlockPos ( m_X + 0.5f , ( float ) m_Y , m_Z + 0.5f ) ;
double Distance = ( EntityPos - BlockPos ) . Length ( ) ;
2014-06-28 15:44:34 -04:00
if ( Distance < = 0.5 )
2014-04-27 12:35:41 -04:00
{
m_NumberOfEntities + + ;
}
return false ;
2014-04-17 07:11:31 -04:00
}
2014-04-27 12:35:41 -04:00
bool GetPowerLevel ( unsigned char & a_PowerLevel ) const
{
2014-06-28 15:44:34 -04:00
a_PowerLevel = std : : min ( ( int ) ceil ( m_NumberOfEntities / 10.f ) , MAX_POWER_LEVEL ) ;
2014-04-27 12:35:41 -04:00
return ( a_PowerLevel > 0 ) ;
}
2014-04-17 07:11:31 -04:00
2014-04-27 12:35:41 -04:00
protected :
int m_NumberOfEntities ;
2014-04-17 07:11:31 -04:00
2014-04-27 12:35:41 -04:00
int m_X ;
int m_Y ;
int m_Z ;
} ;
2014-04-17 07:11:31 -04:00
2014-04-27 12:35:41 -04:00
cPressurePlateCallback PressurePlateCallback ( BlockX , a_RelBlockY , BlockZ ) ;
2014-06-28 15:44:34 -04:00
m_World . ForEachEntityInChunk ( m_Chunk - > GetPosX ( ) , m_Chunk - > GetPosZ ( ) , PressurePlateCallback ) ;
2014-04-17 07:11:31 -04:00
2014-04-27 12:35:41 -04:00
unsigned char Power ;
NIBBLETYPE Meta = m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
if ( PressurePlateCallback . GetPowerLevel ( Power ) )
2014-04-17 07:11:31 -04:00
{
2014-04-27 12:35:41 -04:00
if ( Meta = = E_META_PRESSURE_PLATE_RAISED )
{
m_Chunk - > BroadcastSoundEffect ( " random.click " , ( int ) ( ( BlockX + 0.5 ) * 8.0 ) , ( int ) ( ( a_RelBlockY + 0.1 ) * 8.0 ) , ( int ) ( ( BlockZ + 0.5 ) * 8.0 ) , 0.3F , 0.5F ) ;
}
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , E_META_PRESSURE_PLATE_DEPRESSED ) ;
SetAllDirsAsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , Power ) ;
2014-05-04 09:15:10 -04:00
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_YM , a_MyType ) ;
2014-04-17 07:11:31 -04:00
}
2014-04-27 12:35:41 -04:00
else
2014-04-17 07:11:31 -04:00
{
2014-04-27 12:35:41 -04:00
if ( Meta = = E_META_PRESSURE_PLATE_DEPRESSED )
{
m_Chunk - > BroadcastSoundEffect ( " random.click " , ( int ) ( ( BlockX + 0.5 ) * 8.0 ) , ( int ) ( ( a_RelBlockY + 0.1 ) * 8.0 ) , ( int ) ( ( BlockZ + 0.5 ) * 8.0 ) , 0.3F , 0.6F ) ;
}
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , E_META_PRESSURE_PLATE_RAISED ) ;
2014-06-28 15:44:34 -04:00
WAKE_SIMULATOR_IF_DIRTY ( m_Chunk , BlockX , a_RelBlockY , BlockZ ) ;
2014-04-17 07:11:31 -04:00
}
break ;
}
2014-02-07 16:59:08 -05:00
case E_BLOCK_WOODEN_PRESSURE_PLATE :
{
2014-02-20 13:07:32 -05:00
class cPressurePlateCallback :
2014-02-07 16:59:08 -05:00
public cEntityCallback
{
public :
2014-04-17 07:11:31 -04:00
cPressurePlateCallback ( int a_BlockX , int a_BlockY , int a_BlockZ ) :
2014-05-04 09:42:12 -04:00
m_FoundEntity ( false ) ,
2014-02-07 16:59:08 -05:00
m_X ( a_BlockX ) ,
m_Y ( a_BlockY ) ,
m_Z ( a_BlockZ )
{
}
virtual bool Item ( cEntity * a_Entity ) override
{
Vector3f EntityPos = a_Entity - > GetPosition ( ) ;
Vector3f BlockPos ( m_X + 0.5f , ( float ) m_Y , m_Z + 0.5f ) ;
2014-03-16 17:00:28 -04:00
double Distance = ( EntityPos - BlockPos ) . Length ( ) ;
2014-02-07 16:59:08 -05:00
2014-06-28 15:44:34 -04:00
if ( Distance < = 0.5 )
2014-02-07 16:59:08 -05:00
{
2014-04-17 07:11:31 -04:00
m_FoundEntity = true ;
2014-02-20 13:07:32 -05:00
return true ; // Break out, we only need to know for plates that at least one entity is on top
2014-02-07 16:59:08 -05:00
}
return false ;
}
bool FoundEntity ( void ) const
{
2014-04-17 07:11:31 -04:00
return m_FoundEntity ;
2014-02-07 16:59:08 -05:00
}
protected :
2014-04-17 07:11:31 -04:00
bool m_FoundEntity ;
2014-02-07 16:59:08 -05:00
int m_X ;
int m_Y ;
int m_Z ;
} ;
2014-04-27 12:35:41 -04:00
cPressurePlateCallback PressurePlateCallback ( BlockX , a_RelBlockY , BlockZ ) ;
2014-06-28 15:44:34 -04:00
m_World . ForEachEntityInChunk ( m_Chunk - > GetPosX ( ) , m_Chunk - > GetPosZ ( ) , PressurePlateCallback ) ;
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
NIBBLETYPE Meta = m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-02-20 13:07:32 -05:00
if ( PressurePlateCallback . FoundEntity ( ) )
2014-02-07 16:59:08 -05:00
{
2014-04-17 07:11:31 -04:00
if ( Meta = = E_META_PRESSURE_PLATE_RAISED )
2014-02-20 13:21:04 -05:00
{
2014-04-27 12:35:41 -04:00
m_Chunk - > BroadcastSoundEffect ( " random.click " , ( int ) ( ( BlockX + 0.5 ) * 8.0 ) , ( int ) ( ( a_RelBlockY + 0.1 ) * 8.0 ) , ( int ) ( ( BlockZ + 0.5 ) * 8.0 ) , 0.3F , 0.5F ) ;
2014-02-20 13:21:04 -05:00
}
2014-04-27 12:35:41 -04:00
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , E_META_PRESSURE_PLATE_DEPRESSED ) ;
SetAllDirsAsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-05-04 09:15:10 -04:00
SetDirectionLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , BLOCK_FACE_YM , a_MyType ) ;
2014-02-07 16:59:08 -05:00
}
else
{
2014-04-17 07:11:31 -04:00
if ( Meta = = E_META_PRESSURE_PLATE_DEPRESSED )
2014-02-20 13:21:04 -05:00
{
2014-04-27 12:35:41 -04:00
m_Chunk - > BroadcastSoundEffect ( " random.click " , ( int ) ( ( BlockX + 0.5 ) * 8.0 ) , ( int ) ( ( a_RelBlockY + 0.1 ) * 8.0 ) , ( int ) ( ( BlockZ + 0.5 ) * 8.0 ) , 0.3F , 0.6F ) ;
2014-02-20 13:21:04 -05:00
}
2014-04-27 12:35:41 -04:00
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , E_META_PRESSURE_PLATE_RAISED ) ;
2014-06-28 15:44:34 -04:00
WAKE_SIMULATOR_IF_DIRTY ( m_Chunk , BlockX , a_RelBlockY , BlockZ ) ;
2014-02-07 16:59:08 -05:00
}
break ;
}
default :
2014-04-17 07:11:31 -04:00
{
2014-02-07 16:59:08 -05:00
LOGD ( " Unimplemented pressure plate type %s in cRedstoneSimulator " , ItemToFullString ( a_MyType ) . c_str ( ) ) ;
break ;
2014-04-17 07:11:31 -04:00
}
2014-02-07 16:59:08 -05:00
}
}
2014-06-28 15:44:34 -04:00
void cIncrementalRedstoneSimulator : : HandleTripwireHook ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
{
int BlockX = m_Chunk - > GetPosX ( ) * cChunkDef : : Width + a_RelBlockX ;
int BlockZ = m_Chunk - > GetPosZ ( ) * cChunkDef : : Width + a_RelBlockZ ;
int RelX = a_RelBlockX , RelZ = a_RelBlockZ ;
bool FoundActivated = false ;
eBlockFace FaceToGoTowards = cBlockTripwireHookHandler : : MetadataToDirection ( m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ) ;
for ( int i = 0 ; i < 40 ; + + i ) // Tripwires can be connected up to 40 blocks
{
BLOCKTYPE Type ;
NIBBLETYPE Meta ;
AddFaceDirection ( RelX , a_RelBlockY , RelZ , FaceToGoTowards ) ;
m_Chunk - > UnboundedRelGetBlock ( RelX , a_RelBlockY , RelZ , Type , Meta ) ;
if ( Type = = E_BLOCK_TRIPWIRE )
{
if ( Meta = = 0x1 )
{
FoundActivated = true ;
}
}
else if ( Type = = E_BLOCK_TRIPWIRE_HOOK )
{
if ( ReverseBlockFace ( cBlockTripwireHookHandler : : MetadataToDirection ( Meta ) ) = = FaceToGoTowards )
{
// Other hook not facing in opposite direction
break ;
}
else
{
// Tripwire hook not connected at all, AND away all the power state bits
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) & 0x3 ) ;
WAKE_SIMULATOR_IF_DIRTY ( m_Chunk , BlockX , a_RelBlockY , BlockZ ) ;
return ;
}
}
else
{
// Tripwire hook not connected at all, AND away all the power state bits
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) & 0x3 ) ;
WAKE_SIMULATOR_IF_DIRTY ( m_Chunk , BlockX , a_RelBlockY , BlockZ ) ;
return ;
}
}
if ( FoundActivated )
{
// Connected and activated, set the 3rd and 4th highest bits
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) | 0xC ) ;
SetAllDirsAsPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
}
else
{
// Connected but not activated, AND away the highest bit
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , ( m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) & 0x7 ) | 0x4 ) ;
WAKE_SIMULATOR_IF_DIRTY ( m_Chunk , BlockX , a_RelBlockY , BlockZ ) ;
}
}
void cIncrementalRedstoneSimulator : : HandleTripwire ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
{
int BlockX = m_Chunk - > GetPosX ( ) * cChunkDef : : Width + a_RelBlockX ;
int BlockZ = m_Chunk - > GetPosZ ( ) * cChunkDef : : Width + a_RelBlockZ ;
class cTripwireCallback :
public cEntityCallback
{
public :
cTripwireCallback ( int a_BlockX , int a_BlockY , int a_BlockZ ) :
m_FoundEntity ( false ) ,
m_X ( a_BlockX ) ,
m_Y ( a_BlockY ) ,
m_Z ( a_BlockZ )
{
}
virtual bool Item ( cEntity * a_Entity ) override
{
cBoundingBox bbWire ( m_X , m_X + 1 , m_Y , m_Y + 0.1 , m_Z , m_Z + 1 ) ;
cBoundingBox bbEntity ( a_Entity - > GetPosition ( ) , a_Entity - > GetWidth ( ) / 2 , a_Entity - > GetHeight ( ) ) ;
if ( bbEntity . DoesIntersect ( bbWire ) )
{
m_FoundEntity = true ;
return true ; // One entity is sufficient to trigger the wire
}
return false ;
}
bool FoundEntity ( void ) const
{
return m_FoundEntity ;
}
protected :
bool m_FoundEntity ;
int m_X ;
int m_Y ;
int m_Z ;
} ;
cTripwireCallback TripwireCallback ( BlockX , a_RelBlockY , BlockZ ) ;
m_World . ForEachEntityInChunk ( m_Chunk - > GetPosX ( ) , m_Chunk - > GetPosZ ( ) , TripwireCallback ) ;
if ( TripwireCallback . FoundEntity ( ) )
{
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , 0x1 ) ;
}
else
{
m_Chunk - > SetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , 0x0 ) ;
}
}
2014-04-27 12:35:41 -04:00
bool cIncrementalRedstoneSimulator : : AreCoordsDirectlyPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
PoweredBlocksList * Powered = m_Chunk - > GetNeighborChunk ( BlockX , BlockZ ) - > GetRedstoneSimulatorPoweredBlocksList ( ) ; // Torches want to access neighbour's data when on a wall
for ( PoweredBlocksList : : const_iterator itr = Powered - > begin ( ) ; itr ! = Powered - > end ( ) ; + + itr ) // Check powered list
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( itr - > a_BlockPos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) ) )
2014-02-07 16:59:08 -05:00
{
return true ;
}
}
return false ;
}
2014-04-27 12:35:41 -04:00
bool cIncrementalRedstoneSimulator : : AreCoordsLinkedPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
2014-02-15 10:51:49 -05:00
for ( LinkedBlocksList : : const_iterator itr = m_LinkedPoweredBlocks - > begin ( ) ; itr ! = m_LinkedPoweredBlocks - > end ( ) ; + + itr ) // Check linked powered list
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( itr - > a_BlockPos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) ) )
2014-02-07 16:59:08 -05:00
{
return true ;
}
}
return false ;
}
2014-06-14 05:47:10 -04:00
2014-04-27 12:35:41 -04:00
bool cIncrementalRedstoneSimulator : : IsRepeaterPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , NIBBLETYPE a_Meta )
2014-02-07 16:59:08 -05:00
{
// Repeaters cannot be powered by any face except their back; verify that this is true for a source
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
2014-02-07 16:59:08 -05:00
2014-02-15 10:51:49 -05:00
for ( PoweredBlocksList : : const_iterator itr = m_PoweredBlocks - > begin ( ) ; itr ! = m_PoweredBlocks - > end ( ) ; + + itr )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( ! itr - > a_BlockPos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) ) ) { continue ; }
2014-02-07 16:59:08 -05:00
2014-04-07 12:37:53 -04:00
switch ( a_Meta & 0x3 )
2014-02-07 16:59:08 -05:00
{
case 0x0 :
{
// Flip the coords to check the back of the repeater
2014-04-27 12:35:41 -04:00
if ( itr - > a_SourcePos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ + 1 ) ) ) { return true ; }
2014-02-07 16:59:08 -05:00
break ;
}
case 0x1 :
{
2014-04-27 12:35:41 -04:00
if ( itr - > a_SourcePos . Equals ( Vector3i ( BlockX - 1 , a_RelBlockY , BlockZ ) ) ) { return true ; }
2014-02-07 16:59:08 -05:00
break ;
}
case 0x2 :
{
2014-04-27 12:35:41 -04:00
if ( itr - > a_SourcePos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ - 1 ) ) ) { return true ; }
2014-02-07 16:59:08 -05:00
break ;
}
case 0x3 :
{
2014-04-27 12:35:41 -04:00
if ( itr - > a_SourcePos . Equals ( Vector3i ( BlockX + 1 , a_RelBlockY , BlockZ ) ) ) { return true ; }
2014-02-07 16:59:08 -05:00
break ;
}
}
}
2014-02-15 10:51:49 -05:00
for ( LinkedBlocksList : : const_iterator itr = m_LinkedPoweredBlocks - > begin ( ) ; itr ! = m_LinkedPoweredBlocks - > end ( ) ; + + itr )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( ! itr - > a_BlockPos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) ) ) { continue ; }
2014-02-07 16:59:08 -05:00
2014-04-07 12:37:53 -04:00
switch ( a_Meta & 0x3 )
2014-02-07 16:59:08 -05:00
{
case 0x0 :
{
2014-04-27 12:35:41 -04:00
if ( itr - > a_MiddlePos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ + 1 ) ) ) { return true ; }
2014-02-07 16:59:08 -05:00
break ;
}
case 0x1 :
{
2014-04-27 12:35:41 -04:00
if ( itr - > a_MiddlePos . Equals ( Vector3i ( BlockX - 1 , a_RelBlockY , BlockZ ) ) ) { return true ; }
2014-02-07 16:59:08 -05:00
break ;
}
case 0x2 :
{
2014-04-27 12:35:41 -04:00
if ( itr - > a_MiddlePos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ - 1 ) ) ) { return true ; }
2014-02-07 16:59:08 -05:00
break ;
}
case 0x3 :
{
2014-04-27 12:35:41 -04:00
if ( itr - > a_MiddlePos . Equals ( Vector3i ( BlockX + 1 , a_RelBlockY , BlockZ ) ) ) { return true ; }
2014-02-07 16:59:08 -05:00
break ;
}
}
}
return false ; // Couldn't find power source behind repeater
}
2014-04-06 14:09:33 -04:00
2014-04-27 12:35:41 -04:00
bool cIncrementalRedstoneSimulator : : IsRepeaterLocked ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , NIBBLETYPE a_Meta )
2014-04-08 13:49:53 -04:00
{
switch ( a_Meta & 0x3 ) // We only want the 'direction' part of our metadata
2014-04-06 14:09:33 -04:00
{
2014-04-08 10:14:23 -04:00
// If the repeater is looking up or down (If parallel to the Z axis)
2014-04-08 09:48:24 -04:00
case 0x0 :
2014-04-07 12:37:53 -04:00
case 0x2 :
{
2014-06-14 05:47:10 -04:00
// Check if eastern(right) neighbor is a powered on repeater who is facing us
2014-04-27 12:35:41 -04:00
BLOCKTYPE Block = 0 ;
if ( m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ , Block ) & & ( Block = = E_BLOCK_REDSTONE_REPEATER_ON ) ) // Is right neighbor a powered repeater?
2014-04-08 09:48:24 -04:00
{
2014-04-27 12:35:41 -04:00
NIBBLETYPE OtherRepeaterDir = m_Chunk - > GetMeta ( a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ ) & 0x3 ;
2014-06-14 05:47:10 -04:00
if ( OtherRepeaterDir = = 0x3 ) { return true ; } // If so, I am latched/locked
2014-04-07 12:37:53 -04:00
}
2014-04-08 09:48:24 -04:00
2014-06-14 05:47:10 -04:00
// Check if western(left) neighbor is a powered on repeater who is facing us
2014-04-27 12:35:41 -04:00
if ( m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ , Block ) & & ( Block = = E_BLOCK_REDSTONE_REPEATER_ON ) )
2014-04-08 09:48:24 -04:00
{
2014-04-27 12:35:41 -04:00
NIBBLETYPE OtherRepeaterDir = m_Chunk - > GetMeta ( a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ ) & 0x3 ;
2014-06-14 05:47:10 -04:00
if ( OtherRepeaterDir = = 0x1 ) { return true ; } // If so, I am latched/locked
2014-04-07 12:37:53 -04:00
}
2014-04-08 09:48:24 -04:00
2014-04-07 12:12:06 -04:00
break ;
2014-04-07 12:37:53 -04:00
}
2014-04-08 09:48:24 -04:00
2014-04-08 10:14:23 -04:00
// If the repeater is looking left or right (If parallel to the x axis)
2014-04-07 12:12:06 -04:00
case 0x1 :
case 0x3 :
2014-04-07 12:37:53 -04:00
{
2014-06-14 05:47:10 -04:00
// Check if southern(down) neighbor is a powered on repeater who is facing us
2014-04-27 12:35:41 -04:00
BLOCKTYPE Block = 0 ;
if ( m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX , a_RelBlockY , a_RelBlockZ + 1 , Block ) & & ( Block = = E_BLOCK_REDSTONE_REPEATER_ON ) )
2014-04-07 12:37:53 -04:00
{
2014-04-27 12:35:41 -04:00
NIBBLETYPE OtherRepeaterDir = m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ + 1 ) & 0x3 ;
2014-06-14 05:47:10 -04:00
if ( OtherRepeaterDir = = 0x0 ) { return true ; } // If so, am latched/locked
2014-04-07 12:37:53 -04:00
}
2014-06-14 05:47:10 -04:00
// Check if northern(up) neighbor is a powered on repeater who is facing us
2014-04-27 12:35:41 -04:00
if ( m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX , a_RelBlockY , a_RelBlockZ - 1 , Block ) & & ( Block = = E_BLOCK_REDSTONE_REPEATER_ON ) )
2014-04-07 12:37:53 -04:00
{
2014-04-27 12:35:41 -04:00
NIBBLETYPE OtherRepeaterDir = m_Chunk - > GetMeta ( a_RelBlockX , a_RelBlockY , a_RelBlockZ - 1 ) & 0x3 ;
2014-06-14 05:47:10 -04:00
if ( OtherRepeaterDir = = 0x2 ) { return true ; } // If so, I am latched/locked
2014-04-07 12:37:53 -04:00
}
2014-04-07 12:12:06 -04:00
2014-04-07 12:37:53 -04:00
break ;
}
2014-04-06 14:09:33 -04:00
}
2014-06-14 05:47:10 -04:00
return false ; // None of the checks succeeded, I am not a locked repeater
2014-04-06 14:09:33 -04:00
}
2014-04-27 12:35:41 -04:00
bool cIncrementalRedstoneSimulator : : IsPistonPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , NIBBLETYPE a_Meta )
2014-02-07 16:59:08 -05:00
{
// Pistons cannot be powered through their front face; this function verifies that a source meets this requirement
2014-05-25 08:46:34 -04:00
eBlockFace Face = cBlockPistonHandler : : MetaDataToDirection ( a_Meta ) ;
2014-05-29 06:56:22 -04:00
int BlockX = m_Chunk - > GetPosX ( ) * cChunkDef : : Width + a_RelBlockX ;
int BlockZ = m_Chunk - > GetPosZ ( ) * cChunkDef : : Width + a_RelBlockZ ;
2014-02-07 16:59:08 -05:00
2014-02-15 10:51:49 -05:00
for ( PoweredBlocksList : : const_iterator itr = m_PoweredBlocks - > begin ( ) ; itr ! = m_PoweredBlocks - > end ( ) ; + + itr )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( ! itr - > a_BlockPos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) ) ) { continue ; }
2014-02-07 16:59:08 -05:00
2014-05-29 06:56:22 -04:00
AddFaceDirection ( BlockX , a_RelBlockY , BlockZ , Face ) ;
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
if ( ! itr - > a_SourcePos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) ) )
2014-02-07 16:59:08 -05:00
{
return true ;
}
2014-05-29 06:56:22 -04:00
AddFaceDirection ( BlockX , a_RelBlockY , BlockZ , Face , true ) ;
2014-02-07 16:59:08 -05:00
}
2014-02-15 10:51:49 -05:00
for ( LinkedBlocksList : : const_iterator itr = m_LinkedPoweredBlocks - > begin ( ) ; itr ! = m_LinkedPoweredBlocks - > end ( ) ; + + itr )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( ! itr - > a_BlockPos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) ) ) { continue ; }
2014-02-07 16:59:08 -05:00
2014-05-29 06:56:22 -04:00
AddFaceDirection ( BlockX , a_RelBlockY , BlockZ , Face ) ;
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
if ( ! itr - > a_MiddlePos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) ) )
2014-02-07 16:59:08 -05:00
{
return true ;
}
2014-05-29 06:56:22 -04:00
AddFaceDirection ( BlockX , a_RelBlockY , BlockZ , Face , true ) ;
2014-02-07 16:59:08 -05:00
}
return false ; // Source was in front of the piston's front face
}
2014-04-27 12:35:41 -04:00
bool cIncrementalRedstoneSimulator : : IsWirePowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , unsigned char & a_PowerLevel )
2014-02-07 16:59:08 -05:00
{
2014-04-15 08:15:56 -04:00
a_PowerLevel = 0 ;
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
2014-04-15 08:15:56 -04:00
2014-04-18 03:36:11 -04:00
for ( PoweredBlocksList : : const_iterator itr = m_PoweredBlocks - > begin ( ) ; itr ! = m_PoweredBlocks - > end ( ) ; + + itr ) // Check powered list
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( ! itr - > a_BlockPos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) ) )
2014-04-18 03:36:11 -04:00
{
continue ;
}
2014-06-14 05:47:10 -04:00
a_PowerLevel = itr - > a_PowerLevel ;
2014-02-07 16:59:08 -05:00
}
2014-04-18 03:36:11 -04:00
for ( LinkedBlocksList : : const_iterator itr = m_LinkedPoweredBlocks - > begin ( ) ; itr ! = m_LinkedPoweredBlocks - > end ( ) ; + + itr ) // Check linked powered list
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( ! itr - > a_BlockPos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) ) )
2014-04-18 03:36:11 -04:00
{
continue ;
}
2014-06-14 05:47:10 -04:00
a_PowerLevel = itr - > a_PowerLevel ;
2014-02-07 16:59:08 -05:00
}
2014-04-15 08:15:56 -04:00
2014-06-14 05:47:10 -04:00
return ( a_PowerLevel ! = 0 ) ; // Answer the inital question: is the wire powered?
2014-02-07 16:59:08 -05:00
}
2014-04-27 12:35:41 -04:00
bool cIncrementalRedstoneSimulator : : AreCoordsSimulated ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , bool IsCurrentStatePowered )
2014-02-07 16:59:08 -05:00
{
2014-02-15 10:51:49 -05:00
for ( SimulatedPlayerToggleableList : : const_iterator itr = m_SimulatedPlayerToggleableBlocks - > begin ( ) ; itr ! = m_SimulatedPlayerToggleableBlocks - > end ( ) ; + + itr )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( itr - > a_RelBlockPos . Equals ( Vector3i ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ) )
2014-02-07 16:59:08 -05:00
{
if ( itr - > WasLastStatePowered ! = IsCurrentStatePowered ) // Was the last power state different to the current?
{
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
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : SetDirectionLinkedPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , char a_Direction , unsigned char a_PowerLevel )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
BLOCKTYPE MiddleBlock = 0 ;
2014-02-07 16:59:08 -05:00
switch ( a_Direction )
{
case BLOCK_FACE_XM :
{
2014-04-27 12:35:41 -04:00
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ , MiddleBlock ) )
{
return ;
}
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
SetBlockLinkedPowered ( a_RelBlockX - 2 , a_RelBlockY , a_RelBlockZ , a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX - 1 , a_RelBlockY + 1 , a_RelBlockZ , a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX - 1 , a_RelBlockY - 1 , a_RelBlockZ , a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ + 1 , a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ - 1 , a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
2014-02-07 16:59:08 -05:00
break ;
}
case BLOCK_FACE_XP :
{
2014-04-27 12:35:41 -04:00
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ , MiddleBlock ) )
{
return ;
}
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
SetBlockLinkedPowered ( a_RelBlockX + 2 , a_RelBlockY , a_RelBlockZ , a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX + 1 , a_RelBlockY + 1 , a_RelBlockZ , a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX + 1 , a_RelBlockY - 1 , a_RelBlockZ , a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ + 1 , a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ - 1 , a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
2014-02-07 16:59:08 -05:00
break ;
}
case BLOCK_FACE_YM :
{
2014-04-27 12:35:41 -04:00
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ , MiddleBlock ) )
{
return ;
}
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
SetBlockLinkedPowered ( a_RelBlockX , a_RelBlockY - 2 , a_RelBlockZ , a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX + 1 , a_RelBlockY - 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX - 1 , a_RelBlockY - 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
2014-02-07 16:59:08 -05:00
break ;
}
case BLOCK_FACE_YP :
{
2014-04-27 12:35:41 -04:00
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX , a_RelBlockY + 1 , a_RelBlockZ , MiddleBlock ) )
{
return ;
}
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
SetBlockLinkedPowered ( a_RelBlockX , a_RelBlockY + 2 , a_RelBlockZ , a_RelBlockX , a_RelBlockY + 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX + 1 , a_RelBlockY + 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY + 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX - 1 , a_RelBlockY + 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY + 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX , a_RelBlockY + 1 , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY + 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX , a_RelBlockY + 1 , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY + 1 , a_RelBlockZ , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
2014-02-07 16:59:08 -05:00
break ;
}
case BLOCK_FACE_ZM :
{
2014-04-27 12:35:41 -04:00
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX , a_RelBlockY , a_RelBlockZ - 1 , MiddleBlock ) )
{
return ;
}
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
SetBlockLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ - 2 , a_RelBlockX , a_RelBlockY , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX , a_RelBlockY + 1 , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ - 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
2014-02-07 16:59:08 -05:00
break ;
}
case BLOCK_FACE_ZP :
{
2014-04-27 12:35:41 -04:00
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX , a_RelBlockY , a_RelBlockZ + 1 , MiddleBlock ) )
{
return ;
}
2014-02-07 16:59:08 -05:00
2014-04-27 12:35:41 -04:00
SetBlockLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ + 2 , a_RelBlockX , a_RelBlockY , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX , a_RelBlockY + 1 , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
SetBlockLinkedPowered ( a_RelBlockX , a_RelBlockY - 1 , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ + 1 , a_RelBlockX , a_RelBlockY , a_RelBlockZ , MiddleBlock , a_PowerLevel ) ;
2014-02-07 16:59:08 -05:00
break ;
}
default :
{
ASSERT ( ! " Unhandled face direction when attempting to set blocks as linked powered! " ) ; // Zombies, that wasn't supposed to happen...
break ;
}
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : SetAllDirsAsPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , unsigned char a_PowerLevel )
2014-02-07 16:59:08 -05:00
{
static const struct
{
int x , y , z ;
} gCrossCoords [ ] =
{
{ 1 , 0 , 0 } ,
2014-04-27 12:35:41 -04:00
{ - 1 , 0 , 0 } ,
2014-02-07 16:59:08 -05:00
{ 0 , 0 , 1 } ,
2014-04-27 12:35:41 -04:00
{ 0 , 0 , - 1 } ,
2014-02-07 16:59:08 -05:00
{ 0 , 1 , 0 } ,
2014-04-27 12:35:41 -04:00
{ 0 , - 1 , 0 }
2014-02-07 16:59:08 -05:00
} ;
for ( size_t i = 0 ; i < ARRAYCOUNT ( gCrossCoords ) ; i + + ) // Loop through struct to power all directions
{
2014-04-27 12:35:41 -04:00
SetBlockPowered ( a_RelBlockX + gCrossCoords [ i ] . x , a_RelBlockY + gCrossCoords [ i ] . y , a_RelBlockZ + gCrossCoords [ i ] . z , a_RelBlockX , a_RelBlockY , a_RelBlockZ , a_PowerLevel ) ;
2014-02-07 16:59:08 -05:00
}
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : SetBlockPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , int a_RelSourceX , int a_RelSourceY , int a_RelSourceZ , unsigned char a_PowerLevel )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
int SourceX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelSourceX ;
int SourceZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelSourceZ ;
BLOCKTYPE Block = 0 ;
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , Block ) )
{
return ;
}
2014-02-07 16:59:08 -05:00
if ( Block = = E_BLOCK_AIR )
{
// Don't set air, fixes some bugs (wires powering themselves)
return ;
}
2014-06-04 18:23:09 -04:00
cChunk * Neighbour = m_Chunk - > GetNeighborChunk ( BlockX , BlockZ ) ;
PoweredBlocksList * Powered = Neighbour - > GetRedstoneSimulatorPoweredBlocksList ( ) ;
2014-04-18 03:36:11 -04:00
for ( PoweredBlocksList : : iterator itr = Powered - > begin ( ) ; itr ! = Powered - > end ( ) ; + + itr ) // Check powered list
2014-02-07 16:59:08 -05:00
{
if (
2014-04-27 12:35:41 -04:00
itr - > a_BlockPos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) ) & &
itr - > a_SourcePos . Equals ( Vector3i ( SourceX , a_RelSourceY , SourceZ ) )
)
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
// Check for duplicates, update power level, don't add a new listing
itr - > a_PowerLevel = a_PowerLevel ;
2014-02-07 16:59:08 -05:00
return ;
}
}
2014-04-27 12:35:41 -04:00
PoweredBlocksList * OtherPowered = m_Chunk - > GetNeighborChunk ( SourceX , SourceZ ) - > GetRedstoneSimulatorPoweredBlocksList ( ) ;
2014-04-18 03:36:11 -04:00
for ( PoweredBlocksList : : const_iterator itr = OtherPowered - > begin ( ) ; itr ! = OtherPowered - > end ( ) ; + + itr ) // Check powered list
2014-04-15 08:15:56 -04:00
{
if (
2014-04-27 12:35:41 -04:00
itr - > a_BlockPos . Equals ( Vector3i ( SourceX , a_RelSourceY , SourceZ ) ) & &
itr - > a_SourcePos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) )
)
2014-04-15 08:15:56 -04:00
{
// Powered wires try to power their source - don't let them!
return ;
}
}
2014-02-07 16:59:08 -05:00
sPoweredBlocks RC ;
2014-04-27 12:35:41 -04:00
RC . a_BlockPos = Vector3i ( BlockX , a_RelBlockY , BlockZ ) ;
RC . a_SourcePos = Vector3i ( SourceX , a_RelSourceY , SourceZ ) ;
2014-04-15 08:15:56 -04:00
RC . a_PowerLevel = a_PowerLevel ;
2014-02-15 10:51:49 -05:00
Powered - > push_back ( RC ) ;
2014-06-04 18:23:09 -04:00
Neighbour - > SetIsRedstoneDirty ( true ) ;
m_Chunk - > SetIsRedstoneDirty ( true ) ;
2014-02-07 16:59:08 -05:00
}
void cIncrementalRedstoneSimulator : : SetBlockLinkedPowered (
2014-04-27 12:35:41 -04:00
int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ,
int a_RelMiddleX , int a_RelMiddleY , int a_RelMiddleZ ,
int a_RelSourceX , int a_RelSourceY , int a_RelSourceZ ,
BLOCKTYPE a_MiddleBlock , unsigned char a_PowerLevel
)
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
int BlockX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelBlockX ;
int BlockZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelBlockZ ;
int MiddleX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelMiddleX ;
int MiddleZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelMiddleZ ;
int SourceX = ( m_Chunk - > GetPosX ( ) * cChunkDef : : Width ) + a_RelSourceX ;
int SourceZ = ( m_Chunk - > GetPosZ ( ) * cChunkDef : : Width ) + a_RelSourceZ ;
BLOCKTYPE DestBlock = 0 ;
if ( ! m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX , a_RelBlockY , a_RelBlockZ , DestBlock ) )
{
return ;
}
2014-02-07 16:59:08 -05:00
if ( DestBlock = = E_BLOCK_AIR )
{
// Don't set air, fixes some bugs (wires powering themselves)
return ;
}
2014-04-27 12:35:41 -04:00
if ( ( DestBlock = = E_BLOCK_REDSTONE_WIRE ) & & ( m_Chunk - > GetBlock ( a_RelSourceX , a_RelSourceY , a_RelSourceZ ) = = E_BLOCK_REDSTONE_WIRE ) )
{
return ;
}
2014-02-07 16:59:08 -05:00
if ( ! IsViableMiddleBlock ( a_MiddleBlock ) )
{
return ;
}
2014-06-04 18:23:09 -04:00
cChunk * Neighbour = m_Chunk - > GetNeighborChunk ( BlockX , BlockZ ) ;
LinkedBlocksList * Linked = Neighbour - > GetRedstoneSimulatorLinkedBlocksList ( ) ;
2014-04-18 03:36:11 -04:00
for ( LinkedBlocksList : : iterator itr = Linked - > begin ( ) ; itr ! = Linked - > end ( ) ; + + itr ) // Check linked powered list
2014-02-07 16:59:08 -05:00
{
if (
2014-04-27 12:35:41 -04:00
itr - > a_BlockPos . Equals ( Vector3i ( BlockX , a_RelBlockY , BlockZ ) ) & &
itr - > a_MiddlePos . Equals ( Vector3i ( MiddleX , a_RelMiddleY , MiddleZ ) ) & &
itr - > a_SourcePos . Equals ( Vector3i ( SourceX , a_RelSourceY , SourceZ ) )
2014-04-18 03:36:11 -04:00
)
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
// Check for duplicates, update power level, don't add a new listing
itr - > a_PowerLevel = a_PowerLevel ;
2014-02-07 16:59:08 -05:00
return ;
}
}
sLinkedPoweredBlocks RC ;
2014-04-27 12:35:41 -04:00
RC . a_BlockPos = Vector3i ( BlockX , a_RelBlockY , BlockZ ) ;
RC . a_MiddlePos = Vector3i ( MiddleX , a_RelMiddleY , MiddleZ ) ;
RC . a_SourcePos = Vector3i ( SourceX , a_RelSourceY , SourceZ ) ;
2014-04-15 08:15:56 -04:00
RC . a_PowerLevel = a_PowerLevel ;
2014-02-15 10:51:49 -05:00
Linked - > push_back ( RC ) ;
2014-06-04 18:23:09 -04:00
Neighbour - > SetIsRedstoneDirty ( true ) ;
m_Chunk - > SetIsRedstoneDirty ( true ) ;
2014-02-07 16:59:08 -05:00
}
2014-04-27 12:35:41 -04:00
void cIncrementalRedstoneSimulator : : SetPlayerToggleableBlockAsSimulated ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , bool WasLastStatePowered )
2014-02-07 16:59:08 -05:00
{
2014-02-15 10:51:49 -05:00
for ( SimulatedPlayerToggleableList : : iterator itr = m_SimulatedPlayerToggleableBlocks - > begin ( ) ; itr ! = m_SimulatedPlayerToggleableBlocks - > end ( ) ; + + itr )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( ! itr - > a_RelBlockPos . Equals ( Vector3i ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ) )
2014-02-07 16:59:08 -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 ;
}
}
// We have arrive here; no block must be in list - add one
sSimulatedPlayerToggleableList RC ;
2014-04-27 12:35:41 -04:00
RC . a_RelBlockPos = Vector3i ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
RC . WasLastStatePowered = WasLastStatePowered ;
2014-02-15 10:51:49 -05:00
m_SimulatedPlayerToggleableBlocks - > push_back ( RC ) ;
2014-02-07 16:59:08 -05:00
}
2014-06-06 18:23:28 -04:00
bool cIncrementalRedstoneSimulator : : QueueRepeaterPowerChange ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , NIBBLETYPE a_Meta , bool ShouldPowerOn )
2014-02-07 16:59:08 -05:00
{
2014-02-15 10:51:49 -05:00
for ( RepeatersDelayList : : iterator itr = m_RepeatersDelayList - > begin ( ) ; itr ! = m_RepeatersDelayList - > end ( ) ; + + itr )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( itr - > a_RelBlockPos . Equals ( Vector3i ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ) )
2014-02-07 16:59:08 -05:00
{
if ( ShouldPowerOn = = itr - > ShouldPowerOn ) // We are queued already for the same thing, don't replace entry
{
2014-06-06 18:23:28 -04:00
return false ;
2014-02-07 16:59:08 -05:00
}
// Already in here (normal to allow repeater to continue on powering and updating blocks in front) - just update info and quit
2014-02-15 10:51:49 -05:00
itr - > a_DelayTicks = ( ( ( a_Meta & 0xC ) > > 0x2 ) + 1 ) * 2 ; // See below for description
2014-02-07 16:59:08 -05:00
itr - > a_ElapsedTicks = 0 ;
itr - > ShouldPowerOn = ShouldPowerOn ;
2014-06-06 18:23:28 -04:00
return false ;
2014-02-07 16:59:08 -05:00
}
}
// Self not in list, add self to list
2014-02-15 10:51:49 -05:00
sRepeatersDelayList RC ;
2014-04-27 12:35:41 -04:00
RC . a_RelBlockPos = Vector3i ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ;
2014-02-07 16:59:08 -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.)
2014-04-15 08:15:56 -04:00
// * 2 because in MCS, 1 redstone tick = 1 world tick, but in Vanilla, 1 redstone tick = 2 world ticks, and we need to maintain compatibility
2014-02-15 10:51:49 -05:00
RC . a_DelayTicks = ( ( ( a_Meta & 0xC ) > > 0x2 ) + 1 ) * 2 ;
2014-02-07 16:59:08 -05:00
RC . a_ElapsedTicks = 0 ;
RC . ShouldPowerOn = ShouldPowerOn ;
2014-02-15 10:51:49 -05:00
m_RepeatersDelayList - > push_back ( RC ) ;
2014-06-06 18:23:28 -04:00
return true ;
2014-02-07 16:59:08 -05:00
}
2014-04-27 12:35:41 -04:00
cIncrementalRedstoneSimulator : : eRedstoneDirection cIncrementalRedstoneSimulator : : GetWireDirection ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ )
2014-02-07 16:59:08 -05:00
{
int Dir = REDSTONE_NONE ;
2014-04-27 12:35:41 -04:00
BLOCKTYPE NegX = 0 ;
if ( m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX - 1 , a_RelBlockY , a_RelBlockZ , NegX ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( IsPotentialSource ( NegX ) )
{
Dir | = ( REDSTONE_X_POS ) ;
}
2014-02-07 16:59:08 -05:00
}
2014-04-27 12:35:41 -04:00
BLOCKTYPE PosX = 0 ;
if ( m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX + 1 , a_RelBlockY , a_RelBlockZ , PosX ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( IsPotentialSource ( PosX ) )
{
Dir | = ( REDSTONE_X_NEG ) ;
}
2014-02-07 16:59:08 -05:00
}
2014-04-27 12:35:41 -04:00
BLOCKTYPE NegZ = 0 ;
if ( m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX , a_RelBlockY , a_RelBlockZ - 1 , NegZ ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( IsPotentialSource ( NegZ ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
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 ;
2014-02-07 16:59:08 -05:00
}
}
2014-04-27 12:35:41 -04:00
BLOCKTYPE PosZ = 0 ;
if ( m_Chunk - > UnboundedRelGetBlockType ( a_RelBlockX , a_RelBlockY , a_RelBlockZ + 1 , PosZ ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
if ( IsPotentialSource ( PosZ ) )
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
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 ;
2014-02-07 16:59:08 -05:00
}
}
return ( eRedstoneDirection ) Dir ;
}
bool cIncrementalRedstoneSimulator : : IsLeverOn ( NIBBLETYPE a_BlockMeta )
{
// Extract the ON bit from metadata and return if true if it is set:
return ( ( a_BlockMeta & 0x8 ) = = 0x8 ) ;
}