2012-10-06 16:04:58 -04:00
2012-06-14 09:06:06 -04:00
# pragma once
2012-09-23 18:09:57 -04:00
# include "Simulator.h"
2012-06-14 09:06:06 -04:00
2013-11-18 17:30:34 -05:00
/// Per-chunk data for the simulator, specified individual chunks to simulate; 'Data' is not used
typedef cCoordWithIntList cRedstoneSimulatorChunkData ;
2012-10-06 16:04:58 -04:00
class cRedstoneSimulator :
public cSimulator
2012-06-14 09:06:06 -04:00
{
typedef cSimulator super ;
public :
2013-11-18 17:30:34 -05:00
2013-02-28 08:39:20 -05:00
cRedstoneSimulator ( cWorld & a_World ) ;
2012-06-14 09:06:06 -04:00
~ cRedstoneSimulator ( ) ;
2013-11-18 17:30:34 -05:00
virtual void Simulate ( float a_Dt ) override { } ; // Not used in this simulator
virtual void SimulateChunk ( float a_Dt , int a_ChunkX , int a_ChunkZ , cChunk * a_Chunk ) override ;
virtual bool IsAllowedBlock ( BLOCKTYPE a_BlockType ) override { return IsRedstone ( a_BlockType ) ; }
2012-06-14 09:06:06 -04:00
enum eRedstoneDirection
{
REDSTONE_NONE = 0 ,
REDSTONE_X_POS = 0x1 ,
REDSTONE_X_NEG = 0x2 ,
REDSTONE_Z_POS = 0x4 ,
REDSTONE_Z_NEG = 0x8 ,
} ;
2012-12-16 02:07:30 -05:00
eRedstoneDirection GetWireDirection ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
2012-10-06 16:04:58 -04:00
2012-06-14 09:06:06 -04:00
private :
2013-11-18 17:30:34 -05:00
struct sPoweredBlocks // Define structure of the directly powered blocks list
2012-06-14 09:06:06 -04:00
{
2013-11-18 17:30:34 -05:00
Vector3i a_BlockPos ; // Position of powered block
Vector3i a_SourcePos ; // Position of source powering the block at a_BlockPos
BLOCKTYPE a_SourceBlock ; // The source block type (for pistons pushing away sources and replacing with non source etc.)
2012-06-14 09:06:06 -04:00
} ;
2013-11-18 17:30:34 -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 ;
Vector3i a_MiddlePos ;
Vector3i a_SourcePos ;
BLOCKTYPE a_SourceBlock ;
BLOCKTYPE a_MiddleBlock ;
} ;
2013-12-07 09:41:58 -05:00
struct sSimulatedPlayerToggleableList
{
Vector3i a_BlockPos ;
bool WasLastStatePowered ;
} ;
2013-12-09 19:21:24 -05:00
struct sRepeatersDelayList
{
Vector3i a_BlockPos ;
short a_DelayTicks ;
short a_ElapsedTicks ;
} ;
2012-06-14 09:06:06 -04:00
2013-11-18 17:30:34 -05:00
typedef std : : vector < sPoweredBlocks > PoweredBlocksList ;
typedef std : : vector < sLinkedPoweredBlocks > LinkedBlocksList ;
2013-12-07 09:41:58 -05:00
typedef std : : vector < sSimulatedPlayerToggleableList > SimulatedPlayerToggleableList ;
2013-12-09 19:21:24 -05:00
typedef std : : vector < sRepeatersDelayList > RepeatersDelayList ;
2013-11-18 17:30:34 -05:00
PoweredBlocksList m_PoweredBlocks ;
LinkedBlocksList m_LinkedPoweredBlocks ;
2013-12-07 09:41:58 -05:00
SimulatedPlayerToggleableList m_SimulatedPlayerToggleableBlocks ;
2013-12-09 19:21:24 -05:00
RepeatersDelayList m_RepeatersDelayList ;
2013-11-18 17:30:34 -05:00
virtual void AddBlock ( int a_BlockX , int a_BlockY , int a_BlockZ , cChunk * a_Chunk ) override ;
// 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 ====== */
2013-11-26 16:54:07 -05:00
/// <summary>Handles the redstone torch</summary>
2013-11-18 17:30:34 -05:00
void HandleRedstoneTorch ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_MyState ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Handles the redstone block</summary>
2013-11-18 17:30:34 -05:00
void HandleRedstoneBlock ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Handles levers</summary>
2013-11-18 17:30:34 -05:00
void HandleRedstoneLever ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Handles buttons</summary>
2013-11-18 17:30:34 -05:00
void HandleRedstoneButton ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_BlockType ) ;
/* ==================== */
/* ====== CARRIERS ====== */
2013-11-26 16:54:07 -05:00
/// <summary>Handles redstone wire</summary>
2013-11-18 17:30:34 -05:00
void HandleRedstoneWire ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Handles repeaters</summary>
2013-11-18 17:30:34 -05:00
void HandleRedstoneRepeater ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_MyState ) ;
/* ====================== */
/* ====== DEVICES ====== */
2013-11-26 16:54:07 -05:00
/// <summary>Handles pistons</summary>
2013-11-18 17:30:34 -05:00
void HandlePiston ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Handles dispensers and droppers</summary>
2013-11-18 17:30:34 -05:00
void HandleDropSpenser ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Handles TNT (exploding)</summary>
2013-11-18 17:30:34 -05:00
void HandleTNT ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Handles redstone lamps</summary>
2013-11-18 17:30:34 -05:00
void HandleRedstoneLamp ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_MyState ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Handles doords</summary>
2013-11-18 17:30:34 -05:00
void HandleDoor ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Handles activator, detector, and powered rails</summary>
2013-11-18 17:30:34 -05:00
void HandleRail ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_MyType ) ;
2013-11-29 17:27:08 -05:00
/// <summary>Handles trapdoors</summary>
void HandleTrapdoor ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
2013-11-18 17:30:34 -05:00
/* ===================== */
/* ====== Helper functions ====== */
2013-11-26 16:54:07 -05:00
/// <summary>Marks a block as powered</summary>
2013-11-18 17:30:34 -05:00
void SetBlockPowered ( int a_BlockX , int a_BlockY , int a_BlockZ , int a_SourceX , int a_SourceY , int a_SourceZ , BLOCKTYPE a_SourceBlock ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Marks a block as being powered through another block</summary>
2013-11-18 17:30:34 -05:00
void SetBlockLinkedPowered ( int a_BlockX , int a_BlockY , int a_BlockZ , int a_MiddleX , int a_MiddleY , int a_MiddleZ , int a_SourceX , int a_SourceY , int a_SourceZ , BLOCKTYPE a_SourceBlock , BLOCKTYPE a_MiddeBlock ) ;
2013-12-07 09:41:58 -05:00
/// <summary>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</summary>
void SetPlayerToggleableBlockAsSimulated ( int a_BlockX , int a_BlockY , int a_BlockZ , bool WasLastStatePowered ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Marks the second block in a direction as linked powered</summary>
2013-11-20 17:54:28 -05:00
void SetDirectionLinkedPowered ( int a_BlockX , int a_BlockY , int a_BlockZ , char a_Direction , BLOCKTYPE a_SourceBlock ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Marks all blocks immediately surrounding a coordinate as powered</summary>
2013-11-20 17:54:28 -05:00
void SetAllDirsAsPowered ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_SourceBlock ) ;
2013-11-18 17:30:34 -05:00
2013-11-26 16:54:07 -05:00
/// <summary>Returns if a coordinate is powered or linked powered</summary>
2013-11-18 17:30:34 -05:00
bool AreCoordsPowered ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
2013-12-07 09:41:58 -05:00
/// <summary>Returns if a coordinate was marked as simulated (for blocks toggleable by players)</summary>
bool AreCoordsSimulated ( int a_BlockX , int a_BlockY , int a_BlockZ , bool IsCurrentStatePowered ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Returns if a repeater is powered</summary>
2013-11-18 17:30:34 -05:00
bool IsRepeaterPowered ( int a_BlockX , int a_BlockY , int a_BlockZ , NIBBLETYPE a_Meta ) ;
2013-11-30 07:11:39 -05:00
/// <summary>Returns if a piston is powered</summary>
bool IsPistonPowered ( int a_BlockX , int a_BlockY , int a_BlockZ , NIBBLETYPE a_Meta ) ;
2013-11-18 17:30:34 -05:00
2013-11-26 16:54:07 -05:00
/// <summary>Returns if lever metadata marks it as emitting power</summary>
2013-11-18 17:30:34 -05:00
bool IsLeverOn ( NIBBLETYPE a_BlockMeta ) ;
2013-11-26 16:54:07 -05:00
/// <summary>Returns if button metadata marks it as emitting power</summary>
2013-11-18 17:30:34 -05:00
bool IsButtonOn ( NIBBLETYPE a_BlockMeta ) ;
/* ============================== */
2013-11-21 17:44:18 -05:00
/* ====== Misc Functions ====== */
2013-11-26 16:54:07 -05:00
/// <summary>Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation</summary>
2013-11-21 17:44:18 -05:00
inline static bool IsViableMiddleBlock ( BLOCKTYPE Block )
{
if ( ! g_BlockIsSolid [ Block ] ) { return false ; }
switch ( Block )
{
// Add SOLID but not viable middle blocks here
2013-12-11 13:42:38 -05:00
case E_BLOCK_PISTON :
case E_BLOCK_PISTON_EXTENSION :
case E_BLOCK_STICKY_PISTON :
2013-11-21 17:44:18 -05:00
case E_BLOCK_REDSTONE_REPEATER_ON :
case E_BLOCK_REDSTONE_REPEATER_OFF :
{
return false ;
}
default :
{
return true ;
}
}
}
2013-11-26 16:54:07 -05:00
/// <summary>Returns if a block is a mechanism (something that accepts power and does something)</summary>
2013-11-18 17:30:34 -05:00
inline static bool IsMechanism ( BLOCKTYPE Block )
{
switch ( Block )
{
2013-11-20 17:54:28 -05:00
case E_BLOCK_ACTIVATOR_RAIL :
2013-11-18 17:30:34 -05:00
case E_BLOCK_PISTON :
case E_BLOCK_STICKY_PISTON :
case E_BLOCK_DISPENSER :
case E_BLOCK_DROPPER :
2013-11-20 17:54:28 -05:00
case E_BLOCK_FENCE_GATE :
case E_BLOCK_HOPPER :
case E_BLOCK_NOTE_BLOCK :
2013-11-18 17:30:34 -05:00
case E_BLOCK_TNT :
2013-11-20 17:54:28 -05:00
case E_BLOCK_TRAPDOOR :
2013-11-18 17:30:34 -05:00
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 ;
}
}
2013-11-26 16:54:07 -05:00
/// <summary>Returns if a block has the potential to output power</summary>
2013-11-18 17:30:34 -05:00
inline static bool IsPotentialSource ( BLOCKTYPE Block )
{
switch ( Block )
{
case E_BLOCK_WOODEN_BUTTON :
case E_BLOCK_STONE_BUTTON :
case E_BLOCK_REDSTONE_WIRE :
case E_BLOCK_REDSTONE_TORCH_OFF :
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 :
{
return true ;
}
default : return false ;
}
}
2013-11-26 16:54:07 -05:00
/// <summary>Returns if a block is any sort of redstone device</summary>
2013-11-18 17:30:34 -05:00
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_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_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 ;
}
}
} ;