From e7fba08e6cbba1801dd45ad4c14ea743b7743e84 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 10 Jan 2014 20:31:05 +0000 Subject: [PATCH 1/6] Major refactoring of redstone This commit is a refactoring of the redstone code, mainly the functions handling the removal of invalid blocks from power supplier data structures. Its aim is to improve performance and potentially reduce the memory footprint of the data structures. It works to reduce the amount of GetBlock()s triggered every tick. Before, a GetBlock() was requested for every single item in the data lists, as well as for every single redstone block in a chunk. Following these changes, the AddBlock() event is utilised more effectively to only update the lists when needed (a block is changed), as well as to insert the block type (and update it when needed) alongside the coordinates into the main redstone simulator chunkdata list. In short, a single GetBlock() is now cached, with this cache being updated when the simulator is awoken due to a block change. At least, I *hope* that this is what it does :P --- src/ChunkDef.h | 2 + src/Server.h | 2 +- src/Simulator/RedstoneSimulator.cpp | 288 ++++++++++++++-------------- src/Simulator/RedstoneSimulator.h | 79 ++++---- 4 files changed, 183 insertions(+), 188 deletions(-) diff --git a/src/ChunkDef.h b/src/ChunkDef.h index 7d727a4d4..3df575732 100644 --- a/src/ChunkDef.h +++ b/src/ChunkDef.h @@ -610,8 +610,10 @@ public: // Illegal in C++03: typedef std::list< cCoordWithData > cCoordWithDataList; typedef cCoordWithData cCoordWithInt; +typedef cCoordWithData cCoordWithBlock; typedef std::list cCoordWithIntList; typedef std::vector cCoordWithIntVector; +typedef std::vector cCoordWithBlockVector; diff --git a/src/Server.h b/src/Server.h index d79417fb0..703a7077e 100644 --- a/src/Server.h +++ b/src/Server.h @@ -107,7 +107,7 @@ public: // tolua_export /// Notifies the server that a player is being destroyed; the server uses this to adjust the number of players void PlayerDestroying(const cPlayer * a_Player); - /* Returns base64 encoded favicon data (obtained from favicon.png) */ + /** Returns base64 encoded favicon data (obtained from favicon.png) */ const AString & GetFaviconData(void) const { return m_FaviconData; } CryptoPP::RSA::PrivateKey & GetPrivateKey(void) { return m_PrivateKey; } diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp index f65908729..a21c57f38 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -44,83 +44,45 @@ void cRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChu int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width; int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width; + + BLOCKTYPE Block; + NIBBLETYPE Meta; + a_Chunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); - if (!IsAllowedBlock(a_Chunk->GetBlock(RelX, a_BlockY, RelZ))) - { - return; - } + // Every time a block is changed (AddBlock called), we want to go through all lists and check to see if the coordiantes stored within are still valid + // Checking only when a block is changed, as opposed to every tick, also improves performance - // Check for duplicates: - cRedstoneSimulatorChunkData & ChunkData = a_Chunk->GetRedstoneSimulatorData(); - for (cRedstoneSimulatorChunkData::const_iterator itr = ChunkData.begin(); itr != ChunkData.end(); ++itr) - { - if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) - { - return; - } - } - - ChunkData.push_back(cCoordWithInt(RelX, a_BlockY, RelZ)); -} - - - - - -void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) -{ - cRedstoneSimulatorChunkData & ChunkData = a_Chunk->GetRedstoneSimulatorData(); - if (ChunkData.empty()) - { - return; - } - - int BaseX = a_Chunk->GetPosX() * cChunkDef::Width; - int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width; - - // Check to see if PoweredBlocks have invalid items (source is air or unpowered) for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end();) { - int RelX = itr->a_SourcePos.x - a_ChunkX * cChunkDef::Width; - int RelZ = itr->a_SourcePos.z - a_ChunkZ * cChunkDef::Width; - int DestRelX = itr->a_BlockPos.x - a_ChunkX * cChunkDef::Width; - int DestRelZ = itr->a_BlockPos.z - a_ChunkZ * cChunkDef::Width; - - BLOCKTYPE SourceBlockType; - NIBBLETYPE SourceBlockMeta; - BLOCKTYPE DestBlockType; - if ( - !a_Chunk->UnboundedRelGetBlock(RelX, itr->a_SourcePos.y, RelZ, SourceBlockType, SourceBlockMeta) || - !a_Chunk->UnboundedRelGetBlockType(DestRelX, itr->a_BlockPos.y, DestRelZ, DestBlockType) - ) + if (!itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { + ++itr; continue; } - if (SourceBlockType != itr->a_SourceBlock) + if (!IsPotentialSource(Block)) { - LOGD("cRedstoneSimulator: Erased block %s from powered blocks list due to present/past block type mismatch", ItemToFullString(itr->a_SourceBlock).c_str()); + LOGD("cRedstoneSimulator: 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 = m_PoweredBlocks.erase(itr); } else if ( // Changeable sources - ((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (SourceBlockMeta == 0)) || - ((SourceBlockType == E_BLOCK_LEVER) && !IsLeverOn(SourceBlockMeta)) || - ((SourceBlockType == E_BLOCK_DETECTOR_RAIL) && (SourceBlockMeta & 0x08) == 0x08) || - (((SourceBlockType == E_BLOCK_STONE_BUTTON) || (SourceBlockType == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(SourceBlockMeta))) || - (((SourceBlockType == E_BLOCK_STONE_PRESSURE_PLATE) || (SourceBlockType == E_BLOCK_WOODEN_PRESSURE_PLATE)) && (SourceBlockMeta == 0)) + ((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) || + ((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) || + ((Block == E_BLOCK_DETECTOR_RAIL) && (Meta & 0x08) == 0x08) || + (((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) || + (((Block == E_BLOCK_STONE_PRESSURE_PLATE) || (Block == E_BLOCK_WOODEN_PRESSURE_PLATE)) && (Meta == 0)) ) { - LOGD("cRedstoneSimulator: Erased block %s from powered blocks list due to present/past metadata mismatch", ItemToFullString(itr->a_SourceBlock).c_str()); + LOGD("cRedstoneSimulator: 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 = m_PoweredBlocks.erase(itr); } - else if (SourceBlockType == E_BLOCK_DAYLIGHT_SENSOR) + else if (Block == E_BLOCK_DAYLIGHT_SENSOR) { if (!a_Chunk->IsLightValid()) { - m_World.QueueLightChunk(a_ChunkX, a_ChunkZ); + m_World.QueueLightChunk(a_Chunk->GetPosX(), a_Chunk->GetPosZ()); ++itr; - continue; } else { @@ -135,60 +97,50 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c else { ++itr; - continue; } } } - else if ((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (DestBlockType == E_BLOCK_REDSTONE_WIRE)) - { - // It is simply not allowed that a wire powers another wire, presuming that data here is sane and a dest and source are beside each other - LOGD("cRedstoneSimulator: Erased redstone wire from powered blocks list because its source was also wire"); - itr = m_PoweredBlocks.erase(itr); - } else { ++itr; } } - // Check to see if LinkedPoweredBlocks have invalid items: source, block powered through, or power destination block has changed for (LinkedBlocksList::iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end();) { - int RelX = itr->a_SourcePos.x - a_ChunkX * cChunkDef::Width; - int RelZ = itr->a_SourcePos.z - a_ChunkZ * cChunkDef::Width; - int MidRelX = itr->a_MiddlePos.x - a_ChunkX * cChunkDef::Width; - int MidRelZ = itr->a_MiddlePos.z - a_ChunkZ * cChunkDef::Width; - - BLOCKTYPE SourceBlockType; - NIBBLETYPE SourceBlockMeta; - BLOCKTYPE MiddleBlockType; - if ( - !a_Chunk->UnboundedRelGetBlock(RelX, itr->a_SourcePos.y, RelZ, SourceBlockType, SourceBlockMeta) || - !a_Chunk->UnboundedRelGetBlockType(MidRelX, itr->a_MiddlePos.y, MidRelZ, MiddleBlockType) - ) + if (itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { - continue; + if (!IsPotentialSource(Block)) + { + LOGD("cRedstoneSimulator: 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 = m_LinkedPoweredBlocks.erase(itr); + } + else if ( + // Things that can send power through a block but which depends on meta + ((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) || + ((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) || + (((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) + ) + { + LOGD("cRedstoneSimulator: 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 = m_LinkedPoweredBlocks.erase(itr); + } + else + { + ++itr; + } } - - if (SourceBlockType != itr->a_SourceBlock) + else if (itr->a_MiddlePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { - LOGD("cRedstoneSimulator: Erased block %s from linked powered blocks list due to present/past block type mismatch", ItemToFullString(itr->a_SourceBlock).c_str()); - itr = m_LinkedPoweredBlocks.erase(itr); - } - else if (MiddleBlockType != itr->a_MiddleBlock) - { - LOGD("cRedstoneSimulator: Erased block %s from linked powered blocks list due to present/past middle block mismatch", ItemToFullString(itr->a_SourceBlock).c_str()); - itr = m_LinkedPoweredBlocks.erase(itr); - } - else if ( - // Things that can send power through a block but which depends on meta - ((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (SourceBlockMeta == 0)) || - ((SourceBlockType == E_BLOCK_LEVER) && !IsLeverOn(SourceBlockMeta)) || - (((SourceBlockType == E_BLOCK_STONE_BUTTON) || (SourceBlockType == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(SourceBlockMeta))) - ) - { - LOGD("cRedstoneSimulator: Erased block %s from linked powered blocks list due to present/past metadata mismatch", ItemToFullString(itr->a_SourceBlock).c_str()); - itr = m_LinkedPoweredBlocks.erase(itr); + if (!IsViableMiddleBlock(Block)) + { + LOGD("cRedstoneSimulator: 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 = m_LinkedPoweredBlocks.erase(itr); + } + else + { + ++itr; + } } else { @@ -196,60 +148,85 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c } } - for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end();) + for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end(); ++itr) { - int RelX = itr->a_BlockPos.x - a_ChunkX * cChunkDef::Width; - int RelZ = itr->a_BlockPos.z - a_ChunkZ * cChunkDef::Width; - - BLOCKTYPE SourceBlockType; - if (!a_Chunk->UnboundedRelGetBlockType(RelX, itr->a_BlockPos.y, RelZ, SourceBlockType)) + if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; } - else if (!IsAllowedBlock(SourceBlockType)) + + if (!IsAllowedBlock(Block)) { - LOGD("cRedstoneSimulator: Erased block %s from toggleable simulated list as block is no longer redstone", ItemToFullString(SourceBlockType).c_str()); + LOGD("cRedstoneSimulator: Erased block @ {%i, %i, %i} from toggleable simulated list as it is no longer redstone", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); itr = m_SimulatedPlayerToggleableBlocks.erase(itr); - } - else - { - ++itr; + break; } } - for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end();) + for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); ++itr) { - int RelX = itr->a_BlockPos.x - a_ChunkX * cChunkDef::Width; - int RelZ = itr->a_BlockPos.z - a_ChunkZ * cChunkDef::Width; - - BLOCKTYPE SourceBlockType; - if (!a_Chunk->UnboundedRelGetBlockType(RelX, itr->a_BlockPos.y, RelZ, SourceBlockType)) + if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; } - if ((SourceBlockType != E_BLOCK_REDSTONE_REPEATER_ON) && (SourceBlockType != E_BLOCK_REDSTONE_REPEATER_OFF)) + if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF)) { itr = m_RepeatersDelayList.erase(itr); - continue; + break; } - - ++itr; } + cRedstoneSimulatorChunkData & ChunkData = a_Chunk->GetRedstoneSimulatorData(); + for (cRedstoneSimulatorChunkData::iterator itr = ChunkData.begin(); itr != ChunkData.end(); ++itr) + { + if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) // We are at an entry matching the current (changed) block + { + if (!IsAllowedBlock(Block)) + { + ChunkData.erase(itr); // The new blocktype is not redstone; it must be removed from this list + } + else + { + itr->Data = Block; // Update block information + } + return; + } + } + + if (!IsAllowedBlock(Block)) + { + return; + } + + ChunkData.push_back(cCoordWithBlock(RelX, a_BlockY, RelZ, Block)); +} + + + + + +void cRedstoneSimulator::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 + + cRedstoneSimulatorChunkData & ChunkData = a_Chunk->GetRedstoneSimulatorData(); + if (ChunkData.empty()) + { + return; + } + + int BaseX = a_Chunk->GetPosX() * cChunkDef::Width; + int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width; + for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(), end = ChunkData.end(); dataitr != end;) { - BLOCKTYPE BlockType = a_Chunk->GetBlock(dataitr->x, dataitr->y, dataitr->z); - if (!IsAllowedBlock(BlockType)) - { - dataitr = ChunkData.erase(dataitr); - continue; - } - - // PoweredBlock and LinkedPoweredBlock list was fine, now to the actual handling int a_X = BaseX + dataitr->x; int a_Z = BaseZ + dataitr->z; - switch (BlockType) + switch (dataitr->Data) { case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(a_X, dataitr->y, a_Z); break; case E_BLOCK_LEVER: HandleRedstoneLever(a_X, dataitr->y, a_Z); break; @@ -262,19 +239,19 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: { - HandleRedstoneTorch(a_X, dataitr->y, a_Z, BlockType); + HandleRedstoneTorch(a_X, dataitr->y, a_Z, dataitr->Data); break; } case E_BLOCK_STONE_BUTTON: case E_BLOCK_WOODEN_BUTTON: { - HandleRedstoneButton(a_X, dataitr->y, a_Z, BlockType); + HandleRedstoneButton(a_X, dataitr->y, a_Z, dataitr->Data); break; } case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: { - HandleRedstoneRepeater(a_X, dataitr->y, a_Z, BlockType); + HandleRedstoneRepeater(a_X, dataitr->y, a_Z, dataitr->Data); break; } case E_BLOCK_PISTON: @@ -286,7 +263,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c case E_BLOCK_REDSTONE_LAMP_OFF: case E_BLOCK_REDSTONE_LAMP_ON: { - HandleRedstoneLamp(a_X, dataitr->y, a_Z, BlockType); + HandleRedstoneLamp(a_X, dataitr->y, a_Z, dataitr->Data); break; } case E_BLOCK_DISPENSER: @@ -305,13 +282,13 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_POWERED_RAIL: { - HandleRail(a_X, dataitr->y, a_Z, BlockType); + HandleRail(a_X, dataitr->y, a_Z, dataitr->Data); break; } case E_BLOCK_WOODEN_PRESSURE_PLATE: case E_BLOCK_STONE_PRESSURE_PLATE: { - HandlePressurePlate(a_X, dataitr->y, a_Z, BlockType); + HandlePressurePlate(a_X, dataitr->y, a_Z, dataitr->Data); break; } } @@ -487,7 +464,7 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl }; // Check to see if directly beside a power source - if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) + if (IsWirePowered(a_BlockX, a_BlockY, a_BlockZ)) { m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 15); // Maximum power } @@ -546,6 +523,7 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl // However, self not directly powered anymore, so source must have been removed, // therefore, self must be set to meta zero m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0); + m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ); return; // No need to process block power sets because self not powered } else @@ -693,7 +671,7 @@ void cRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int // 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_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks); + LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks); itr->a_ElapsedTicks++; } } @@ -1188,6 +1166,33 @@ bool cRedstoneSimulator::IsPistonPowered(int a_BlockX, int a_BlockY, int a_Block +bool cRedstoneSimulator::IsWirePowered(int a_BlockX, int a_BlockY, int a_BlockZ) +{ + for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) + { + if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; } + + if (m_World.GetBlock(itr->a_SourcePos) != E_BLOCK_REDSTONE_WIRE) + { + return true; + } + } + + for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) + { + if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; } + + if (m_World.GetBlock(itr->a_SourcePos) != E_BLOCK_REDSTONE_WIRE) + { + return true; + } + } + return false; // Source was in front of the piston's front face +} + + + + bool cRedstoneSimulator::AreCoordsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool IsCurrentStatePowered) { @@ -1333,11 +1338,6 @@ void cRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY, int a_Block // Don't set air, fixes some bugs (wires powering themselves) return; } - if ((Block == E_BLOCK_REDSTONE_WIRE) && (a_SourceBlock == E_BLOCK_REDSTONE_WIRE)) - { - // Wires cannot power themselves normally, instead, the wire handler will manually set meta - return; - } for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) // Check powered list { @@ -1354,7 +1354,6 @@ void cRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY, int a_Block sPoweredBlocks RC; RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ); RC.a_SourcePos = Vector3i(a_SourceX, a_SourceY, a_SourceZ); - RC.a_SourceBlock = a_SourceBlock; m_PoweredBlocks.push_back(RC); } @@ -1379,11 +1378,6 @@ void cRedstoneSimulator::SetBlockLinkedPowered( { return; } - if ((a_SourceBlock == E_BLOCK_REDSTONE_WIRE) && (DestBlock == E_BLOCK_REDSTONE_WIRE)) - { - // Wires cannot power another wire through a block - return; - } for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) // Check linked powered list { @@ -1402,8 +1396,6 @@ void cRedstoneSimulator::SetBlockLinkedPowered( RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ); RC.a_MiddlePos = Vector3i(a_MiddleX, a_MiddleY, a_MiddleZ); RC.a_SourcePos = Vector3i(a_SourceX, a_SourceY, a_SourceZ); - RC.a_SourceBlock = a_SourceBlock; - RC.a_MiddleBlock = a_MiddleBlock; m_LinkedPoweredBlocks.push_back(RC); } diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h index 1080c3f81..4fe8b59b3 100644 --- a/src/Simulator/RedstoneSimulator.h +++ b/src/Simulator/RedstoneSimulator.h @@ -4,7 +4,7 @@ #include "Simulator.h" /// Per-chunk data for the simulator, specified individual chunks to simulate; 'Data' is not used -typedef cCoordWithIntList cRedstoneSimulatorChunkData; +typedef cCoordWithBlockVector cRedstoneSimulatorChunkData; @@ -39,7 +39,6 @@ private: { Vector3i a_BlockPos; // Position of powered block Vector3i a_SourcePos; // Position of source powering the block at a_BlockPos - BLOCKTYPE a_SourceBlock; // The source block type (for pistons pushing away sources and replacing with non source etc.) }; struct sLinkedPoweredBlocks // Define structure of the indirectly powered blocks list (i.e. repeaters powering through a block to the block at the other side) @@ -47,8 +46,6 @@ private: Vector3i a_BlockPos; Vector3i a_MiddlePos; Vector3i a_SourcePos; - BLOCKTYPE a_SourceBlock; - BLOCKTYPE a_MiddleBlock; }; struct sSimulatedPlayerToggleableList @@ -81,81 +78,86 @@ private: // In addition to being non-performant, it would stop the player from actually breaking said device /* ====== SOURCES ====== */ - /// Handles the redstone torch + /** Handles the redstone torch */ void HandleRedstoneTorch(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState); - /// Handles the redstone block + /** Handles the redstone block */ void HandleRedstoneBlock(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Handles levers + /** Handles levers */ void HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Handles buttons + /** Handles buttons */ void HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType); - /// Handles daylight sensors + /** Handles daylight sensors */ void HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Handles pressure plates + /** Handles pressure plates */ void HandlePressurePlate(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType); /* ==================== */ /* ====== CARRIERS ====== */ - /// Handles redstone wire + /** Handles redstone wire */ void HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Handles repeaters + /** Handles repeaters */ void HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState); /* ====================== */ /* ====== DEVICES ====== */ - /// Handles pistons + /** Handles pistons */ void HandlePiston(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Handles dispensers and droppers + /** Handles dispensers and droppers */ void HandleDropSpenser(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Handles TNT (exploding) + /** Handles TNT (exploding) */ void HandleTNT(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Handles redstone lamps + /** Handles redstone lamps */ void HandleRedstoneLamp(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState); - /// Handles doords + /** Handles doords */ void HandleDoor(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Handles activator, detector, and powered rails + /** Handles activator, detector, and powered rails */ void HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType); - /// Handles trapdoors + /** Handles trapdoors */ void HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Handles noteblocks + /** Handles noteblocks */ void HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ); /* ===================== */ /* ====== Helper functions ====== */ - /// Marks a block as powered + /** Marks a block as powered */ void SetBlockPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock); - /// Marks a block as being powered through another block + /** Marks a block as being powered through another block */ void SetBlockLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_MiddleX, int a_MiddleY, int a_MiddleZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock, BLOCKTYPE a_MiddeBlock); - /// Marks a block as simulated, who should not be simulated further unless their power state changes, to accomodate a player manually toggling the block without triggering the simulator toggling it back + /** Marks a block as simulated, who should not be simulated further unless their power state changes, to accomodate a player manually toggling the block without triggering the simulator toggling it back */ void SetPlayerToggleableBlockAsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool WasLastStatePowered); - /// Marks the second block in a direction as linked powered + /** Marks the second block in a direction as linked powered */ void SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, BLOCKTYPE a_SourceBlock); - /// Marks all blocks immediately surrounding a coordinate as powered + /** Marks all blocks immediately surrounding a coordinate as powered */ void SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock); - /// Queues a repeater to be powered or unpowered + /** Queues a repeater to be powered or unpowered */ void QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, short a_ElapsedTicks, bool ShouldPowerOn); - /// Returns if a coordinate is powered or linked powered + /** Returns if a coordinate is powered or linked powered */ bool AreCoordsPowered(int a_BlockX, int a_BlockY, int a_BlockZ) { return AreCoordsDirectlyPowered(a_BlockX, a_BlockY, a_BlockZ) || AreCoordsLinkedPowered(a_BlockX, a_BlockY, a_BlockZ); } - /// Returns if a coordinate is in the directly powered blocks list + /** Returns if a coordinate is in the directly powered blocks list */ bool AreCoordsDirectlyPowered(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Returns if a coordinate is in the indirectly powered blocks list + /** Returns if a coordinate is in the indirectly powered blocks list */ bool AreCoordsLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Returns if a coordinate was marked as simulated (for blocks toggleable by players) + /** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */ bool AreCoordsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool IsCurrentStatePowered); - /// Returns if a repeater is powered + /** Returns if a repeater is powered */ bool IsRepeaterPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta); - /// Returns if a piston is powered + /** Returns if a piston is powered */ bool IsPistonPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta); + /** Returns if a wire is powered + The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire + */ + bool IsWirePowered(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Returns if lever metadata marks it as emitting power + + /** Returns if lever metadata marks it as emitting power */ bool IsLeverOn(NIBBLETYPE a_BlockMeta); - /// Returns if button metadata marks it as emitting power + /** Returns if button metadata marks it as emitting power */ bool IsButtonOn(NIBBLETYPE a_BlockMeta); /* ============================== */ /* ====== Misc Functions ====== */ - /// Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation + /** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */ inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { if (!g_BlockIsSolid[Block]) { return false; } @@ -176,7 +178,7 @@ private: } } - /// Returns if a block is a mechanism (something that accepts power and does something) + /** Returns if a block is a mechanism (something that accepts power and does something) */ inline static bool IsMechanism(BLOCKTYPE Block) { switch (Block) @@ -205,7 +207,7 @@ private: } } - /// Returns if a block has the potential to output power + /** Returns if a block has the potential to output power */ inline static bool IsPotentialSource(BLOCKTYPE Block) { switch (Block) @@ -214,7 +216,6 @@ private: case E_BLOCK_WOODEN_BUTTON: case E_BLOCK_STONE_BUTTON: case E_BLOCK_REDSTONE_WIRE: - case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_LEVER: case E_BLOCK_REDSTONE_REPEATER_ON: @@ -227,7 +228,7 @@ private: } } - /// Returns if a block is any sort of redstone device + /** Returns if a block is any sort of redstone device */ inline static bool IsRedstone(BLOCKTYPE Block) { switch (Block) From d5b38402ed232e38da72dc59f0ec492654c9c0f8 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 10 Jan 2014 21:35:41 +0000 Subject: [PATCH 2/6] Fixed doors, fixes #453 --- src/Simulator/RedstoneSimulator.cpp | 46 +++++------------------------ 1 file changed, 8 insertions(+), 38 deletions(-) diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp index a21c57f38..742d8ed2b 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -222,7 +222,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c int BaseX = a_Chunk->GetPosX() * cChunkDef::Width; int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width; - for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(), end = ChunkData.end(); dataitr != end;) + for (cRedstoneSimulatorChunkData::const_iterator dataitr = ChunkData.begin(); dataitr != ChunkData.end(); ++dataitr) { int a_X = BaseX + dataitr->x; int a_Z = BaseZ + dataitr->z; @@ -292,8 +292,6 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c break; } } - - ++dataitr; } } @@ -759,48 +757,20 @@ void cRedstoneSimulator::HandleTNT(int a_BlockX, int a_BlockY, int a_BlockZ) void cRedstoneSimulator::HandleDoor(int a_BlockX, int a_BlockY, int a_BlockZ) { - if ((m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x08) == 0x08) + if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) { - // Block position is located at top half of door - // Is Y - 1 both within world boundaries, a door block, and the bottom half of a door? - // The bottom half stores the open/closed information - if ( - (a_BlockY - 1 >= 0) && - ((m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_WOODEN_DOOR) || (m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_IRON_DOOR)) && - (m_World.GetBlockMeta(a_BlockX, a_BlockY - 1, a_BlockZ & 0x08) == 0) - ) + if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true)) { - if ((m_World.GetBlockMeta(a_BlockX, a_BlockY - 1, a_BlockZ) & 0x04) == 0) // Closed door? - { - if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) // Powered? If so, toggle open - { - cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ); - } - } - else // Opened door - { - if (!AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) // Unpowered? Close if so - { - cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ); - } - } + cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ); + SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true); } } else { - if ((m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x04) == 0) // Closed door? + if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, false)) { - if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) // Powered? If so, toggle open - { - cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ); - } - } - else // Opened door - { - if (!AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) // Unpowered? Close if so - { - cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ); - } + cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ); + SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false); } } } From b068b73ad9cce7a5150c589b66d6465a8a4d0b90 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 11 Jan 2014 01:51:24 +0000 Subject: [PATCH 3/6] Renamed g_TorchPlaceable... ...to g_FullyOccupiesVoxel, as recommended by @bearbin --- src/BlockID.cpp | 126 +++++++++++++++++------------------ src/BlockID.h | 2 +- src/Blocks/BlockRedstone.h | 2 +- src/Blocks/BlockTorch.h | 6 +- src/Defines.h | 4 +- src/Items/ItemRedstoneDust.h | 2 +- 6 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/BlockID.cpp b/src/BlockID.cpp index 05d4c6595..db7551a9a 100644 --- a/src/BlockID.cpp +++ b/src/BlockID.cpp @@ -20,7 +20,7 @@ bool g_BlockPistonBreakable[256]; bool g_BlockIsSnowable[256]; bool g_BlockRequiresSpecialTool[256]; bool g_BlockIsSolid[256]; -bool g_BlockIsTorchPlaceable[256]; +bool g_BlockFullyOccupiesVoxel[256]; @@ -591,7 +591,7 @@ public: memset(g_BlockTransparent, 0x00, sizeof(g_BlockTransparent)); memset(g_BlockOneHitDig, 0x00, sizeof(g_BlockOneHitDig)); memset(g_BlockPistonBreakable, 0x00, sizeof(g_BlockPistonBreakable)); - memset(g_BlockIsTorchPlaceable, 0x00, sizeof(g_BlockIsTorchPlaceable)); + memset(g_BlockFullyOccupiesVoxel, 0x00, sizeof(g_BlockFullyOccupiesVoxel)); // Setting bools to true must be done manually, see http://forum.mc-server.org/showthread.php?tid=629&pid=5415#pid5415 for (size_t i = 0; i < ARRAYCOUNT(g_BlockIsSnowable); i++) @@ -891,67 +891,67 @@ public: g_BlockIsSolid[E_BLOCK_WOODEN_SLAB] = false; // Torch placeable blocks: - g_BlockIsTorchPlaceable[E_BLOCK_BEDROCK] = true; - g_BlockIsTorchPlaceable[E_BLOCK_BLOCK_OF_COAL] = true; - g_BlockIsTorchPlaceable[E_BLOCK_BLOCK_OF_REDSTONE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_BOOKCASE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_BRICK] = true; - g_BlockIsTorchPlaceable[E_BLOCK_CLAY] = true; - g_BlockIsTorchPlaceable[E_BLOCK_COAL_ORE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_COBBLESTONE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_COMMAND_BLOCK] = true; - g_BlockIsTorchPlaceable[E_BLOCK_CRAFTING_TABLE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_DIAMOND_BLOCK] = true; - g_BlockIsTorchPlaceable[E_BLOCK_DIAMOND_ORE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_DIRT] = true; - g_BlockIsTorchPlaceable[E_BLOCK_DISPENSER] = true; - g_BlockIsTorchPlaceable[E_BLOCK_DOUBLE_STONE_SLAB] = true; - g_BlockIsTorchPlaceable[E_BLOCK_DOUBLE_WOODEN_SLAB] = true; - g_BlockIsTorchPlaceable[E_BLOCK_DROPPER] = true; - g_BlockIsTorchPlaceable[E_BLOCK_EMERALD_BLOCK] = true; - g_BlockIsTorchPlaceable[E_BLOCK_EMERALD_ORE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_END_STONE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_FURNACE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_GLOWSTONE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_GOLD_BLOCK] = true; - g_BlockIsTorchPlaceable[E_BLOCK_GOLD_ORE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_GRASS] = true; - g_BlockIsTorchPlaceable[E_BLOCK_GRAVEL] = true; - g_BlockIsTorchPlaceable[E_BLOCK_HARDENED_CLAY] = true; - g_BlockIsTorchPlaceable[E_BLOCK_HAY_BALE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_HUGE_BROWN_MUSHROOM] = true; - g_BlockIsTorchPlaceable[E_BLOCK_HUGE_RED_MUSHROOM] = true; - g_BlockIsTorchPlaceable[E_BLOCK_IRON_BLOCK] = true; - g_BlockIsTorchPlaceable[E_BLOCK_IRON_ORE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_JACK_O_LANTERN] = true; - g_BlockIsTorchPlaceable[E_BLOCK_JUKEBOX] = true; - g_BlockIsTorchPlaceable[E_BLOCK_LAPIS_BLOCK] = true; - g_BlockIsTorchPlaceable[E_BLOCK_LAPIS_ORE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_LOG] = true; - g_BlockIsTorchPlaceable[E_BLOCK_MELON] = true; - g_BlockIsTorchPlaceable[E_BLOCK_MOSSY_COBBLESTONE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_MYCELIUM] = true; - g_BlockIsTorchPlaceable[E_BLOCK_NETHERRACK] = true; - g_BlockIsTorchPlaceable[E_BLOCK_NETHER_BRICK] = true; - g_BlockIsTorchPlaceable[E_BLOCK_NETHER_QUARTZ_ORE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_NOTE_BLOCK] = true; - g_BlockIsTorchPlaceable[E_BLOCK_OBSIDIAN] = true; - g_BlockIsTorchPlaceable[E_BLOCK_PACKED_ICE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_PLANKS] = true; - g_BlockIsTorchPlaceable[E_BLOCK_PUMPKIN] = true; - g_BlockIsTorchPlaceable[E_BLOCK_QUARTZ_BLOCK] = true; - g_BlockIsTorchPlaceable[E_BLOCK_REDSTONE_LAMP_OFF] = true; - g_BlockIsTorchPlaceable[E_BLOCK_REDSTONE_LAMP_ON] = true; - g_BlockIsTorchPlaceable[E_BLOCK_REDSTONE_ORE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_REDSTONE_ORE_GLOWING] = true; - g_BlockIsTorchPlaceable[E_BLOCK_SANDSTONE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_SAND] = true; - g_BlockIsTorchPlaceable[E_BLOCK_SILVERFISH_EGG] = true; - g_BlockIsTorchPlaceable[E_BLOCK_SPONGE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_STAINED_CLAY] = true; - g_BlockIsTorchPlaceable[E_BLOCK_WOOL] = true; - g_BlockIsTorchPlaceable[E_BLOCK_STONE] = true; - g_BlockIsTorchPlaceable[E_BLOCK_STONE_BRICKS] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_BEDROCK] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_BLOCK_OF_COAL] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_BLOCK_OF_REDSTONE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_BOOKCASE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_BRICK] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_CLAY] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_COAL_ORE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_COBBLESTONE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_COMMAND_BLOCK] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_CRAFTING_TABLE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_DIAMOND_BLOCK] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_DIAMOND_ORE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_DIRT] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_DISPENSER] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_DOUBLE_STONE_SLAB] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_DOUBLE_WOODEN_SLAB] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_DROPPER] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_EMERALD_BLOCK] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_EMERALD_ORE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_END_STONE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_FURNACE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_GLOWSTONE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_GOLD_BLOCK] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_GOLD_ORE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_GRASS] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_GRAVEL] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_HARDENED_CLAY] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_HAY_BALE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_HUGE_BROWN_MUSHROOM] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_HUGE_RED_MUSHROOM] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_IRON_BLOCK] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_IRON_ORE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_JACK_O_LANTERN] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_JUKEBOX] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_LAPIS_BLOCK] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_LAPIS_ORE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_LOG] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_MELON] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_MOSSY_COBBLESTONE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_MYCELIUM] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_NETHERRACK] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_NETHER_BRICK] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_NETHER_QUARTZ_ORE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_NOTE_BLOCK] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_OBSIDIAN] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_PACKED_ICE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_PLANKS] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_PUMPKIN] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_QUARTZ_BLOCK] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_REDSTONE_LAMP_OFF] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_REDSTONE_LAMP_ON] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_REDSTONE_ORE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_REDSTONE_ORE_GLOWING] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_SANDSTONE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_SAND] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_SILVERFISH_EGG] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_SPONGE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_STAINED_CLAY] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_WOOL] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_STONE] = true; + g_BlockFullyOccupiesVoxel[E_BLOCK_STONE_BRICKS] = true; } } BlockPropertiesInitializer; diff --git a/src/BlockID.h b/src/BlockID.h index 288719ccf..a6f0e2675 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -909,7 +909,7 @@ extern bool g_BlockPistonBreakable[256]; extern bool g_BlockIsSnowable[256]; extern bool g_BlockRequiresSpecialTool[256]; extern bool g_BlockIsSolid[256]; -extern bool g_BlockIsTorchPlaceable[256]; +extern bool g_BlockFullyOccupiesVoxel[256]; diff --git a/src/Blocks/BlockRedstone.h b/src/Blocks/BlockRedstone.h index 1bd9995f2..5ffb77fb6 100644 --- a/src/Blocks/BlockRedstone.h +++ b/src/Blocks/BlockRedstone.h @@ -20,7 +20,7 @@ public: virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override { - return ((a_RelY > 0) && g_BlockIsTorchPlaceable[a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)]); + return ((a_RelY > 0) && g_BlockFullyOccupiesVoxel[a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)]); } diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h index 9e543dfd7..faba9c4f5 100644 --- a/src/Blocks/BlockTorch.h +++ b/src/Blocks/BlockTorch.h @@ -98,7 +98,7 @@ public: static bool CanBePlacedOn(BLOCKTYPE a_BlockType, char a_BlockFace) { - if ( !g_BlockIsTorchPlaceable[a_BlockType] ) + if ( !g_BlockFullyOccupiesVoxel[a_BlockType] ) { return (a_BlockFace == BLOCK_FACE_TOP); // Allow placement only when torch upright (for glass, etc.); exceptions won't even be sent by client, no need to handle } @@ -127,7 +127,7 @@ public: { return i; } - else if ((g_BlockIsTorchPlaceable[BlockInQuestion]) && (i != BLOCK_FACE_BOTTOM)) + else if ((g_BlockFullyOccupiesVoxel[BlockInQuestion]) && (i != BLOCK_FACE_BOTTOM)) { // Otherwise, if block in that direction is torch placeable and we haven't gotten to it via the bottom face, return that face return i; @@ -161,7 +161,7 @@ public: // No need to check for upright orientation, it was done when the torch was placed return true; } - else if ( !g_BlockIsTorchPlaceable[BlockInQuestion] ) + else if ( !g_BlockFullyOccupiesVoxel[BlockInQuestion] ) { return false; } diff --git a/src/Defines.h b/src/Defines.h index 534802d55..9bbe1055d 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -41,8 +41,8 @@ extern bool g_BlockRequiresSpecialTool[256]; /// Is this block solid (player cannot walk through)? extern bool g_BlockIsSolid[256]; -/// Can torches be placed on this block? -extern bool g_BlockIsTorchPlaceable[256]; +/// Does this block fully occupy it's voxel - is it a 'full' block? +extern bool g_BlockFullyOccupiesVoxel[256]; /// Experience Orb setup enum diff --git a/src/Items/ItemRedstoneDust.h b/src/Items/ItemRedstoneDust.h index 38bf00ba6..de90c8075 100644 --- a/src/Items/ItemRedstoneDust.h +++ b/src/Items/ItemRedstoneDust.h @@ -27,7 +27,7 @@ public: BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { - if (!g_BlockIsTorchPlaceable[a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)]) // Some solid blocks, such as cocoa beans, are not suitable for dust + if (!g_BlockFullyOccupiesVoxel[a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)]) // Some solid blocks, such as cocoa beans, are not suitable for dust { return false; } From 6b25ef4fa30d9b85188daad5bbb89b1d5c6f27e1 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 11 Jan 2014 01:52:14 +0000 Subject: [PATCH 4/6] Fixed a door bug and reduced code Doors wouldn't get powered by repeaters, and some blocks, like glass, were viable middle blocks when they shouldn't have been. --- src/Simulator/RedstoneSimulator.h | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h index 4fe8b59b3..1e92eccb4 100644 --- a/src/Simulator/RedstoneSimulator.h +++ b/src/Simulator/RedstoneSimulator.h @@ -158,25 +158,7 @@ private: /* ====== Misc Functions ====== */ /** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */ - inline static bool IsViableMiddleBlock(BLOCKTYPE Block) - { - if (!g_BlockIsSolid[Block]) { return false; } - - switch (Block) - { - // Add SOLID but not viable middle blocks here - case E_BLOCK_PISTON: - case E_BLOCK_PISTON_EXTENSION: - case E_BLOCK_STICKY_PISTON: - case E_BLOCK_REDSTONE_REPEATER_ON: - case E_BLOCK_REDSTONE_REPEATER_OFF: - case E_BLOCK_DAYLIGHT_SENSOR: - { - return false; - } - default: return true; - } - } + inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { return g_BlockFullyOccupiesVoxel[Block]; } /** Returns if a block is a mechanism (something that accepts power and does something) */ inline static bool IsMechanism(BLOCKTYPE Block) From ff573816314deba24916fd3f5ae7dbf42acea360 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 11 Jan 2014 14:26:18 +0000 Subject: [PATCH 5/6] Did some stuff with the vectors --- src/Simulator/RedstoneSimulator.cpp | 49 ++++++++++------------------- 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp index 742d8ed2b..6ab915d03 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -52,18 +52,18 @@ void cRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChu // Every time a block is changed (AddBlock called), we want to go through all lists and check to see if the coordiantes stored within are still valid // Checking only when a block is changed, as opposed to every tick, also improves performance - for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end();) + for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) { if (!itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { - ++itr; continue; } if (!IsPotentialSource(Block)) { LOGD("cRedstoneSimulator: 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 = m_PoweredBlocks.erase(itr); + m_PoweredBlocks.erase(itr); + break; } else if ( // Changeable sources @@ -75,14 +75,15 @@ void cRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChu ) { LOGD("cRedstoneSimulator: 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 = m_PoweredBlocks.erase(itr); + m_PoweredBlocks.erase(itr); + break; } else if (Block == E_BLOCK_DAYLIGHT_SENSOR) { if (!a_Chunk->IsLightValid()) { m_World.QueueLightChunk(a_Chunk->GetPosX(), a_Chunk->GetPosZ()); - ++itr; + break; } else { @@ -92,28 +93,22 @@ void cRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChu if (a_Chunk->GetTimeAlteredLight(SkyLight) <= 8) // Could use SkyLight - m_World.GetSkyDarkness(); { LOGD("cRedstoneSimulator: Erased daylight sensor from powered blocks list due to insufficient light level"); - itr = m_PoweredBlocks.erase(itr); - } - else - { - ++itr; + m_PoweredBlocks.erase(itr); + break; } } } - else - { - ++itr; - } } - for (LinkedBlocksList::iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end();) + for (LinkedBlocksList::iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) { if (itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { if (!IsPotentialSource(Block)) { LOGD("cRedstoneSimulator: 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 = m_LinkedPoweredBlocks.erase(itr); + m_LinkedPoweredBlocks.erase(itr); + break; } else if ( // Things that can send power through a block but which depends on meta @@ -123,11 +118,8 @@ void cRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChu ) { LOGD("cRedstoneSimulator: 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 = m_LinkedPoweredBlocks.erase(itr); - } - else - { - ++itr; + m_LinkedPoweredBlocks.erase(itr); + break; } } else if (itr->a_MiddlePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) @@ -135,16 +127,9 @@ void cRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChu if (!IsViableMiddleBlock(Block)) { LOGD("cRedstoneSimulator: 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 = m_LinkedPoweredBlocks.erase(itr); + m_LinkedPoweredBlocks.erase(itr); + break; } - else - { - ++itr; - } - } - else - { - ++itr; } } @@ -158,7 +143,7 @@ void cRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChu if (!IsAllowedBlock(Block)) { LOGD("cRedstoneSimulator: Erased block @ {%i, %i, %i} from toggleable simulated list as it is no longer redstone", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); - itr = m_SimulatedPlayerToggleableBlocks.erase(itr); + m_SimulatedPlayerToggleableBlocks.erase(itr); break; } } @@ -172,7 +157,7 @@ void cRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChu if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF)) { - itr = m_RepeatersDelayList.erase(itr); + m_RepeatersDelayList.erase(itr); break; } } From 318c353ee482be9341bd22d1b22b326d8ddd2d31 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 11 Jan 2014 21:32:42 +0000 Subject: [PATCH 6/6] Fixed rails powering --- src/Simulator/RedstoneSimulator.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h index 1e92eccb4..63a5be3d3 100644 --- a/src/Simulator/RedstoneSimulator.h +++ b/src/Simulator/RedstoneSimulator.h @@ -194,6 +194,7 @@ private: { switch (Block) { + case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_DAYLIGHT_SENSOR: case E_BLOCK_WOODEN_BUTTON: case E_BLOCK_STONE_BUTTON: @@ -231,6 +232,7 @@ private: case E_BLOCK_LEVER: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_NOTE_BLOCK: + case E_BLOCK_POWERED_RAIL: case E_BLOCK_REDSTONE_LAMP_OFF: case E_BLOCK_REDSTONE_LAMP_ON: case E_BLOCK_REDSTONE_REPEATER_OFF: