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/Simulator/IncrementalRedstoneSimulator.cpp | |
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/Simulator/IncrementalRedstoneSimulator.cpp')
-rw-r--r-- | src/Simulator/IncrementalRedstoneSimulator.cpp | 212 |
1 files changed, 78 insertions, 134 deletions
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; + } } |