diff options
author | Tiger Wang <ziwei.tiger@hotmail.co.uk> | 2015-06-02 14:29:52 +0200 |
---|---|---|
committer | Tiger Wang <ziwei.tiger@hotmail.co.uk> | 2015-06-06 13:21:21 +0200 |
commit | 171c59a01b07b7513cf7a281bbcb141e8182d274 (patch) | |
tree | 6fd4b835b68b2dcde80a3f868d0b83f2987d2a54 /src | |
parent | Improved link power behaviour (diff) | |
download | cuberite-171c59a01b07b7513cf7a281bbcb141e8182d274.tar cuberite-171c59a01b07b7513cf7a281bbcb141e8182d274.tar.gz cuberite-171c59a01b07b7513cf7a281bbcb141e8182d274.tar.bz2 cuberite-171c59a01b07b7513cf7a281bbcb141e8182d274.tar.lz cuberite-171c59a01b07b7513cf7a281bbcb141e8182d274.tar.xz cuberite-171c59a01b07b7513cf7a281bbcb141e8182d274.tar.zst cuberite-171c59a01b07b7513cf7a281bbcb141e8182d274.zip |
Diffstat (limited to 'src')
-rw-r--r-- | src/ChunkDef.h | 29 | ||||
-rw-r--r-- | src/Mobs/Path.h | 17 | ||||
-rw-r--r-- | src/Simulator/IncrementalRedstoneSimulator.cpp | 212 | ||||
-rw-r--r-- | src/Simulator/IncrementalRedstoneSimulator.h | 31 | ||||
-rw-r--r-- | src/Vector3.h | 6 |
5 files changed, 92 insertions, 203 deletions
diff --git a/src/ChunkDef.h b/src/ChunkDef.h index a1273bd23..57c4e6918 100644 --- a/src/ChunkDef.h +++ b/src/ChunkDef.h @@ -514,32 +514,3 @@ typedef cCoordWithData<BLOCKTYPE> cCoordWithBlock; typedef std::list<cCoordWithInt> cCoordWithIntList; typedef std::vector<cCoordWithInt> cCoordWithIntVector; - - - - - -/** Generic template that can store two types of any kind of data together with a triplet of 3 coords */ -template <typename X, typename Z> class cCoordWithDoubleData -{ -public: - int x; - int y; - int z; - X Data; - Z DataTwo; - - cCoordWithDoubleData(int a_X, int a_Y, int a_Z) : - x(a_X), y(a_Y), z(a_Z) - { - } - - cCoordWithDoubleData(int a_X, int a_Y, int a_Z, const X & a_Data, const Z & a_DataTwo) : - x(a_X), y(a_Y), z(a_Z), Data(a_Data), DataTwo(a_DataTwo) - { - } -}; - -typedef cCoordWithDoubleData <BLOCKTYPE, bool> cCoordWithBlockAndBool; - -typedef std::vector<cCoordWithBlockAndBool> cCoordWithBlockAndBoolVector; diff --git a/src/Mobs/Path.h b/src/Mobs/Path.h index c250eece2..491165795 100644 --- a/src/Mobs/Path.h +++ b/src/Mobs/Path.h @@ -124,21 +124,6 @@ public: return m_PathPoints.size(); } - struct VectorHasher - { - std::size_t operator()(const Vector3i & a_Vector) const - { - // Guaranteed to have no hash collisions for any 128x128x128 area. Suitable for pathfinding. - int32_t t = 0; - t += static_cast<int8_t>(a_Vector.x); - t = t << 8; - t += static_cast<int8_t>(a_Vector.y); - t = t << 8; - t += static_cast<int8_t>(a_Vector.z); - t = t << 8; - return static_cast<size_t>(t); - } - }; private: /* General */ @@ -160,7 +145,7 @@ private: /* Pathfinding fields */ std::priority_queue<cPathCell *, std::vector<cPathCell *>, compareHeuristics> m_OpenList; - std::unordered_map<Vector3i, cPathCell, VectorHasher> m_Map; + std::unordered_map<Vector3i, cPathCell, Vector3i> m_Map; Vector3i m_Destination; Vector3i m_Source; int m_BoundingBoxWidth; diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 29ea65407..f60106fac 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -92,67 +92,45 @@ void cIncrementalRedstoneSimulator::AddBlock(const Vector3i & a_RelBlockPosition } auto & SimulatedPlayerToggleableBlocks = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_SimulatedPlayerToggleableBlocks; - if ( - DoesIgnorePlayerToggle(Block) && - std::find_if(SimulatedPlayerToggleableBlocks.begin(), SimulatedPlayerToggleableBlocks.end(), - [a_RelBlockPosition](const sSimulatedPlayerToggleableList & itr){ return itr.a_RelBlockPos == a_RelBlockPosition; }) == SimulatedPlayerToggleableBlocks.end() - ) + if (DoesIgnorePlayerToggle(Block)) { - // We have arrived here; no block must be in list - add one - sSimulatedPlayerToggleableList RC; - RC.a_RelBlockPos = a_RelBlockPosition; - RC.WasLastStatePowered = AreCoordsDirectlyPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk) || AreCoordsLinkedPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk); - // Initialise the toggleable blocks list so that trapdoors etc. aren't reset on restart (#1887) - SimulatedPlayerToggleableBlocks.emplace_back(RC); + SimulatedPlayerToggleableBlocks.emplace( + a_RelBlockPosition, + AreCoordsDirectlyPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk) || AreCoordsLinkedPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk) + ); // This map won't insert if key already present, so no need to check + } + else + { + SimulatedPlayerToggleableBlocks.erase(a_RelBlockPosition); } - SimulatedPlayerToggleableBlocks.erase(std::remove_if(SimulatedPlayerToggleableBlocks.begin(), SimulatedPlayerToggleableBlocks.end(), [a_RelBlockPosition, Block, this](const sSimulatedPlayerToggleableList & itr) - { - return (itr.a_RelBlockPos == a_RelBlockPosition) && !DoesIgnorePlayerToggle(Block); - } - ), SimulatedPlayerToggleableBlocks.end()); - - auto & RepeatersDelayList = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_RepeatersDelayList; - RepeatersDelayList.erase(std::remove_if(RepeatersDelayList.begin(), RepeatersDelayList.end(), [a_RelBlockPosition, Block](const sRepeatersDelayList & itr) - { - return (itr.a_RelBlockPos == a_RelBlockPosition) && (Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF); - } - ), RepeatersDelayList.end()); - - auto & RedstoneSimulatorChunkData = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_ChunkData; - for (auto & itr : RedstoneSimulatorChunkData) + if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF)) { - if (a_RelBlockPosition == Vector3i(itr.x, itr.y, itr.z)) // We are at an entry matching the current (changed) block - { - if (!IsAllowedBlock(Block)) - { - itr.DataTwo = true; // The new blocktype is not redstone; it must be queued to be removed from this list - } - else - { - itr.DataTwo = false; - itr.Data = Block; // Update block information - } - return; - } + static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_RepeatersDelayList.erase(a_RelBlockPosition); } + auto & RedstoneSimulatorChunkData = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_ChunkData; + auto Iterator = RedstoneSimulatorChunkData.find(a_RelBlockPosition); if (!IsAllowedBlock(Block)) { + if (Iterator != RedstoneSimulatorChunkData.end()) + { + Iterator->second.second = true; // The new blocktype is not redstone; it must be queued to be removed from this list + } return; } - - auto & QueuedData = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_QueuedChunkData; - for (const auto & itr : QueuedData) + else { - if (a_RelBlockPosition == Vector3i(itr.x, itr.y, itr.z)) + if (Iterator != RedstoneSimulatorChunkData.end()) { - // Can't have duplicates in here either, in case something adds the block again before the structure can written to the main chunk data + Iterator->second.second = false; + Iterator->second.first = Block; // Update block information return; } } - QueuedData.emplace_back(cCoordWithBlockAndBool(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, Block, false)); + + RedstoneSimulatorChunkData.emplace(a_RelBlockPosition, std::make_pair(Block, false)); } @@ -167,19 +145,11 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt m_RedstoneSimulatorChunkData = new cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData(); a_Chunk->SetRedstoneSimulatorData(m_RedstoneSimulatorChunkData); } - if (m_RedstoneSimulatorChunkData->m_ChunkData.empty() && static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk->GetRedstoneSimulatorData())->m_QueuedChunkData.empty()) + if (m_RedstoneSimulatorChunkData->m_ChunkData.empty()) { return; } - 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 = &m_RedstoneSimulatorChunkData->m_PoweredBlocks; m_RepeatersDelayList = &m_RedstoneSimulatorChunkData->m_RepeatersDelayList; m_SimulatedPlayerToggleableBlocks = &m_RedstoneSimulatorChunkData->m_SimulatedPlayerToggleableBlocks; @@ -199,24 +169,24 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt for (auto dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.begin(); dataitr != m_RedstoneSimulatorChunkData->m_ChunkData.end();) { - if (dataitr->DataTwo) + if (dataitr->second.second) { dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.erase(dataitr); continue; } - switch (dataitr->Data) + switch (dataitr->second.first) { - case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRIPWIRE: HandleTripwire(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRIPWIRE_HOOK: HandleTripwireHook(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_TRIPWIRE: HandleTripwire(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_TRIPWIRE_HOOK: HandleTripwireHook(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; case E_BLOCK_WOODEN_PRESSURE_PLATE: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: { - HandlePressurePlate(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + HandlePressurePlate(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first); break; } default: break; @@ -224,23 +194,23 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt if (ShouldUpdateSimulateOnceBlocks) { - switch (dataitr->Data) + switch (dataitr->second.first) { - case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_IRON_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_TNT: HandleTNT(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_IRON_TRAPDOOR: HandleTrapdoor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_POWERED_RAIL: { - HandleRail(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + HandleRail(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first); break; } case E_BLOCK_ACACIA_DOOR: @@ -251,7 +221,7 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt case E_BLOCK_WOODEN_DOOR: case E_BLOCK_IRON_DOOR: { - HandleDoor(dataitr->x, dataitr->y, dataitr->z); + HandleDoor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; } case E_BLOCK_ACACIA_FENCE_GATE: @@ -261,49 +231,49 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt case E_BLOCK_JUNGLE_FENCE_GATE: case E_BLOCK_SPRUCE_FENCE_GATE: { - HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); + HandleFenceGate(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; } case E_BLOCK_REDSTONE_LAMP_OFF: case E_BLOCK_REDSTONE_LAMP_ON: { - HandleRedstoneLamp(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + HandleRedstoneLamp(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first); break; } case E_BLOCK_DISPENSER: case E_BLOCK_DROPPER: { - HandleDropSpenser(dataitr->x, dataitr->y, dataitr->z); + HandleDropSpenser(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; } case E_BLOCK_PISTON: case E_BLOCK_STICKY_PISTON: { - HandlePiston(dataitr->x, dataitr->y, dataitr->z); + HandlePiston(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; } case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: { - HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + HandleRedstoneRepeater(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first); break; } case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: { - HandleRedstoneTorch(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + HandleRedstoneTorch(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first); break; } case E_BLOCK_STONE_BUTTON: case E_BLOCK_WOODEN_BUTTON: { - HandleRedstoneButton(dataitr->x, dataitr->y, dataitr->z); + HandleRedstoneButton(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; } case E_BLOCK_ACTIVE_COMPARATOR: case E_BLOCK_INACTIVE_COMPARATOR: { - HandleRedstoneComparator(dataitr->x, dataitr->y, dataitr->z); + HandleRedstoneComparator(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; } default: break; @@ -872,32 +842,29 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays() { for (auto itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end();) { - if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks? + if (itr->second.a_ElapsedTicks >= itr->second.a_DelayTicks) // Has the elapsed ticks reached the target ticks? { - int RelBlockX = itr->a_RelBlockPos.x; - int RelBlockY = itr->a_RelBlockPos.y; - int RelBlockZ = itr->a_RelBlockPos.z; BLOCKTYPE Block; NIBBLETYPE Meta; - m_Chunk->GetBlockTypeMeta(RelBlockX, RelBlockY, RelBlockZ, Block, Meta); - if (itr->ShouldPowerOn) + m_Chunk->GetBlockTypeMeta(itr->first.x, itr->first.y, itr->first.z, Block, Meta); + if (itr->second.ShouldPowerOn) { if (Block != E_BLOCK_REDSTONE_REPEATER_ON) // For performance { - m_Chunk->SetBlock(itr->a_RelBlockPos, E_BLOCK_REDSTONE_REPEATER_ON, Meta); + m_Chunk->SetBlock(itr->first, E_BLOCK_REDSTONE_REPEATER_ON, Meta); } } else if (Block != E_BLOCK_REDSTONE_REPEATER_OFF) { - m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta); + m_Chunk->SetBlock(itr->first.x, itr->first.y, itr->first.z, E_BLOCK_REDSTONE_REPEATER_OFF, Meta); } itr = m_RepeatersDelayList->erase(itr); } else { - LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->a_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks); - itr->a_ElapsedTicks++; - itr++; + LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->first.x, itr->first.y, itr->first.z, itr->second.a_ElapsedTicks, itr->second.a_DelayTicks); + itr->second.a_ElapsedTicks++; + ++itr; } } } @@ -1871,9 +1838,9 @@ bool cIncrementalRedstoneSimulator::AreCoordsSimulated(int a_RelBlockX, int a_Re { for (const auto & itr : *m_SimulatedPlayerToggleableBlocks) { - if (itr.a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) + if (itr.first.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) { - if (itr.WasLastStatePowered != IsCurrentStatePowered) // Was the last power state different to the current? + if (itr.second != IsCurrentStatePowered) // Was the last power state different to the current? { return false; // It was, coordinates are no longer simulated } @@ -2116,60 +2083,37 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool a_WasLastStatePowered) { - for (auto & itr : *m_SimulatedPlayerToggleableBlocks) - { - if (!itr.a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) - { - continue; - } - - // Update listing - itr.WasLastStatePowered = a_WasLastStatePowered; - return; - } - - // We have arrived here; no block must be in list - add one - sSimulatedPlayerToggleableList RC; - RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - RC.WasLastStatePowered = a_WasLastStatePowered; - m_SimulatedPlayerToggleableBlocks->emplace_back(RC); + m_SimulatedPlayerToggleableBlocks->operator[](Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) = a_WasLastStatePowered; } -bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn) +void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool a_ShouldPowerOn) { - for (auto itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr) - { - if (itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) - { - if (ShouldPowerOn == itr->ShouldPowerOn) // We are queued already for the same thing, don't replace entry - { - return false; - } - - // Already in here (normal to allow repeater to continue on powering and updating blocks in front) - just update info and quit - itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; // See below for description - itr->a_ElapsedTicks = 0; - itr->ShouldPowerOn = ShouldPowerOn; - return false; - } - } - - // Self not in list, add self to list sRepeatersDelayList RC; - RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); // Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.) // Multiply by 2 because in MCS, 1 redstone tick = 1 world tick, but in Vanilla, 1 redstone tick = 2 world ticks, and we need to maintain compatibility RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; - RC.a_ElapsedTicks = 0; - RC.ShouldPowerOn = ShouldPowerOn; - m_RepeatersDelayList->emplace_back(RC); - return true; + RC.ShouldPowerOn = a_ShouldPowerOn; + + auto Result = m_RepeatersDelayList->emplace(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), RC); + if (!Result.second) + { + // Key exists + if (a_ShouldPowerOn == Result.first->second.ShouldPowerOn) + { + // We are queued already for the same thing, don't replace entry + return; + } + + Result.first->second.a_DelayTicks = RC.a_DelayTicks; + Result.first->second.a_ElapsedTicks = 0; + Result.first->second.ShouldPowerOn = a_ShouldPowerOn; + } } diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index 934a0eab9..c4be70e97 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -3,7 +3,7 @@ #include "RedstoneSimulator.h" #include "BlockEntities/RedstonePoweredEntity.h" -#include <bitset> +#include <unordered_map> class cWorld; class cChunk; @@ -38,15 +38,6 @@ public: virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override { return IsRedstone(a_BlockType); } virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override; - enum eRedstoneWireDirectionBitfieldPositions - { - eWbpXP = 0, - eWbpXN = 1, - eWbpZP = 2, - eWbpZN = 3, - }; - std::bitset<4> GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ); - private: #define MAX_POWER_LEVEL 15 @@ -66,15 +57,8 @@ private: 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? @@ -85,20 +69,19 @@ private: { public: /// Per-chunk data for the simulator, specified individual chunks to simulate - cCoordWithBlockAndBoolVector m_ChunkData; - cCoordWithBlockAndBoolVector m_QueuedChunkData; + std::unordered_map<Vector3i, std::pair<BLOCKTYPE, bool>, Vector3i> m_ChunkData; std::vector<sPoweredBlocks> m_PoweredBlocks; std::vector<sLinkedPoweredBlocks> m_LinkedBlocks; - std::vector<sSimulatedPlayerToggleableList> m_SimulatedPlayerToggleableBlocks; - std::vector<sRepeatersDelayList> m_RepeatersDelayList; + std::unordered_map<Vector3i, bool, Vector3i> m_SimulatedPlayerToggleableBlocks; + std::unordered_map<Vector3i, sRepeatersDelayList, Vector3i> m_RepeatersDelayList; }; public: typedef std::vector <sPoweredBlocks> PoweredBlocksList; typedef std::vector <sLinkedPoweredBlocks> LinkedBlocksList; - typedef std::vector <sSimulatedPlayerToggleableList> SimulatedPlayerToggleableList; - typedef std::vector <sRepeatersDelayList> RepeatersDelayList; + typedef std::unordered_map<Vector3i, bool, Vector3i> SimulatedPlayerToggleableList; + typedef std::unordered_map<Vector3i, sRepeatersDelayList, Vector3i> RepeatersDelayList; private: @@ -211,7 +194,7 @@ private: 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); + void QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn); /** Removes a block from the Powered and LinkedPowered lists Recursively removes all blocks powered by the given one diff --git a/src/Vector3.h b/src/Vector3.h index 346bc1bbb..279fe5cd7 100644 --- a/src/Vector3.h +++ b/src/Vector3.h @@ -235,6 +235,12 @@ public: return *this; } + /** Provides a hash of a vector's contents */ + size_t operator()(const Vector3<T> & a_Vector) const + { + return ((std::hash<T>()(a_Vector.x) ^ (std::hash<T>()(a_Vector.y) << 1)) ^ std::hash<T>()(a_Vector.z)); + } + // tolua_begin inline Vector3<T> operator + (const Vector3<T>& a_Rhs) const |