2014-02-07 16:59:08 -05:00
# pragma once
# include "RedstoneSimulator.h"
2014-02-15 10:51:49 -05:00
/// Per-chunk data for the simulator, specified individual chunks to simulate
2014-02-07 16:59:08 -05:00
typedef cCoordWithBlockAndBoolVector cRedstoneSimulatorChunkData ;
class cIncrementalRedstoneSimulator :
public cRedstoneSimulator
{
typedef cRedstoneSimulator super ;
public :
cIncrementalRedstoneSimulator ( cWorld & a_World ) ;
~ cIncrementalRedstoneSimulator ( ) ;
virtual void Simulate ( float a_Dt ) override { UNUSED ( a_Dt ) ; } // not used
virtual void SimulateChunk ( float a_Dt , int a_ChunkX , int a_ChunkZ , cChunk * a_Chunk ) override ;
2014-02-15 10:51:49 -05:00
virtual bool IsAllowedBlock ( BLOCKTYPE a_BlockType ) override { return IsRedstone ( a_BlockType ) ; }
virtual void WakeUp ( int a_BlockX , int a_BlockY , int a_BlockZ , cChunk * a_Chunk ) override ;
2014-02-07 16:59:08 -05:00
enum eRedstoneDirection
{
REDSTONE_NONE = 0 ,
REDSTONE_X_POS = 0x1 ,
REDSTONE_X_NEG = 0x2 ,
REDSTONE_Z_POS = 0x4 ,
REDSTONE_Z_NEG = 0x8 ,
} ;
eRedstoneDirection GetWireDirection ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
private :
2014-04-17 07:11:31 -04:00
# define MAX_POWER_LEVEL 15
2014-02-07 16:59:08 -05:00
struct sPoweredBlocks // Define structure of the directly powered blocks list
{
Vector3i a_BlockPos ; // Position of powered block
Vector3i a_SourcePos ; // Position of source powering the block at a_BlockPos
2014-04-15 08:15:56 -04:00
unsigned char a_PowerLevel ;
2014-02-07 16:59:08 -05:00
} ;
struct sLinkedPoweredBlocks // Define structure of the indirectly powered blocks list (i.e. repeaters powering through a block to the block at the other side)
{
Vector3i a_BlockPos ;
2014-04-15 08:15:56 -04:00
Vector3i a_MiddlePos ; // Position of block that is betwixt a source and the destination
2014-02-07 16:59:08 -05:00
Vector3i a_SourcePos ;
2014-04-15 08:15:56 -04:00
unsigned char a_PowerLevel ;
2014-02-07 16:59:08 -05:00
} ;
2014-04-15 08:15:56 -04:00
struct sSimulatedPlayerToggleableList // Define structure of the list containing simulate-on-update blocks (such as trapdoors that respond once to a block update, and can be toggled by a player)
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
Vector3i a_RelBlockPos ;
2014-04-15 08:15:56 -04:00
bool WasLastStatePowered ; // Was the last state powered or not? Determines whether a source update has happened and if I should resimulate
2014-02-07 16:59:08 -05:00
} ;
2014-04-15 08:15:56 -04:00
struct sRepeatersDelayList // Define structure of list containing repeaters' delay states
2014-02-07 16:59:08 -05:00
{
2014-04-27 12:35:41 -04:00
Vector3i a_RelBlockPos ;
2014-04-15 08:15:56 -04:00
unsigned char a_DelayTicks ; // For how many ticks should the repeater delay
unsigned char a_ElapsedTicks ; // How much of the previous has been elapsed?
bool ShouldPowerOn ; // What happens when the delay time is fulfilled?
2014-02-07 16:59:08 -05:00
} ;
2014-02-15 10:51:49 -05:00
public :
2014-02-07 16:59:08 -05:00
typedef std : : vector < sPoweredBlocks > PoweredBlocksList ;
typedef std : : vector < sLinkedPoweredBlocks > LinkedBlocksList ;
typedef std : : vector < sSimulatedPlayerToggleableList > SimulatedPlayerToggleableList ;
typedef std : : vector < sRepeatersDelayList > RepeatersDelayList ;
2014-02-15 10:51:49 -05:00
private :
cRedstoneSimulatorChunkData * m_RedstoneSimulatorChunkData ;
PoweredBlocksList * m_PoweredBlocks ;
LinkedBlocksList * m_LinkedPoweredBlocks ;
SimulatedPlayerToggleableList * m_SimulatedPlayerToggleableBlocks ;
RepeatersDelayList * m_RepeatersDelayList ;
2014-02-07 16:59:08 -05:00
2014-02-15 14:56:45 -05:00
virtual void AddBlock ( int a_BlockX , int a_BlockY , int a_BlockZ , cChunk * a_Chunk ) override { RedstoneAddBlock ( a_BlockX , a_BlockY , a_BlockZ , a_Chunk ) ; }
void RedstoneAddBlock ( int a_BlockX , int a_BlockY , int a_BlockZ , cChunk * a_Chunk , cChunk * a_OtherChunk = NULL ) ;
2014-02-15 10:51:49 -05:00
cChunk * m_Chunk ;
2014-02-07 16:59:08 -05:00
// We want a_MyState for devices needing a full FastSetBlock (as opposed to meta) because with our simulation model, we cannot keep setting the block if it is already set correctly
// In addition to being non-performant, it would stop the player from actually breaking said device
/* ====== SOURCES ====== */
/** Handles the redstone torch */
2014-04-27 12:35:41 -04:00
void HandleRedstoneTorch ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , BLOCKTYPE a_MyState ) ;
2014-02-07 16:59:08 -05:00
/** Handles the redstone block */
2014-04-27 12:35:41 -04:00
void HandleRedstoneBlock ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Handles levers */
2014-04-27 12:35:41 -04:00
void HandleRedstoneLever ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Handles buttons */
2014-04-27 12:35:41 -04:00
void HandleRedstoneButton ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Handles daylight sensors */
2014-04-27 12:35:41 -04:00
void HandleDaylightSensor ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Handles pressure plates */
2014-04-27 12:35:41 -04:00
void HandlePressurePlate ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , BLOCKTYPE a_MyType ) ;
2014-02-07 16:59:08 -05:00
/* ==================== */
/* ====== CARRIERS ====== */
/** Handles redstone wire */
2014-04-27 12:35:41 -04:00
void HandleRedstoneWire ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Handles repeaters */
2014-04-27 12:35:41 -04:00
void HandleRedstoneRepeater ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , BLOCKTYPE a_MyState ) ;
2014-02-07 16:59:08 -05:00
/* ====================== */
/* ====== DEVICES ====== */
/** Handles pistons */
2014-04-27 12:35:41 -04:00
void HandlePiston ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Handles dispensers and droppers */
2014-04-27 12:35:41 -04:00
void HandleDropSpenser ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Handles TNT (exploding) */
2014-04-27 12:35:41 -04:00
void HandleTNT ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Handles redstone lamps */
2014-04-27 12:35:41 -04:00
void HandleRedstoneLamp ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , BLOCKTYPE a_MyState ) ;
2014-02-07 16:59:08 -05:00
/** Handles doords */
2014-04-27 12:35:41 -04:00
void HandleDoor ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Handles command blocks */
2014-04-27 12:35:41 -04:00
void HandleCommandBlock ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Handles activator, detector, and powered rails */
2014-04-27 12:35:41 -04:00
void HandleRail ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , BLOCKTYPE a_MyType ) ;
2014-02-07 16:59:08 -05:00
/** Handles trapdoors */
2014-04-27 12:35:41 -04:00
void HandleTrapdoor ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-15 10:51:49 -05:00
/** Handles fence gates */
2014-04-27 12:35:41 -04:00
void HandleFenceGate ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Handles noteblocks */
2014-04-27 12:35:41 -04:00
void HandleNoteBlock ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/* ===================== */
/* ====== Helper functions ====== */
/** Marks a block as powered */
2014-04-27 12:35:41 -04:00
void SetBlockPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , int a_RelSourceX , int a_RelSourceY , int a_RelSourceZ , unsigned char a_PowerLevel = MAX_POWER_LEVEL ) ;
2014-02-07 16:59:08 -05:00
/** Marks a block as being powered through another block */
2014-04-27 12:35:41 -04:00
void SetBlockLinkedPowered ( 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_MiddeBlock , unsigned char a_PowerLevel = MAX_POWER_LEVEL ) ;
2014-02-07 16:59:08 -05:00
/** Marks a block as simulated, who should not be simulated further unless their power state changes, to accomodate a player manually toggling the block without triggering the simulator toggling it back */
2014-04-27 12:35:41 -04:00
void SetPlayerToggleableBlockAsSimulated ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , bool WasLastStatePowered ) ;
2014-02-07 16:59:08 -05:00
/** Marks the second block in a direction as linked powered */
2014-04-27 12:35:41 -04:00
void SetDirectionLinkedPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , char a_Direction , unsigned char a_PowerLevel = MAX_POWER_LEVEL ) ;
2014-02-07 16:59:08 -05:00
/** Marks all blocks immediately surrounding a coordinate as powered */
2014-04-27 12:35:41 -04:00
void SetAllDirsAsPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , unsigned char a_PowerLevel = MAX_POWER_LEVEL ) ;
2014-02-07 16:59:08 -05:00
/** Queues a repeater to be powered or unpowered */
2014-04-27 12:35:41 -04:00
void QueueRepeaterPowerChange ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , NIBBLETYPE a_Meta , bool ShouldPowerOn ) ;
2014-02-07 16:59:08 -05:00
/** Returns if a coordinate is powered or linked powered */
2014-04-27 12:35:41 -04:00
bool AreCoordsPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) { return AreCoordsDirectlyPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) | | AreCoordsLinkedPowered ( a_RelBlockX , a_RelBlockY , a_RelBlockZ ) ; }
2014-02-07 16:59:08 -05:00
/** Returns if a coordinate is in the directly powered blocks list */
2014-04-27 12:35:41 -04:00
bool AreCoordsDirectlyPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Returns if a coordinate is in the indirectly powered blocks list */
2014-04-27 12:35:41 -04:00
bool AreCoordsLinkedPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ ) ;
2014-02-07 16:59:08 -05:00
/** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */
2014-04-27 12:35:41 -04:00
bool AreCoordsSimulated ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , bool IsCurrentStatePowered ) ;
2014-02-07 16:59:08 -05:00
/** Returns if a repeater is powered */
2014-04-27 12:35:41 -04:00
bool IsRepeaterPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , NIBBLETYPE a_Meta ) ;
2014-04-06 14:09:33 -04:00
/** Returns if a repeater is locked */
2014-04-27 12:35:41 -04:00
bool IsRepeaterLocked ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , NIBBLETYPE a_Meta ) ;
2014-02-07 16:59:08 -05:00
/** Returns if a piston is powered */
2014-04-27 12:35:41 -04:00
bool IsPistonPowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , NIBBLETYPE a_Meta ) ;
2014-02-07 16:59:08 -05:00
/** Returns if a wire is powered
2014-04-15 08:15:56 -04:00
The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire */
2014-04-27 12:35:41 -04:00
bool IsWirePowered ( int a_RelBlockX , int a_RelBlockY , int a_RelBlockZ , unsigned char & a_PowerLevel ) ;
2014-02-07 16:59:08 -05:00
/** Returns if lever metadata marks it as emitting power */
2014-04-17 08:02:20 -04:00
bool IsLeverOn ( NIBBLETYPE a_BlockMeta ) ;
2014-02-07 16:59:08 -05:00
/** Returns if button metadata marks it as emitting power */
2014-04-17 08:02:20 -04:00
bool IsButtonOn ( NIBBLETYPE a_BlockMeta ) { return IsLeverOn ( a_BlockMeta ) ; }
2014-02-07 16:59:08 -05:00
/* ============================== */
/* ====== Misc Functions ====== */
/** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */
2014-03-01 14:34:19 -05:00
inline static bool IsViableMiddleBlock ( BLOCKTYPE Block ) { return cBlockInfo : : FullyOccupiesVoxel ( Block ) ; }
2014-02-07 16:59:08 -05:00
/** Returns if a block is a mechanism (something that accepts power and does something) */
inline static bool IsMechanism ( BLOCKTYPE Block )
{
switch ( Block )
{
case E_BLOCK_ACTIVATOR_RAIL :
case E_BLOCK_COMMAND_BLOCK :
case E_BLOCK_PISTON :
case E_BLOCK_STICKY_PISTON :
case E_BLOCK_DISPENSER :
case E_BLOCK_DROPPER :
case E_BLOCK_FENCE_GATE :
case E_BLOCK_HOPPER :
case E_BLOCK_NOTE_BLOCK :
case E_BLOCK_TNT :
case E_BLOCK_TRAPDOOR :
case E_BLOCK_REDSTONE_LAMP_OFF :
case E_BLOCK_REDSTONE_LAMP_ON :
case E_BLOCK_WOODEN_DOOR :
case E_BLOCK_IRON_DOOR :
case E_BLOCK_REDSTONE_REPEATER_OFF :
case E_BLOCK_REDSTONE_REPEATER_ON :
case E_BLOCK_POWERED_RAIL :
{
return true ;
}
default : return false ;
}
}
/** Returns if a block has the potential to output power */
inline static bool IsPotentialSource ( BLOCKTYPE Block )
{
switch ( Block )
{
case E_BLOCK_DETECTOR_RAIL :
case E_BLOCK_DAYLIGHT_SENSOR :
case E_BLOCK_WOODEN_BUTTON :
case E_BLOCK_STONE_BUTTON :
case E_BLOCK_REDSTONE_WIRE :
case E_BLOCK_REDSTONE_TORCH_ON :
case E_BLOCK_LEVER :
case E_BLOCK_REDSTONE_REPEATER_ON :
case E_BLOCK_BLOCK_OF_REDSTONE :
case E_BLOCK_ACTIVE_COMPARATOR :
2014-02-11 18:13:49 -05:00
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE :
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE :
case E_BLOCK_STONE_PRESSURE_PLATE :
case E_BLOCK_WOODEN_PRESSURE_PLATE :
2014-02-07 16:59:08 -05:00
{
return true ;
}
default : return false ;
}
}
/** Returns if a block is any sort of redstone device */
inline static bool IsRedstone ( BLOCKTYPE Block )
{
switch ( Block )
{
// All redstone devices, please alpha sort
case E_BLOCK_ACTIVATOR_RAIL :
case E_BLOCK_ACTIVE_COMPARATOR :
case E_BLOCK_BLOCK_OF_REDSTONE :
case E_BLOCK_COMMAND_BLOCK :
case E_BLOCK_DETECTOR_RAIL :
case E_BLOCK_DISPENSER :
case E_BLOCK_DAYLIGHT_SENSOR :
case E_BLOCK_DROPPER :
case E_BLOCK_FENCE_GATE :
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE :
case E_BLOCK_HOPPER :
case E_BLOCK_INACTIVE_COMPARATOR :
case E_BLOCK_IRON_DOOR :
case E_BLOCK_LEVER :
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE :
case E_BLOCK_NOTE_BLOCK :
case E_BLOCK_POWERED_RAIL :
case E_BLOCK_REDSTONE_LAMP_OFF :
case E_BLOCK_REDSTONE_LAMP_ON :
case E_BLOCK_REDSTONE_REPEATER_OFF :
case E_BLOCK_REDSTONE_REPEATER_ON :
case E_BLOCK_REDSTONE_TORCH_OFF :
case E_BLOCK_REDSTONE_TORCH_ON :
case E_BLOCK_REDSTONE_WIRE :
case E_BLOCK_STICKY_PISTON :
case E_BLOCK_STONE_BUTTON :
case E_BLOCK_STONE_PRESSURE_PLATE :
case E_BLOCK_TNT :
case E_BLOCK_TRAPDOOR :
case E_BLOCK_TRIPWIRE_HOOK :
case E_BLOCK_WOODEN_BUTTON :
case E_BLOCK_WOODEN_DOOR :
case E_BLOCK_WOODEN_PRESSURE_PLATE :
case E_BLOCK_PISTON :
{
return true ;
}
default : return false ;
}
}
} ;
2014-02-15 10:51:49 -05:00