diff --git a/src/BlockID.cpp b/src/BlockID.cpp index b609af571..69a3a817c 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]; @@ -491,7 +491,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++) @@ -791,67 +791,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 899336fa6..b31c589b9 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -906,7 +906,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/ChunkDef.h b/src/ChunkDef.h index edeb7c0a0..d1288994c 100644 --- a/src/ChunkDef.h +++ b/src/ChunkDef.h @@ -520,8 +520,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/Defines.h b/src/Defines.h index c75effa44..cc04d8026 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; } 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..6ab915d03 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -44,83 +44,46 @@ 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))) + // 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(); ++itr) { - return; - } - - // 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))) { 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()); - itr = m_PoweredBlocks.erase(itr); + 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); + m_PoweredBlocks.erase(itr); + break; } 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()); - itr = m_PoweredBlocks.erase(itr); + 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); + m_PoweredBlocks.erase(itr); + break; } - 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); - ++itr; - continue; + m_World.QueueLightChunk(a_Chunk->GetPosX(), a_Chunk->GetPosZ()); + break; } else { @@ -130,126 +93,125 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c 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; - continue; + m_PoweredBlocks.erase(itr); + break; } } } - else if ((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (DestBlockType == E_BLOCK_REDSTONE_WIRE)) + } + + for (LinkedBlocksList::iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) + { + if (itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { - // 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); + 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); + m_LinkedPoweredBlocks.erase(itr); + break; + } + 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); + m_LinkedPoweredBlocks.erase(itr); + break; + } } - else + else if (itr->a_MiddlePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { - ++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); + m_LinkedPoweredBlocks.erase(itr); + break; + } } } - // 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();) + for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end(); ++itr) { - 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_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; } - if (SourceBlockType != itr->a_SourceBlock) + if (!IsAllowedBlock(Block)) { - 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); - } - else - { - ++itr; + 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); + m_SimulatedPlayerToggleableBlocks.erase(itr); + break; } } - for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.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; } - else if (!IsAllowedBlock(SourceBlockType)) + + if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF)) { - LOGD("cRedstoneSimulator: Erased block %s from toggleable simulated list as block is no longer redstone", ItemToFullString(SourceBlockType).c_str()); - itr = m_SimulatedPlayerToggleableBlocks.erase(itr); - } - else - { - ++itr; + m_RepeatersDelayList.erase(itr); + break; } } - for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end();) + cRedstoneSimulatorChunkData & ChunkData = a_Chunk->GetRedstoneSimulatorData(); + for (cRedstoneSimulatorChunkData::iterator itr = ChunkData.begin(); itr != ChunkData.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->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) // We are at an entry matching the current (changed) block { - continue; + 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 ((SourceBlockType != E_BLOCK_REDSTONE_REPEATER_ON) && (SourceBlockType != E_BLOCK_REDSTONE_REPEATER_OFF)) - { - itr = m_RepeatersDelayList.erase(itr); - continue; - } - - ++itr; } - for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(), end = ChunkData.end(); dataitr != end;) + if (!IsAllowedBlock(Block)) { - BLOCKTYPE BlockType = a_Chunk->GetBlock(dataitr->x, dataitr->y, dataitr->z); - if (!IsAllowedBlock(BlockType)) - { - dataitr = ChunkData.erase(dataitr); - continue; - } + return; + } - // PoweredBlock and LinkedPoweredBlock list was fine, now to the actual handling + 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::const_iterator dataitr = ChunkData.begin(); dataitr != ChunkData.end(); ++dataitr) + { 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 +224,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 +248,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,18 +267,16 @@ 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; } } - - ++dataitr; } } @@ -487,7 +447,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 +506,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 +654,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++; } } @@ -781,48 +742,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); } } } @@ -1188,6 +1121,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 +1293,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 +1309,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 +1333,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 +1351,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..63a5be3d3 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,102 +78,89 @@ 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 - inline static bool IsViableMiddleBlock(BLOCKTYPE Block) - { - if (!g_BlockIsSolid[Block]) { return false; } + /** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */ + inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { return g_BlockFullyOccupiesVoxel[Block]; } - 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; - } - } - - /// 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,16 +189,16 @@ 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) { + case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_DAYLIGHT_SENSOR: case E_BLOCK_WOODEN_BUTTON: case E_BLOCK_STONE_BUTTON: case E_BLOCK_REDSTONE_WIRE: - case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_LEVER: case E_BLOCK_REDSTONE_REPEATER_ON: @@ -227,7 +211,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) @@ -248,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: