summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTycho <work.tycho+git@gmail.com>2014-09-16 21:29:31 +0200
committerTycho <work.tycho+git@gmail.com>2014-09-16 21:29:31 +0200
commit26a4845a995065f0ed24ef0e21e4c9bf44cef002 (patch)
tree56037a87d24a4162698fca4d7180b0c996c4ee46
parentDon't include IncrementalRedsonteSimulator.inc when in SELF_TEST mode (diff)
downloadcuberite-26a4845a995065f0ed24ef0e21e4c9bf44cef002.tar
cuberite-26a4845a995065f0ed24ef0e21e4c9bf44cef002.tar.gz
cuberite-26a4845a995065f0ed24ef0e21e4c9bf44cef002.tar.bz2
cuberite-26a4845a995065f0ed24ef0e21e4c9bf44cef002.tar.lz
cuberite-26a4845a995065f0ed24ef0e21e4c9bf44cef002.tar.xz
cuberite-26a4845a995065f0ed24ef0e21e4c9bf44cef002.tar.zst
cuberite-26a4845a995065f0ed24ef0e21e4c9bf44cef002.zip
-rw-r--r--src/Chunk.h11
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.cpp11
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.h312
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.inc417
-rw-r--r--src/Simulator/RedstoneSimulator.h6
-rw-r--r--src/World.cpp2
6 files changed, 384 insertions, 375 deletions
diff --git a/src/Chunk.h b/src/Chunk.h
index 9a0e96513..4e8404595 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -417,11 +417,6 @@ public:
cSandSimulatorChunkData & GetSandSimulatorData (void) { return m_SandSimulatorData; }
cRedstoneSimulatorChunkData * GetRedstoneSimulatorData(void) { return &m_RedstoneSimulatorData; }
- cRedstoneSimulatorChunkData * GetRedstoneSimulatorQueuedData(void) { return &m_RedstoneSimulatorQueuedData; }
- cIncrementalRedstoneSimulator<cChunk, cWorld, GetHandlerCompileTime, cChestEntity>::PoweredBlocksList * GetRedstoneSimulatorPoweredBlocksList(void) { return &m_RedstoneSimulatorPoweredBlocksList; }
- cIncrementalRedstoneSimulator<cChunk, cWorld, GetHandlerCompileTime, cChestEntity>::LinkedBlocksList * GetRedstoneSimulatorLinkedBlocksList(void) { return &m_RedstoneSimulatorLinkedBlocksList; }
- cIncrementalRedstoneSimulator<cChunk, cWorld, GetHandlerCompileTime, cChestEntity>::SimulatedPlayerToggleableList * GetRedstoneSimulatorSimulatedPlayerToggleableList(void) { return &m_RedstoneSimulatorSimulatedPlayerToggleableList; }
- cIncrementalRedstoneSimulator<cChunk, cWorld, GetHandlerCompileTime, cChestEntity>::RepeatersDelayList * GetRedstoneSimulatorRepeatersDelayList(void) { return &m_RedstoneSimulatorRepeatersDelayList; }
bool IsRedstoneDirty(void) const { return m_IsRedstoneDirty; }
void SetIsRedstoneDirty(bool a_Flag) { m_IsRedstoneDirty = a_Flag; }
@@ -507,11 +502,7 @@ private:
cSandSimulatorChunkData m_SandSimulatorData;
cRedstoneSimulatorChunkData m_RedstoneSimulatorData;
- cRedstoneSimulatorChunkData m_RedstoneSimulatorQueuedData;
- cIncrementalRedstoneSimulator<cChunk, cWorld, GetHandlerCompileTime, cChestEntity>::PoweredBlocksList m_RedstoneSimulatorPoweredBlocksList;
- cIncrementalRedstoneSimulator<cChunk, cWorld, GetHandlerCompileTime, cChestEntity>::LinkedBlocksList m_RedstoneSimulatorLinkedBlocksList;
- cIncrementalRedstoneSimulator<cChunk, cWorld, GetHandlerCompileTime, cChestEntity>::SimulatedPlayerToggleableList m_RedstoneSimulatorSimulatedPlayerToggleableList;
- cIncrementalRedstoneSimulator<cChunk, cWorld, GetHandlerCompileTime, cChestEntity>::RepeatersDelayList m_RedstoneSimulatorRepeatersDelayList;
+
/** Indicates if simulate-once blocks should be updated by the redstone simulator */
bool m_IsRedstoneDirty;
diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp
index 515d72457..55cc014f3 100644
--- a/src/Simulator/IncrementalRedstoneSimulator.cpp
+++ b/src/Simulator/IncrementalRedstoneSimulator.cpp
@@ -1,9 +1,6 @@
#include "Globals.h"
-#ifndef SELF_TEST
-
-#include "IncrementalRedstoneSimulator.h"
#include "IncrementalRedstoneSimulator.inc"
@@ -18,6 +15,8 @@
#include "Blocks/BlockPiston.h"
#include "BlockEntities/ChestEntity.h"
-#pragma clang diagnostic ignored "-Wweak-template-vtables"
-template class cIncrementalRedstoneSimulator<cChunk, cWorld, GetHandlerCompileTime, cChestEntity>;
-#endif
+cRedstoneSimulator<cChunk, cWorld> * MakeIncrementalRedstoneSimulator(cWorld & a_World)
+{
+ return new cIncrementalRedstoneSimulator<cChunk, cWorld, GetHandlerCompileTime, cChestEntity>(a_World);
+}
+
diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h
index 0120a3208..5bd1ad95d 100644
--- a/src/Simulator/IncrementalRedstoneSimulator.h
+++ b/src/Simulator/IncrementalRedstoneSimulator.h
@@ -3,313 +3,7 @@
#include "RedstoneSimulator.h"
-/// Per-chunk data for the simulator, specified individual chunks to simulate
-typedef cCoordWithBlockAndBoolVector cRedstoneSimulatorChunkData;
-
-class cRedstonePoweredEntity;
-
-typedef cItemCallback<cRedstonePoweredEntity> cRedstonePoweredCallback;
-
-
-template<class ChunkType, class WorldType, template <BLOCKTYPE block> class GetHandlerCompileTime, class ChestType>
-class cIncrementalRedstoneSimulator :
- public cRedstoneSimulator<ChunkType, WorldType>
-{
- typedef cRedstoneSimulator<ChunkType, WorldType> super;
-public:
-
- cIncrementalRedstoneSimulator(WorldType & 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, ChunkType * a_Chunk) override;
- virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override { return IsRedstone(a_BlockType); }
- virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) override;
-
- 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:
-
- #define MAX_POWER_LEVEL 15
-
- 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
- unsigned char a_PowerLevel;
- };
-
- 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; // Position of block that is betwixt a source and the destination
- Vector3i a_SourcePos;
- unsigned char a_PowerLevel;
- };
-
- 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)
- {
- Vector3i a_RelBlockPos;
- bool WasLastStatePowered; // Was the last state powered or not? Determines whether a source update has happened and if I should resimulate
- };
-
- struct sRepeatersDelayList // Define structure of list containing repeaters' delay states
- {
- Vector3i a_RelBlockPos;
- 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?
- };
-
-public:
-
- typedef std::vector <sPoweredBlocks> PoweredBlocksList;
- typedef std::vector <sLinkedPoweredBlocks> LinkedBlocksList;
- typedef std::vector <sSimulatedPlayerToggleableList> SimulatedPlayerToggleableList;
- typedef std::vector <sRepeatersDelayList> RepeatersDelayList;
-
-private:
-
- cRedstoneSimulatorChunkData * m_RedstoneSimulatorChunkData;
- PoweredBlocksList * m_PoweredBlocks;
- LinkedBlocksList * m_LinkedPoweredBlocks;
- SimulatedPlayerToggleableList * m_SimulatedPlayerToggleableBlocks;
- RepeatersDelayList * m_RepeatersDelayList;
-
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) override { RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); }
- void RedstoneAddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk, ChunkType * a_OtherChunk = NULL);
- ChunkType * m_Chunk;
-
- // 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 */
- void HandleRedstoneTorch(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
- /** Handles the redstone block */
- void HandleRedstoneBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles levers */
- void HandleRedstoneLever(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles buttons */
- void HandleRedstoneButton(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles daylight sensors */
- void HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles pressure plates */
- void HandlePressurePlate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType);
- /** Handles tripwire hooks
- Performs correct meta and power setting for self by going in the direction it faces and looking for a continous line of tripwire bounded by another oppositely facing hook
- If this line is complete, it verifies that at least on wire reports an entity is on top (via its meta), and performs its task
- */
- void HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles trapped chests */
- void HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /* ==================== */
-
- /* ====== CARRIERS ====== */
- /** Handles redstone wire */
- void HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles repeaters */
- void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
- /* ====================== */
-
- /* ====== DEVICES ====== */
- /** Handles pistons */
- void HandlePiston(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles dispensers and droppers */
- void HandleDropSpenser(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles TNT (exploding) */
- void HandleTNT(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles redstone lamps */
- void HandleRedstoneLamp(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
- /** Handles doords */
- void HandleDoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles command blocks */
- void HandleCommandBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles activator, detector, and powered rails */
- void HandleRail(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType);
- /** Handles trapdoors */
- void HandleTrapdoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles fence gates */
- void HandleFenceGate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles noteblocks */
- void HandleNoteBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Handles tripwires */
- void HandleTripwire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /* ===================== */
-
- /* ====== Helper functions ====== */
- /** Marks a block as powered */
- 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);
- /** Marks a block as being powered through another block */
- 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);
- /** 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 */
- void SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool WasLastStatePowered);
- /** Marks the second block in a direction as linked powered */
- void SetDirectionLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, char a_Direction, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
- /** Marks all blocks immediately surrounding a coordinate as powered */
- void SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
- /** Queues a repeater to be powered or unpowered and returns if the m_RepeatersDelayList iterators were invalidated */
- bool QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
- /** Removes a block from the Powered and LinkedPowered lists
- Used for variable sources such as tripwire hooks, daylight sensors, and trapped chests
- */
- void SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, ChunkType * a_Chunk, bool a_IsFirstCall = true);
-
- /** Returns if a coordinate is powered or linked powered */
- bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }
- /** Returns if a coordinate is in the directly powered blocks list */
- bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, ChunkType * a_Chunk);
- /** Returns if a coordinate is in the indirectly powered blocks list */
- bool AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */
- bool AreCoordsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool IsCurrentStatePowered);
- /** Returns if a repeater is powered by testing for power sources behind the repeater */
- bool IsRepeaterPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
- /** Returns if a repeater is locked */
- bool IsRepeaterLocked(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
- /** Returns if a piston is powered */
- bool IsPistonPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
- /** Returns if a wire is powered
- The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire */
- bool IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel);
- /** Handles delayed updates to repeaters **/
- void HandleRedstoneRepeaterDelays(void);
-
- /** Returns if lever metadata marks it as emitting power */
- bool IsLeverOn(NIBBLETYPE a_BlockMeta);
- /** Returns if button metadata marks it as emitting power */
- bool IsButtonOn(NIBBLETYPE a_BlockMeta) { return IsLeverOn(a_BlockMeta); }
- /* ============================== */
-
- /* ====== Misc Functions ====== */
- /** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */
- inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { return cBlockInfo::FullyOccupiesVoxel(Block); }
-
- /** Returns if a block is a mechanism (something that accepts power and does something)
- Used by torches to determine if they power a block whilst not standing on the ground
- */
- 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:
- case E_BLOCK_REDSTONE_WIRE:
- {
- 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:
- 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:
- case E_BLOCK_TRAPPED_CHEST:
- {
- 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_TRAPPED_CHEST:
- case E_BLOCK_TRIPWIRE_HOOK:
- case E_BLOCK_TRIPWIRE:
- 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;
- }
- }
-
- inline static bool AreCoordsOnChunkBoundary(int a_BlockX, int a_BlockY, int a_BlockZ)
- {
- return ( // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks
- ((a_BlockX % cChunkDef::Width) <= 1) ||
- ((a_BlockX % cChunkDef::Width) >= 14) ||
- ((a_BlockZ % cChunkDef::Width) <= 1) ||
- ((a_BlockZ % cChunkDef::Width) >= 14)
- );
- }
-};
+class cWorld;
+class cChunk;
+cRedstoneSimulator<cChunk, cWorld> * MakeIncrementalRedstoneSimulator(cWorld & a_World);
diff --git a/src/Simulator/IncrementalRedstoneSimulator.inc b/src/Simulator/IncrementalRedstoneSimulator.inc
index 6d1f7b0ae..e3c856328 100644
--- a/src/Simulator/IncrementalRedstoneSimulator.inc
+++ b/src/Simulator/IncrementalRedstoneSimulator.inc
@@ -3,20 +3,334 @@
#include "BoundingBox.h"
#include "BlockEntities/RedstonePoweredEntity.h"
#include "Blocks/ChunkInterface.h"
+#include "RedstoneSimulator.h"
+
+
+
+typedef cItemCallback<cRedstonePoweredEntity> cRedstonePoweredCallback;
+
+
template<class ChunkType, class WorldType, template <BLOCKTYPE block> class GetHandlerCompileTime, class ChestType>
-cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulator(WorldType & a_World) :
- super(a_World),
- m_RedstoneSimulatorChunkData(),
- m_PoweredBlocks(),
- m_LinkedPoweredBlocks(),
- m_SimulatedPlayerToggleableBlocks(),
- m_RepeatersDelayList(),
- m_Chunk()
+class cIncrementalRedstoneSimulator :
+ public cRedstoneSimulator<ChunkType, WorldType>
{
-}
+ typedef cRedstoneSimulator<ChunkType, WorldType> super;
+public:
+
+ cIncrementalRedstoneSimulator(WorldType & a_World)
+ : cRedstoneSimulator<ChunkType, WorldType>(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, ChunkType * a_Chunk) override;
+ virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override { return IsRedstone(a_BlockType); }
+ virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) override;
+
+ 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:
+
+ #define MAX_POWER_LEVEL 15
+
+ 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
+ unsigned char a_PowerLevel;
+ };
+
+ 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; // Position of block that is betwixt a source and the destination
+ Vector3i a_SourcePos;
+ unsigned char a_PowerLevel;
+ };
+
+ 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)
+ {
+ Vector3i a_RelBlockPos;
+ bool WasLastStatePowered; // Was the last state powered or not? Determines whether a source update has happened and if I should resimulate
+ };
+
+ struct sRepeatersDelayList // Define structure of list containing repeaters' delay states
+ {
+ Vector3i a_RelBlockPos;
+ 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?
+ };
+
+ class cIncrementalRedstoneSimulatorChunkData :
+ cRedstoneSimulatorChunkData
+ {
+ public:
+ /// Per-chunk data for the simulator, specified individual chunks to simulate
+ cCoordWithBlockAndBoolVector m_ChunkData;
+ cCoordWithBlockAndBoolVector m_QueuedChunkData;
+ std::vector<sPoweredBlocks> m_PoweredBlocks;
+ std::vector<sLinkedPoweredBlocks> m_LinkedBlocks;
+ std::vector<sSimulatedPlayerToggleableList> m_SimulatedPlayerToggleableBlocks;
+ std::vector<sRepeatersDelayList> m_RepeatersDelayList;
+ };
+
+public:
+
+ typedef std::vector <sPoweredBlocks> PoweredBlocksList;
+ typedef std::vector <sLinkedPoweredBlocks> LinkedBlocksList;
+ typedef std::vector <sSimulatedPlayerToggleableList> SimulatedPlayerToggleableList;
+ typedef std::vector <sRepeatersDelayList> RepeatersDelayList;
+
+private:
+
+ cIncrementalRedstoneSimulatorChunkData * m_RedstoneSimulatorChunkData;
+ PoweredBlocksList * m_PoweredBlocks;
+ LinkedBlocksList * m_LinkedPoweredBlocks;
+ SimulatedPlayerToggleableList * m_SimulatedPlayerToggleableBlocks;
+ RepeatersDelayList * m_RepeatersDelayList;
+
+ virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk) override { RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); }
+ void RedstoneAddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, ChunkType * a_Chunk, ChunkType * a_OtherChunk = NULL);
+ ChunkType * m_Chunk;
+
+ // 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 */
+ void HandleRedstoneTorch(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
+ /** Handles the redstone block */
+ void HandleRedstoneBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles levers */
+ void HandleRedstoneLever(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles buttons */
+ void HandleRedstoneButton(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles daylight sensors */
+ void HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles pressure plates */
+ void HandlePressurePlate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType);
+ /** Handles tripwire hooks
+ Performs correct meta and power setting for self by going in the direction it faces and looking for a continous line of tripwire bounded by another oppositely facing hook
+ If this line is complete, it verifies that at least on wire reports an entity is on top (via its meta), and performs its task
+ */
+ void HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles trapped chests */
+ void HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /* ==================== */
+
+ /* ====== CARRIERS ====== */
+ /** Handles redstone wire */
+ void HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles repeaters */
+ void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
+ /* ====================== */
+
+ /* ====== DEVICES ====== */
+ /** Handles pistons */
+ void HandlePiston(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles dispensers and droppers */
+ void HandleDropSpenser(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles TNT (exploding) */
+ void HandleTNT(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles redstone lamps */
+ void HandleRedstoneLamp(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
+ /** Handles doords */
+ void HandleDoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles command blocks */
+ void HandleCommandBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles activator, detector, and powered rails */
+ void HandleRail(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType);
+ /** Handles trapdoors */
+ void HandleTrapdoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles fence gates */
+ void HandleFenceGate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles noteblocks */
+ void HandleNoteBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles tripwires */
+ void HandleTripwire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /* ===================== */
+
+ /* ====== Helper functions ====== */
+ /** Marks a block as powered */
+ 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);
+ /** Marks a block as being powered through another block */
+ 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);
+ /** 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 */
+ void SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool WasLastStatePowered);
+ /** Marks the second block in a direction as linked powered */
+ void SetDirectionLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, char a_Direction, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
+ /** Marks all blocks immediately surrounding a coordinate as powered */
+ void SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
+ /** Queues a repeater to be powered or unpowered and returns if the m_RepeatersDelayList iterators were invalidated */
+ bool QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
+ /** Removes a block from the Powered and LinkedPowered lists
+ Used for variable sources such as tripwire hooks, daylight sensors, and trapped chests
+ */
+ void SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, ChunkType * a_Chunk, bool a_IsFirstCall = true);
+
+ /** Returns if a coordinate is powered or linked powered */
+ bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }
+ /** Returns if a coordinate is in the directly powered blocks list */
+ bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, ChunkType * a_Chunk);
+ /** Returns if a coordinate is in the indirectly powered blocks list */
+ bool AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */
+ bool AreCoordsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool IsCurrentStatePowered);
+ /** Returns if a repeater is powered by testing for power sources behind the repeater */
+ bool IsRepeaterPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
+ /** Returns if a repeater is locked */
+ bool IsRepeaterLocked(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
+ /** Returns if a piston is powered */
+ bool IsPistonPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
+ /** Returns if a wire is powered
+ The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire */
+ bool IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel);
+ /** Handles delayed updates to repeaters **/
+ void HandleRedstoneRepeaterDelays(void);
+
+ /** Returns if lever metadata marks it as emitting power */
+ bool IsLeverOn(NIBBLETYPE a_BlockMeta);
+ /** Returns if button metadata marks it as emitting power */
+ bool IsButtonOn(NIBBLETYPE a_BlockMeta) { return IsLeverOn(a_BlockMeta); }
+ /* ============================== */
+
+ /* ====== Misc Functions ====== */
+ /** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */
+ inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { return cBlockInfo::FullyOccupiesVoxel(Block); }
+
+ /** Returns if a block is a mechanism (something that accepts power and does something)
+ Used by torches to determine if they power a block whilst not standing on the ground
+ */
+ 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:
+ case E_BLOCK_REDSTONE_WIRE:
+ {
+ 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:
+ 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:
+ case E_BLOCK_TRAPPED_CHEST:
+ {
+ 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_TRAPPED_CHEST:
+ case E_BLOCK_TRIPWIRE_HOOK:
+ case E_BLOCK_TRIPWIRE:
+ 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;
+ }
+ }
+
+ inline static bool AreCoordsOnChunkBoundary(int a_BlockX, int a_BlockY, int a_BlockZ)
+ {
+ return ( // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks
+ ((a_BlockX % cChunkDef::Width) <= 1) ||
+ ((a_BlockX % cChunkDef::Width) >= 14) ||
+ ((a_BlockZ % cChunkDef::Width) <= 1) ||
+ ((a_BlockZ % cChunkDef::Width) >= 14)
+ );
+ }
+};
+
@@ -70,8 +384,8 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
// 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
- PoweredBlocksList * PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList();
- for (typename PoweredBlocksList::iterator itr = PoweredBlocks->begin(); itr != PoweredBlocks->end();)
+ PoweredBlocksList & PoweredBlocks = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks;
+ for (typename PoweredBlocksList::iterator itr = PoweredBlocks.begin(); itr != PoweredBlocks.end();)
{
if (!itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
{
@@ -82,7 +396,7 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
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);
- itr = PoweredBlocks->erase(itr);
+ itr = PoweredBlocks.erase(itr);
continue;
}
else if (
@@ -95,22 +409,22 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
)
{
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);
- itr = PoweredBlocks->erase(itr);
+ itr = PoweredBlocks.erase(itr);
continue;
}
++itr;
}
- LinkedBlocksList * LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList();
+ LinkedBlocksList & LinkedPoweredBlocks = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_LinkedBlocks;
// 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 (typename LinkedBlocksList::iterator itr = LinkedPoweredBlocks->begin(); itr != LinkedPoweredBlocks->end();)
+ for (typename LinkedBlocksList::iterator itr = LinkedPoweredBlocks.begin(); itr != LinkedPoweredBlocks.end();)
{
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);
- itr = LinkedPoweredBlocks->erase(itr);
+ itr = LinkedPoweredBlocks.erase(itr);
continue;
}
else if (
@@ -121,7 +435,7 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
)
{
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);
- itr = LinkedPoweredBlocks->erase(itr);
+ itr = LinkedPoweredBlocks.erase(itr);
continue;
}
}
@@ -130,15 +444,15 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
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);
- itr = LinkedPoweredBlocks->erase(itr);
+ itr = LinkedPoweredBlocks.erase(itr);
continue;
}
}
++itr;
}
- SimulatedPlayerToggleableList * SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList();
- for (typename SimulatedPlayerToggleableList::iterator itr = SimulatedPlayerToggleableBlocks->begin(); itr != SimulatedPlayerToggleableBlocks->end(); ++itr)
+ SimulatedPlayerToggleableList & SimulatedPlayerToggleableBlocks = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_SimulatedPlayerToggleableBlocks;
+ for (typename SimulatedPlayerToggleableList::iterator itr = SimulatedPlayerToggleableBlocks.begin(); itr != SimulatedPlayerToggleableBlocks.end(); ++itr)
{
if (!itr->a_RelBlockPos.Equals(Vector3i(RelX, a_BlockY, RelZ)))
{
@@ -148,13 +462,13 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
if (!IsAllowedBlock(Block))
{
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);
- SimulatedPlayerToggleableBlocks->erase(itr);
+ SimulatedPlayerToggleableBlocks.erase(itr);
break;
}
}
- RepeatersDelayList * RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList();
- for (typename RepeatersDelayList::iterator itr = RepeatersDelayList->begin(); itr != RepeatersDelayList->end(); ++itr)
+ RepeatersDelayList & RepeatersDelayList = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_RepeatersDelayList;
+ for (typename RepeatersDelayList::iterator itr = RepeatersDelayList.begin(); itr != RepeatersDelayList.end(); ++itr)
{
if (!itr->a_RelBlockPos.Equals(Vector3i(RelX, a_BlockY, RelZ)))
{
@@ -163,7 +477,7 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF))
{
- RepeatersDelayList->erase(itr);
+ RepeatersDelayList.erase(itr);
break;
}
}
@@ -174,8 +488,8 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
return;
}
- cRedstoneSimulatorChunkData * RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData();
- for (cRedstoneSimulatorChunkData::iterator itr = RedstoneSimulatorChunkData->begin(); itr != RedstoneSimulatorChunkData->end(); ++itr)
+ cCoordWithBlockAndBoolVector & RedstoneSimulatorChunkData = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_ChunkData;
+ for (cCoordWithBlockAndBoolVector::iterator itr = RedstoneSimulatorChunkData.begin(); itr != RedstoneSimulatorChunkData.end(); ++itr)
{
if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) // We are at an entry matching the current (changed) block
{
@@ -197,7 +511,8 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
return;
}
- for (cRedstoneSimulatorChunkData::iterator itr = a_Chunk->GetRedstoneSimulatorQueuedData()->begin(); itr != a_Chunk->GetRedstoneSimulatorQueuedData()->end(); ++itr)
+ cCoordWithBlockAndBoolVector & QueuedData = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_QueuedChunkData;
+ for (cCoordWithBlockAndBoolVector::iterator itr = QueuedData.begin(); itr != QueuedData.end(); ++itr)
{
if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ))
{
@@ -205,7 +520,7 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
return;
}
}
- a_Chunk->GetRedstoneSimulatorQueuedData()->push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false));
+ QueuedData.push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false));
}
@@ -214,19 +529,23 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
template <class ChunkType, class WorldType, template <BLOCKTYPE block> class GetHandlerCompileTime, class ChestType>
void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, ChunkType * a_Chunk)
{
- m_RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData();
- if (m_RedstoneSimulatorChunkData->empty() && a_Chunk->GetRedstoneSimulatorQueuedData()->empty())
+ m_RedstoneSimulatorChunkData = (cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData();
+ if (m_RedstoneSimulatorChunkData->m_ChunkData.empty() && ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_QueuedChunkData.empty())
{
return;
}
- m_RedstoneSimulatorChunkData->insert(m_RedstoneSimulatorChunkData->end(), a_Chunk->GetRedstoneSimulatorQueuedData()->begin(), a_Chunk->GetRedstoneSimulatorQueuedData()->end());
- a_Chunk->GetRedstoneSimulatorQueuedData()->clear();
+ m_RedstoneSimulatorChunkData->m_ChunkData.insert(
+ m_RedstoneSimulatorChunkData->m_ChunkData.end(),
+ m_RedstoneSimulatorChunkData ->m_QueuedChunkData.begin(),
+ m_RedstoneSimulatorChunkData ->m_QueuedChunkData.end());
+
+ m_RedstoneSimulatorChunkData->m_QueuedChunkData.clear();
- m_PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList();
- m_RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList();
- m_SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList();
- m_LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList();
+ m_PoweredBlocks = &m_RedstoneSimulatorChunkData->m_PoweredBlocks;
+ m_RepeatersDelayList = &m_RedstoneSimulatorChunkData->m_RepeatersDelayList;
+ m_SimulatedPlayerToggleableBlocks = &m_RedstoneSimulatorChunkData->m_SimulatedPlayerToggleableBlocks;
+ m_LinkedPoweredBlocks = &m_RedstoneSimulatorChunkData->m_LinkedBlocks;
m_Chunk = a_Chunk;
bool ShouldUpdateSimulateOnceBlocks = false;
@@ -240,11 +559,11 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
HandleRedstoneRepeaterDelays();
- for (cRedstoneSimulatorChunkData::iterator dataitr = m_RedstoneSimulatorChunkData->begin(); dataitr != m_RedstoneSimulatorChunkData->end();)
+ for (cCoordWithBlockAndBoolVector::iterator dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.begin(); dataitr != m_RedstoneSimulatorChunkData->m_ChunkData.end();)
{
if (dataitr->DataTwo)
{
- dataitr = m_RedstoneSimulatorChunkData->erase(dataitr);
+ dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.erase(dataitr);
continue;
}
@@ -1497,7 +1816,7 @@ bool cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
- for (typename PoweredBlocksList::const_iterator itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end(); ++itr) // Check powered list
+ for (typename PoweredBlocksList::const_iterator itr = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks.begin(); itr != ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks.end(); ++itr) // Check powered list
{
if (itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)))
{
@@ -1904,8 +2223,8 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
return;
}
- PoweredBlocksList * Powered = Neighbour->GetRedstoneSimulatorPoweredBlocksList(); // We need to insert the value into the chunk who owns the block position
- for (typename PoweredBlocksList::iterator itr = Powered->begin(); itr != Powered->end(); ++itr)
+ PoweredBlocksList & Powered = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position
+ for (typename PoweredBlocksList::iterator itr = Powered.begin(); itr != Powered.end(); ++itr)
{
if (
itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) &&
@@ -1952,7 +2271,7 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
RC.a_BlockPos = Vector3i(BlockX, a_RelBlockY, BlockZ);
RC.a_SourcePos = Vector3i(SourceX, a_RelSourceY, SourceZ);
RC.a_PowerLevel = a_PowerLevel;
- Powered->push_back(RC);
+ Powered.push_back(RC);
Neighbour->SetIsRedstoneDirty(true);
m_Chunk->SetIsRedstoneDirty(true);
}
@@ -1986,8 +2305,8 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
return;
}
- LinkedBlocksList * Linked = Neighbour->GetRedstoneSimulatorLinkedBlocksList();
- for (typename LinkedBlocksList::iterator itr = Linked->begin(); itr != Linked->end(); ++itr) // Check linked powered list
+ LinkedBlocksList & Linked = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_LinkedBlocks;
+ for (typename LinkedBlocksList::iterator itr = Linked.begin(); itr != Linked.end(); ++itr) // Check linked powered list
{
if (
itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) &&
@@ -2006,7 +2325,7 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
RC.a_MiddlePos = Vector3i(MiddleX, a_RelMiddleY, MiddleZ);
RC.a_SourcePos = Vector3i(SourceX, a_RelSourceY, SourceZ);
RC.a_PowerLevel = a_PowerLevel;
- Linked->push_back(RC);
+ Linked.push_back(RC);
Neighbour->SetIsRedstoneDirty(true);
m_Chunk->SetIsRedstoneDirty(true);
}
@@ -2096,21 +2415,21 @@ void cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime,
}
// TODO: on C++11 support, change both of these to llama functions pased to a std::remove_if
- for (typename PoweredBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end();)
+ for (typename PoweredBlocksList::iterator itr = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks.begin(); itr != ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks.end();)
{
if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)))
{
- itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->erase(itr);
+ itr = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks.erase(itr);
a_Chunk->SetIsRedstoneDirty(true);
continue;
}
++itr;
}
- for (typename LinkedBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->end();)
+ for (typename LinkedBlocksList::iterator itr = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_LinkedBlocks.begin(); itr != ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_LinkedBlocks.end();)
{
if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)))
{
- itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->erase(itr);
+ itr = ((cIncrementalRedstoneSimulator<ChunkType, WorldType, GetHandlerCompileTime, ChestType>::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_LinkedBlocks.erase(itr);
a_Chunk->SetIsRedstoneDirty(true);
continue;
}
diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h
index 56843e37f..0e3dd495d 100644
--- a/src/Simulator/RedstoneSimulator.h
+++ b/src/Simulator/RedstoneSimulator.h
@@ -4,6 +4,12 @@
#include "Simulator.h"
+class cRedstoneSimulatorChunkData
+{
+public:
+ virtual ~cRedstoneSimulatorChunkData() {}
+} ;
+
template <class ChunkType, class WorldType>
class cRedstoneSimulator :
diff --git a/src/World.cpp b/src/World.cpp
index 732c9f14c..ded42f093 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -3272,7 +3272,7 @@ cRedstoneSimulator<cChunk, cWorld> * cWorld::InitializeRedstoneSimulator(cIniFil
if (NoCaseCompare(SimulatorName, "Incremental") == 0)
{
- res = new cIncrementalRedstoneSimulator<cChunk, cWorld, GetHandlerCompileTime, cChestEntity>(*this);
+ res = MakeIncrementalRedstoneSimulator(*this);
}
else if (NoCaseCompare(SimulatorName, "noop") == 0)
{