From e40f9d6e5b93e840e3d67e79f5ba49da1fbb75f0 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sat, 26 Apr 2014 10:50:23 -0700 Subject: Implemented Chunk Sparsing with segments --- src/Simulator/FireSimulator.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/Simulator') diff --git a/src/Simulator/FireSimulator.cpp b/src/Simulator/FireSimulator.cpp index 470dfc791..4c1008897 100644 --- a/src/Simulator/FireSimulator.cpp +++ b/src/Simulator/FireSimulator.cpp @@ -95,8 +95,10 @@ void cFireSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChun int NumMSecs = (int)a_Dt; for (cCoordWithIntList::iterator itr = Data.begin(); itr != Data.end();) { - int idx = cChunkDef::MakeIndexNoCheck(itr->x, itr->y, itr->z); - BLOCKTYPE BlockType = a_Chunk->GetBlock(idx); + int x = itr->x; + int y = itr->y; + int z = itr->z; + BLOCKTYPE BlockType = a_Chunk->GetBlock(x,y,z); if (!IsAllowedBlock(BlockType)) { @@ -125,7 +127,7 @@ void cFireSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChun itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width ); */ - NIBBLETYPE BlockMeta = a_Chunk->GetMeta(idx); + NIBBLETYPE BlockMeta = a_Chunk->GetMeta(x, y, z); if (BlockMeta == 0x0f) { // The fire burnt out completely @@ -140,7 +142,7 @@ void cFireSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChun if((itr->y > 0) && (!DoesBurnForever(a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z)))) { - a_Chunk->SetMeta(idx, BlockMeta + 1); + a_Chunk->SetMeta(x, y, z, BlockMeta + 1); } itr->Data = GetBurnStepTime(a_Chunk, itr->x, itr->y, itr->z); // TODO: Add some randomness into this } // for itr - Data[] -- cgit v1.2.3 From cfbb2563604e77e044be9a0f12b2152a7d626b51 Mon Sep 17 00:00:00 2001 From: Julian Laubstein Date: Mon, 19 May 2014 10:37:43 +0200 Subject: Fixed some warnings --- src/Simulator/IncrementalRedstoneSimulator.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index 233a3d408..a57a17328 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -202,8 +202,13 @@ private: case E_BLOCK_POWERED_RAIL: { return true; + break; + } + default: + { + return false; + break; } - default: return false; } } @@ -275,8 +280,13 @@ private: case E_BLOCK_PISTON: { return true; + break; + } + default: + { + return false; + break; } - default: return false; } } }; -- cgit v1.2.3 From e9abf9a4987835a52dab508f9b8a8feb57e9a103 Mon Sep 17 00:00:00 2001 From: Julian Laubstein Date: Mon, 19 May 2014 13:02:02 +0200 Subject: Rolled some changes back --- src/Simulator/IncrementalRedstoneSimulator.h | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index a57a17328..233a3d408 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -202,13 +202,8 @@ private: case E_BLOCK_POWERED_RAIL: { return true; - break; - } - default: - { - return false; - break; } + default: return false; } } @@ -280,13 +275,8 @@ private: case E_BLOCK_PISTON: { return true; - break; - } - default: - { - return false; - break; } + default: return false; } } }; -- cgit v1.2.3 From 6687848a7ec1a65ed2c99264ecf9e8119b19c964 Mon Sep 17 00:00:00 2001 From: Julian Laubstein Date: Mon, 19 May 2014 14:49:18 +0200 Subject: Fixed warnings in IncrementalRedstoneSimulator --- src/Simulator/IncrementalRedstoneSimulator.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 074063add..8d29fbec7 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -18,7 +18,13 @@ cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulator(cWorld & a_World) - : super(a_World) + : super(a_World), + m_RedstoneSimulatorChunkData(), + m_PoweredBlocks(), + m_LinkedPoweredBlocks(), + m_SimulatedPlayerToggleableBlocks(), + m_RepeatersDelayList(), + m_Chunk() { } -- cgit v1.2.3 From ee929793f09c431693e1bef7edd77213ba412f60 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 25 May 2014 13:46:34 +0100 Subject: Hopefully fixed piston duplication issues * Fixes #879 * Fixes #714 --- src/Simulator/IncrementalRedstoneSimulator.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 074063add..c24b1c4b3 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -11,7 +11,7 @@ #include "../Blocks/BlockDoor.h" #include "../Blocks/BlockButton.h" #include "../Blocks/BlockLever.h" -#include "../Piston.h" +#include "../Blocks/BlockPiston.h" @@ -814,17 +814,16 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int void cIncrementalRedstoneSimulator::HandlePiston(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { - cPiston Piston(&m_World); int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; if (IsPistonPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7)) // We only want the bottom three bits (4th controls extended-ness) { - Piston.ExtendPiston(BlockX, a_RelBlockY, BlockZ); + cBlockPistonHandler::ExtendPiston(BlockX, a_RelBlockY, BlockZ, &m_World); } else { - Piston.RetractPiston(BlockX, a_RelBlockY, BlockZ); + cBlockPistonHandler::RetractPiston(BlockX, a_RelBlockY, BlockZ, &m_World); } } @@ -1491,7 +1490,7 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBl // Pistons cannot be powered through their front face; this function verifies that a source meets this requirement int OldX = a_RelBlockX, OldY = a_RelBlockY, OldZ = a_RelBlockZ; - eBlockFace Face = cPiston::MetaDataToDirection(a_Meta); + eBlockFace Face = cBlockPistonHandler::MetaDataToDirection(a_Meta); int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; -- cgit v1.2.3 From ae4371a733ee3ac029498ddef50850cc0ca9cbd9 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 29 May 2014 11:56:22 +0100 Subject: Fixed piston power checking --- src/Simulator/IncrementalRedstoneSimulator.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index c24b1c4b3..51a7c2886 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -1489,41 +1489,36 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBl { // Pistons cannot be powered through their front face; this function verifies that a source meets this requirement - int OldX = a_RelBlockX, OldY = a_RelBlockY, OldZ = a_RelBlockZ; eBlockFace Face = cBlockPistonHandler::MetaDataToDirection(a_Meta); - int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX; - int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ; + int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX; + int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ; for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; } - AddFaceDirection(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Face); + AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face); if (!itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { return true; } - a_RelBlockX = OldX; - a_RelBlockY = OldY; - a_RelBlockZ = OldZ; + AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face, true); } for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; } - AddFaceDirection(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Face); + AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face); if (!itr->a_MiddlePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { return true; } - a_RelBlockX = OldX; - a_RelBlockY = OldY; - a_RelBlockZ = OldZ; + AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face, true); } return false; // Source was in front of the piston's front face } -- cgit v1.2.3 From b4ba2209342d536e83b3461db00e9f9fd811120e Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 29 May 2014 19:21:56 +0200 Subject: Add SetOpen() and IsOpen() to BlockDoor.h and fix door redstone bug. --- src/Simulator/IncrementalRedstoneSimulator.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 074063add..d49142e4f 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -906,8 +906,11 @@ void cIncrementalRedstoneSimulator::HandleDoor(int a_RelBlockX, int a_RelBlockY, if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true)) { cChunkInterface ChunkInterface(m_World.GetChunkMap()); - cBlockDoorHandler::ChangeDoor(ChunkInterface, a_RelBlockX, a_RelBlockY, a_RelBlockZ); - m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); + if (!cBlockDoorHandler::IsOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ)) + { + cBlockDoorHandler::SetOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ, true); + m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); + } SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true); } } @@ -916,8 +919,11 @@ void cIncrementalRedstoneSimulator::HandleDoor(int a_RelBlockX, int a_RelBlockY, if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false)) { cChunkInterface ChunkInterface(m_World.GetChunkMap()); - cBlockDoorHandler::ChangeDoor(ChunkInterface, a_RelBlockX, a_RelBlockY, a_RelBlockZ); - m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); + if (cBlockDoorHandler::IsOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ)) + { + cBlockDoorHandler::SetOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ, false); + m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0); + } SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false); } } -- cgit v1.2.3 From 8604dedfdf4e9522fa99e6280e09180523ecce09 Mon Sep 17 00:00:00 2001 From: Julian Laubstein Date: Wed, 4 Jun 2014 10:20:20 +0200 Subject: Update IncrementalRedstoneSimulator.cpp --- src/Simulator/IncrementalRedstoneSimulator.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 8d29fbec7..a89c017df 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -17,14 +17,14 @@ -cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulator(cWorld & a_World) - : super(a_World), - m_RedstoneSimulatorChunkData(), - m_PoweredBlocks(), - m_LinkedPoweredBlocks(), - m_SimulatedPlayerToggleableBlocks(), - m_RepeatersDelayList(), - m_Chunk() +cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulator(cWorld & a_World) : + super(a_World), + m_RedstoneSimulatorChunkData(), + m_PoweredBlocks(), + m_LinkedPoweredBlocks(), + m_SimulatedPlayerToggleableBlocks(), + m_RepeatersDelayList(), + m_Chunk() { } -- cgit v1.2.3 From 22236a103ac506b27236469f353f6ec24bd5f9c6 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 4 Jun 2014 23:23:09 +0100 Subject: Redstone fixes and improvements [SEE DESC] Haha, see desc. * Improved redstone speed through a marking dirty system. Only a select few devices are still continuously simulated * Fixed redstone crashing with recent piston changes --- src/Simulator/IncrementalRedstoneSimulator.cpp | 147 +++++++++++++++---------- 1 file changed, 87 insertions(+), 60 deletions(-) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index f4355b33b..fb8a3e81d 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -89,6 +89,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, { 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); + a_Chunk->SetIsRedstoneDirty(true); continue; } else if ( @@ -103,6 +104,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, { 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); + a_Chunk->SetIsRedstoneDirty(true); continue; } ++itr; @@ -118,6 +120,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, { 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); + a_Chunk->SetIsRedstoneDirty(true); continue; } else if ( @@ -131,6 +134,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, { 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); + a_Chunk->SetIsRedstoneDirty(true); continue; } } @@ -140,6 +144,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, { 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); + a_Chunk->SetIsRedstoneDirty(true); continue; } } @@ -205,7 +210,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, return; } - RedstoneSimulatorChunkData->push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false)); + a_Chunk->GetRedstoneSimulatorQueuedData()->push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false)); } @@ -214,22 +219,29 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) { - // We still attempt to simulate all blocks in the chunk every tick, because of outside influence that needs to be taken into account - // For example, repeaters need to be ticked, pressure plates checked for entities, daylight sensor checked for light changes, etc. - // The easiest way to make this more efficient is probably just to reduce code within the handlers that put too much strain on server, like getting or setting blocks - // A marking dirty system might be a TODO for later on, perhaps - m_RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData(); - if (m_RedstoneSimulatorChunkData->empty()) + if (m_RedstoneSimulatorChunkData->empty() && a_Chunk->GetRedstoneSimulatorQueuedData()->empty()) { return; } + m_RedstoneSimulatorChunkData->insert(m_RedstoneSimulatorChunkData->end(), a_Chunk->GetRedstoneSimulatorQueuedData()->begin(), a_Chunk->GetRedstoneSimulatorQueuedData()->end()); + a_Chunk->GetRedstoneSimulatorQueuedData()->clear(); + m_PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList(); m_RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList(); m_SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList(); m_LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList(); m_Chunk = a_Chunk; + bool ShouldUpdateSimulateOnceBlocks = false; + + if (a_Chunk->IsRedstoneDirty()) + { + // Simulate the majority of devices only if something (blockwise or power-wise) has changed + // Make sure to allow the chunk to resimulate after the initial run if there was a power change (ShouldUpdateSimulateOnceBlocks helps to do this) + a_Chunk->SetIsRedstoneDirty(false); // + ShouldUpdateSimulateOnceBlocks = true; + } for (cRedstoneSimulatorChunkData::iterator dataitr = m_RedstoneSimulatorChunkData->begin(); dataitr != m_RedstoneSimulatorChunkData->end();) { @@ -241,65 +253,15 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int switch (dataitr->Data) { - 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_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_REDSTONE_TORCH_OFF: - case E_BLOCK_REDSTONE_TORCH_ON: - { - HandleRedstoneTorch(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); - break; - } - case E_BLOCK_STONE_BUTTON: - case E_BLOCK_WOODEN_BUTTON: - { - HandleRedstoneButton(dataitr->x, dataitr->y, dataitr->z); - break; - } case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: { HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); break; } - case E_BLOCK_PISTON: - case E_BLOCK_STICKY_PISTON: - { - HandlePiston(dataitr->x, dataitr->y, dataitr->z); - break; - } - case E_BLOCK_REDSTONE_LAMP_OFF: - case E_BLOCK_REDSTONE_LAMP_ON: - { - HandleRedstoneLamp(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); - break; - } - case E_BLOCK_DISPENSER: - case E_BLOCK_DROPPER: - { - HandleDropSpenser(dataitr->x, dataitr->y, dataitr->z); - break; - } - case E_BLOCK_WOODEN_DOOR: - case E_BLOCK_IRON_DOOR: - { - HandleDoor(dataitr->x, dataitr->y, dataitr->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); - break; - } case E_BLOCK_WOODEN_PRESSURE_PLATE: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: @@ -308,7 +270,66 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int HandlePressurePlate(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); break; } - default: LOGD("Unhandled block (!) or unimplemented redstone block: %s", ItemToString(dataitr->Data).c_str()); break; + default: break; + } + + if (ShouldUpdateSimulateOnceBlocks) + { + switch (dataitr->Data) + { + 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_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->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); + break; + } + case E_BLOCK_WOODEN_DOOR: + case E_BLOCK_IRON_DOOR: + { + HandleDoor(dataitr->x, dataitr->y, dataitr->z); + break; + } + case E_BLOCK_REDSTONE_LAMP_OFF: + case E_BLOCK_REDSTONE_LAMP_ON: + { + HandleRedstoneLamp(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + break; + } + case E_BLOCK_DISPENSER: + case E_BLOCK_DROPPER: + { + HandleDropSpenser(dataitr->x, dataitr->y, dataitr->z); + break; + } + case E_BLOCK_PISTON: + case E_BLOCK_STICKY_PISTON: + { + HandlePiston(dataitr->x, dataitr->y, dataitr->z); + break; + } + case E_BLOCK_REDSTONE_TORCH_OFF: + case E_BLOCK_REDSTONE_TORCH_ON: + { + HandleRedstoneTorch(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + break; + } + case E_BLOCK_STONE_BUTTON: + case E_BLOCK_WOODEN_BUTTON: + { + HandleRedstoneButton(dataitr->x, dataitr->y, dataitr->z); + break; + } + default: break; + } } ++dataitr; } @@ -1736,7 +1757,8 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_RelBlockX, int a_RelBl return; } - PoweredBlocksList * Powered = m_Chunk->GetNeighborChunk(BlockX, BlockZ)->GetRedstoneSimulatorPoweredBlocksList(); + cChunk * Neighbour = m_Chunk->GetNeighborChunk(BlockX, BlockZ); + PoweredBlocksList * Powered = Neighbour->GetRedstoneSimulatorPoweredBlocksList(); for (PoweredBlocksList::iterator itr = Powered->begin(); itr != Powered->end(); ++itr) // Check powered list { if ( @@ -1768,6 +1790,8 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_RelBlockX, int a_RelBl RC.a_SourcePos = Vector3i(SourceX, a_RelSourceY, SourceZ); RC.a_PowerLevel = a_PowerLevel; Powered->push_back(RC); + Neighbour->SetIsRedstoneDirty(true); + m_Chunk->SetIsRedstoneDirty(true); } @@ -1807,7 +1831,8 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( return; } - LinkedBlocksList * Linked = m_Chunk->GetNeighborChunk(BlockX, BlockZ)->GetRedstoneSimulatorLinkedBlocksList(); + cChunk * Neighbour = m_Chunk->GetNeighborChunk(BlockX, BlockZ); + LinkedBlocksList * Linked = Neighbour->GetRedstoneSimulatorLinkedBlocksList(); for (LinkedBlocksList::iterator itr = Linked->begin(); itr != Linked->end(); ++itr) // Check linked powered list { if ( @@ -1828,6 +1853,8 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( RC.a_SourcePos = Vector3i(SourceX, a_RelSourceY, SourceZ); RC.a_PowerLevel = a_PowerLevel; Linked->push_back(RC); + Neighbour->SetIsRedstoneDirty(true); + m_Chunk->SetIsRedstoneDirty(true); } -- cgit v1.2.3 From 5f56773dde8d06a291f42def9302ad932c490a28 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 6 Jun 2014 20:36:50 +0100 Subject: Further reduced redstone idle CPU consumption * Repeaters and wires are no longer unnecessarily ticked * Fixed #1063, likely addressed #1062 * Fixed bugs regarding duplicate values --- src/Simulator/IncrementalRedstoneSimulator.cpp | 34 ++++++++++++++++++++------ 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index fb8a3e81d..21326c7c4 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -209,7 +209,15 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, { return; } - + + for (cRedstoneSimulatorChunkData::iterator itr = a_Chunk->GetRedstoneSimulatorQueuedData()->begin(); itr != a_Chunk->GetRedstoneSimulatorQueuedData()->end(); ++itr) + { + if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) + { + // Can't have duplicates in here either, in case something adds the block again before the structure can written to the main chunk data + return; + } + } a_Chunk->GetRedstoneSimulatorQueuedData()->push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false)); } @@ -239,7 +247,7 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int { // Simulate the majority of devices only if something (blockwise or power-wise) has changed // Make sure to allow the chunk to resimulate after the initial run if there was a power change (ShouldUpdateSimulateOnceBlocks helps to do this) - a_Chunk->SetIsRedstoneDirty(false); // + a_Chunk->SetIsRedstoneDirty(false); ShouldUpdateSimulateOnceBlocks = true; } @@ -253,13 +261,24 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int switch (dataitr->Data) { - case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: { - HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + if (ShouldUpdateSimulateOnceBlocks) + { + HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + break; + } + for (RepeatersDelayList::const_iterator repeateritr = m_RepeatersDelayList->begin(); repeateritr != m_RepeatersDelayList->end(); ++repeateritr) + { + if (repeateritr->a_RelBlockPos == Vector3i(dataitr->x, dataitr->y, dataitr->z)) + { + HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + break; + } + } break; } case E_BLOCK_WOODEN_PRESSURE_PLATE: @@ -277,10 +296,11 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int { switch (dataitr->Data) { + 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_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_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break; case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break; -- cgit v1.2.3 From d5649df326d90361bbf64e2ebb4893caa0499521 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 6 Jun 2014 23:23:28 +0100 Subject: Further improvements on redstone speed Based on suggestions of @worktycho * Repeaters now walk their data structure only when needed * Fixed a bug with cChunkData returning an incorrect value for whether a meta had changed --- src/Simulator/IncrementalRedstoneSimulator.cpp | 141 ++++++++++++++----------- src/Simulator/IncrementalRedstoneSimulator.h | 6 +- 2 files changed, 80 insertions(+), 67 deletions(-) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 21326c7c4..aef332e9f 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -266,19 +266,20 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: { - if (ShouldUpdateSimulateOnceBlocks) - { - HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); - break; - } - for (RepeatersDelayList::const_iterator repeateritr = m_RepeatersDelayList->begin(); repeateritr != m_RepeatersDelayList->end(); ++repeateritr) + bool FoundItem = false; + for (RepeatersDelayList::iterator repeateritr = m_RepeatersDelayList->begin(); repeateritr != m_RepeatersDelayList->end(); ++repeateritr) { if (repeateritr->a_RelBlockPos == Vector3i(dataitr->x, dataitr->y, dataitr->z)) { - HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data, repeateritr); + FoundItem = true; break; } } + if (!FoundItem && ShouldUpdateSimulateOnceBlocks) + { + HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data, m_RepeatersDelayList->end()); + } break; } case E_BLOCK_WOODEN_PRESSURE_PLATE: @@ -746,7 +747,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re -void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState) +void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState, RepeatersDelayList::iterator a_Itr) { /* Repeater Orientation Mini Guide: =================================== @@ -772,87 +773,99 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int // Create a variable holding my meta to avoid multiple lookups. NIBBLETYPE a_Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); bool IsOn = (a_MyState == E_BLOCK_REDSTONE_REPEATER_ON); - + + bool WereItrsChanged = false; if (!IsRepeaterLocked(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta)) // If we're locked, change nothing. Otherwise: { bool IsSelfPowered = IsRepeaterPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta); if (IsSelfPowered && !IsOn) // Queue a power change if powered, but not on and not locked. { - QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, true); + WereItrsChanged = QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, true); } else if (!IsSelfPowered && IsOn) // Queue a power change if unpowered, on, and not locked. { - QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false); + WereItrsChanged = QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false); + } + else + { + return; } } + else + { + return; + } - for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr) + if (WereItrsChanged) { - if (!itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) + for (a_Itr = m_RepeatersDelayList->begin(); a_Itr != m_RepeatersDelayList->end(); ++a_Itr) { - continue; + if (a_Itr->a_RelBlockPos == Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) + { + break; + } } + } - if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks? + if (a_Itr->a_ElapsedTicks >= a_Itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks? + { + if (a_Itr->ShouldPowerOn) { - if (itr->ShouldPowerOn) + if (!IsOn) { - if (!IsOn) + m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_REPEATER_ON, a_Meta); // For performance + } + + switch (a_Meta & 0x3) // We only want the direction (bottom) bits + { + case 0x0: { - m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_REPEATER_ON, a_Meta); // For performance + SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZM); + break; } - - switch (a_Meta & 0x3) // We only want the direction (bottom) bits + case 0x1: { - case 0x0: - { - SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZM); - break; - } - case 0x1: - { - SetBlockPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XP); - break; - } - case 0x2: - { - SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZP); - break; - } - case 0x3: - { - SetBlockPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XM); - break; - } + SetBlockPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XP); + break; } - - // Removal of the data entry will be handled in SimChunk - we still want to continue trying to power blocks, even if our delay time has reached - // Otherwise, the power state of blocks in front won't update after we have powered on - return; - } - else - { - if (IsOn) + case 0x2: + { + SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZP); + break; + } + case 0x3: { - m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta); + SetBlockPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XM); + break; } - m_RepeatersDelayList->erase(itr); // We can remove off repeaters which don't need further updating - return; } + + // Removal of the data entry will be handled in SimChunk - we still want to continue trying to power blocks, even if our delay time has reached + // Otherwise, the power state of blocks in front won't update after we have powered on + return; } else { - // Apparently, incrementing ticks only works reliably here, and not in SimChunk; - // With a world with lots of redstone, the repeaters simply do not delay - // I am confounded to say why. Perhaps optimisation failure. - 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++; + if (IsOn) + { + m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta); + } + m_RepeatersDelayList->erase(a_Itr); // We can remove off repeaters which don't need further updating + return; } } + else + { + // Apparently, incrementing ticks only works reliably here, and not in SimChunk; + // With a world with lots of redstone, the repeaters simply do not delay + // I am confounded to say why. Perhaps optimisation failure. + LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", a_Itr->a_RelBlockPos.x, a_Itr->a_RelBlockPos.y, a_Itr->a_RelBlockPos.z, a_Itr->a_ElapsedTicks, a_Itr->a_DelayTicks); + a_Itr->a_ElapsedTicks++; + } } @@ -1914,7 +1927,7 @@ void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_Re -void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn) +bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn) { for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr) { @@ -1922,14 +1935,14 @@ void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, in { if (ShouldPowerOn == itr->ShouldPowerOn) // We are queued already for the same thing, don't replace entry { - return; + 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; + return false; } } @@ -1944,7 +1957,7 @@ void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, in RC.a_ElapsedTicks = 0; RC.ShouldPowerOn = ShouldPowerOn; m_RepeatersDelayList->push_back(RC); - return; + return true; } diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index 233a3d408..83076311a 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -108,7 +108,7 @@ private: /** 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); + void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState, RepeatersDelayList::iterator a_Itr); /* ====================== */ /* ====== DEVICES ====== */ @@ -145,8 +145,8 @@ private: 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 */ - void QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn); + /** 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); /** 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) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); } -- cgit v1.2.3 From af4a21ea0689107b377818574cb07dc4a2e8b755 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 8 Jun 2014 21:58:08 +0200 Subject: Fixed deadlock when moving players to other worlds. Fixes #1039, fixes #851 --- src/Simulator/SandSimulator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Simulator') diff --git a/src/Simulator/SandSimulator.cpp b/src/Simulator/SandSimulator.cpp index b8f34559f..1380f8841 100644 --- a/src/Simulator/SandSimulator.cpp +++ b/src/Simulator/SandSimulator.cpp @@ -60,7 +60,7 @@ void cSandSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChun ); */ cFallingBlock * FallingBlock = new cFallingBlock(Pos, BlockType, a_Chunk->GetMeta(itr->x, itr->y, itr->z)); - FallingBlock->Initialize(&m_World); + FallingBlock->Initialize(m_World); a_Chunk->SetBlock(itr->x, itr->y, itr->z, E_BLOCK_AIR, 0); } } -- cgit v1.2.3 From 1bce1ac4327965453d7709503c5f0b4d8b3edea6 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 12 Jun 2014 17:13:39 +0100 Subject: Fixed two redstone bugs * Fixed chunk border powering * Fixed quick place-replace powering --- src/Simulator/IncrementalRedstoneSimulator.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index b32a57165..eff11bd01 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -65,6 +65,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, RelX = a_BlockX - a_OtherChunk->GetPosX() * cChunkDef::Width; RelZ = a_BlockZ - a_OtherChunk->GetPosZ() * cChunkDef::Width; a_OtherChunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); + a_OtherChunk->SetIsRedstoneDirty(true); } else { @@ -199,6 +200,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, } else { + itr->DataTwo = false; itr->Data = Block; // Update block information } return; @@ -802,11 +804,15 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int { if (a_Itr->a_RelBlockPos == Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) { + // Leave a_Itr at where we found the entry break; } } } + // a_Itr may be passed with m_RepeatersDelayList::end, however, we can guarantee this iterator is always valid because... + // ...QueueRepeaterPowerChange is called to add an entry (and the above code updates iterator). However, if the repeater was locked or something similar... + // ...we will never get here because of the returns. if (a_Itr->a_ElapsedTicks >= a_Itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks? { if (a_Itr->ShouldPowerOn) -- cgit v1.2.3 From c1deda5d8f01811efa5094e9375166acb69d50ed Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 14 Jun 2014 10:47:10 +0100 Subject: Fixed a repeater issue * Repeaters now properly continuously update their powering * Minor cosmetic improvements --- src/Simulator/IncrementalRedstoneSimulator.cpp | 31 +++++++++++++------------- src/Simulator/IncrementalRedstoneSimulator.h | 2 +- 2 files changed, 16 insertions(+), 17 deletions(-) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index eff11bd01..f20f396f2 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -788,12 +788,12 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int { WereItrsChanged = QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false); } - else + else if (a_Itr != m_RepeatersDelayList->end()) { return; } } - else + else if (a_Itr != m_RepeatersDelayList->end()) { return; } @@ -1429,8 +1429,7 @@ bool cIncrementalRedstoneSimulator::AreCoordsLinkedPowered(int a_RelBlockX, int -// IsRepeaterPowered tests if a repeater should be powered by testing for power sources behind the repeater. -// It takes the coordinates of the repeater the the meta value. + bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta) { // Repeaters cannot be powered by any face except their back; verify that this is true for a source @@ -1510,19 +1509,19 @@ bool cIncrementalRedstoneSimulator::IsRepeaterLocked(int a_RelBlockX, int a_RelB case 0x0: case 0x2: { - // Check if eastern(right) neighbor is a powered on repeater who is facing us. + // Check if eastern(right) neighbor is a powered on repeater who is facing us BLOCKTYPE Block = 0; if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) // Is right neighbor a powered repeater? { NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ) & 0x3; - if (OtherRepeaterDir == 0x3) { return true; } // If so, I am latched/locked. + if (OtherRepeaterDir == 0x3) { return true; } // If so, I am latched/locked } - // Check if western(left) neighbor is a powered on repeater who is facing us. + // Check if western(left) neighbor is a powered on repeater who is facing us if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) { NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX -1, a_RelBlockY, a_RelBlockZ) & 0x3; - if (OtherRepeaterDir == 0x1) { return true; } // If so, I am latched/locked. + if (OtherRepeaterDir == 0x1) { return true; } // If so, I am latched/locked } break; @@ -1532,26 +1531,26 @@ bool cIncrementalRedstoneSimulator::IsRepeaterLocked(int a_RelBlockX, int a_RelB case 0x1: case 0x3: { - // Check if southern(down) neighbor is a powered on repeater who is facing us. + // Check if southern(down) neighbor is a powered on repeater who is facing us BLOCKTYPE Block = 0; if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) { NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1) & 0x3; - if (OtherRepeaterDir == 0x0) { return true; } // If so, am latched/locked. + if (OtherRepeaterDir == 0x0) { return true; } // If so, am latched/locked } - // Check if northern(up) neighbor is a powered on repeater who is facing us. + // Check if northern(up) neighbor is a powered on repeater who is facing us if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) { NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1) & 0x3; - if (OtherRepeaterDir == 0x2) { return true; } // If so, I am latched/locked. + if (OtherRepeaterDir == 0x2) { return true; } // If so, I am latched/locked } break; } } - return false; // None of the checks succeeded, I am not a locked repeater. + return false; // None of the checks succeeded, I am not a locked repeater } @@ -1610,7 +1609,7 @@ bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBloc { continue; } - a_PowerLevel = std::max(a_PowerLevel, itr->a_PowerLevel); + a_PowerLevel = itr->a_PowerLevel; } for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list @@ -1619,10 +1618,10 @@ bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBloc { continue; } - a_PowerLevel = std::max(a_PowerLevel, itr->a_PowerLevel); + a_PowerLevel = itr->a_PowerLevel; } - return (a_PowerLevel != 0); // Source was in front of the piston's front face + return (a_PowerLevel != 0); // Answer the inital question: is the wire powered? } diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index 83076311a..1d6a49aca 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -156,7 +156,7 @@ private: 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 */ + /** 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); -- cgit v1.2.3 From ee50790398791c38e563eee04cf12780fab74baf Mon Sep 17 00:00:00 2001 From: Tycho Date: Mon, 16 Jun 2014 15:12:50 +0100 Subject: Merge branch 'master' of github.com:mc-server/MCServer --- src/Simulator/IncrementalRedstoneSimulator.cpp | 38 ++++++++++++++++++++------ 1 file changed, 30 insertions(+), 8 deletions(-) (limited to 'src/Simulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index f20f396f2..69c8b9f56 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -59,19 +59,21 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, int RelZ = 0; BLOCKTYPE Block; NIBBLETYPE Meta; + cChunk * Chunk; if (a_OtherChunk != NULL) { RelX = a_BlockX - a_OtherChunk->GetPosX() * cChunkDef::Width; RelZ = a_BlockZ - a_OtherChunk->GetPosZ() * cChunkDef::Width; a_OtherChunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); - a_OtherChunk->SetIsRedstoneDirty(true); + Chunk = a_OtherChunk; } else { RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width; RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width; a_Chunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); + Chunk = a_Chunk; } // 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 @@ -90,7 +92,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, { 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); - a_Chunk->SetIsRedstoneDirty(true); + Chunk->SetIsRedstoneDirty(true); continue; } else if ( @@ -105,9 +107,25 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, { 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); - a_Chunk->SetIsRedstoneDirty(true); + Chunk->SetIsRedstoneDirty(true); continue; } + else if (Block == E_BLOCK_DAYLIGHT_SENSOR) + { + if (!m_World.IsChunkLighted(Chunk->GetPosX(), Chunk->GetPosZ())) + { + m_World.QueueLightChunk(Chunk->GetPosX(), Chunk->GetPosZ()); + } + else + { + if (Chunk->GetTimeAlteredLight(Chunk->GetSkyLight(RelX, a_BlockY + 1, RelZ)) <= 7) + { + itr = PoweredBlocks->erase(itr); + Chunk->SetIsRedstoneDirty(true); + continue; + } + } + } ++itr; } @@ -121,7 +139,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, { 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); - a_Chunk->SetIsRedstoneDirty(true); + Chunk->SetIsRedstoneDirty(true); continue; } else if ( @@ -135,7 +153,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, { 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); - a_Chunk->SetIsRedstoneDirty(true); + Chunk->SetIsRedstoneDirty(true); continue; } } @@ -145,7 +163,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, { 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); - a_Chunk->SetIsRedstoneDirty(true); + Chunk->SetIsRedstoneDirty(true); continue; } } @@ -788,12 +806,12 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int { WereItrsChanged = QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false); } - else if (a_Itr != m_RepeatersDelayList->end()) + else if (a_Itr == m_RepeatersDelayList->end()) { return; } } - else if (a_Itr != m_RepeatersDelayList->end()) + else if (a_Itr == m_RepeatersDelayList->end()) { return; } @@ -1145,6 +1163,10 @@ void cIncrementalRedstoneSimulator::HandleDaylightSensor(int a_RelBlockX, int a_ { SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); } + else + { + WakeUp(BlockX, a_RelBlockY, BlockZ, m_Chunk); + } } } -- cgit v1.2.3