diff options
author | Tycho <work.tycho+git@gmail.com> | 2014-09-16 21:29:31 +0200 |
---|---|---|
committer | Tycho <work.tycho+git@gmail.com> | 2014-09-16 21:29:31 +0200 |
commit | 26a4845a995065f0ed24ef0e21e4c9bf44cef002 (patch) | |
tree | 56037a87d24a4162698fca4d7180b0c996c4ee46 /src/Simulator/IncrementalRedstoneSimulator.inc | |
parent | Don't include IncrementalRedsonteSimulator.inc when in SELF_TEST mode (diff) | |
download | cuberite-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 |
Diffstat (limited to 'src/Simulator/IncrementalRedstoneSimulator.inc')
-rw-r--r-- | src/Simulator/IncrementalRedstoneSimulator.inc | 417 |
1 files changed, 368 insertions, 49 deletions
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; } |