diff options
-rw-r--r-- | source/Blocks/BlockButton.cpp | 4 | ||||
-rw-r--r-- | source/Blocks/BlockButton.h | 7 | ||||
-rw-r--r-- | source/Blocks/BlockLever.cpp | 2 | ||||
-rw-r--r-- | source/Blocks/BlockLever.h | 47 | ||||
-rw-r--r-- | source/Simulator/RedstoneSimulator.cpp | 91 | ||||
-rw-r--r-- | source/Simulator/RedstoneSimulator.h | 27 |
6 files changed, 108 insertions, 70 deletions
diff --git a/source/Blocks/BlockButton.cpp b/source/Blocks/BlockButton.cpp index 19b055b62..a48e82f4d 100644 --- a/source/Blocks/BlockButton.cpp +++ b/source/Blocks/BlockButton.cpp @@ -18,13 +18,13 @@ cBlockButtonHandler::cBlockButtonHandler(BLOCKTYPE a_BlockType) void cBlockButtonHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) { // Flip the ON bit on/off using the XOR bitwise operation - NIBBLETYPE Meta = ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08) & 0x0f); + NIBBLETYPE Meta = (a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) | 0x08); a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, Meta); a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f); // Queue a button reset (unpress) - a_World->QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08) & 0x0f), m_BlockType == E_BLOCK_STONE_BUTTON ? 20 : 30); + a_World->QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, (a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x07), m_BlockType == E_BLOCK_STONE_BUTTON ? 20 : 30); } diff --git a/source/Blocks/BlockButton.h b/source/Blocks/BlockButton.h index 15649acc0..e2c60002b 100644 --- a/source/Blocks/BlockButton.h +++ b/source/Blocks/BlockButton.h @@ -81,10 +81,13 @@ public: virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override { - NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ); + NIBBLETYPE Meta; + a_Chunk.UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ, Meta); AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true); - return (a_RelY > 0) && (g_BlockIsSolid[a_Chunk.GetBlock(a_RelX, a_RelY, a_RelZ)]); + BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn); + + return (a_RelY > 0) && (g_BlockIsSolid[BlockIsOn]); } } ; diff --git a/source/Blocks/BlockLever.cpp b/source/Blocks/BlockLever.cpp index 2739fa3a9..c482b0246 100644 --- a/source/Blocks/BlockLever.cpp +++ b/source/Blocks/BlockLever.cpp @@ -20,7 +20,7 @@ cBlockLeverHandler::cBlockLeverHandler(BLOCKTYPE a_BlockType) void cBlockLeverHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) { // Flip the ON bit on/off using the XOR bitwise operation - NIBBLETYPE Meta = ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08) & 0x0f); + NIBBLETYPE Meta = (a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08); a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, Meta); a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f); diff --git a/source/Blocks/BlockLever.h b/source/Blocks/BlockLever.h index fe7ecdf7e..5e6a3bd1e 100644 --- a/source/Blocks/BlockLever.h +++ b/source/Blocks/BlockLever.h @@ -46,13 +46,13 @@ public: // Determine lever direction: switch (a_Dir) { - case BLOCK_FACE_TOP: return 0x6; - case BLOCK_FACE_EAST: return 0x1; - case BLOCK_FACE_WEST: return 0x2; - case BLOCK_FACE_SOUTH: return 0x3; - case BLOCK_FACE_NORTH: return 0x4; - case BLOCK_FACE_BOTTOM: return 0x0; - default: return 0x6; + case BLOCK_FACE_YP: return 0x6; + case BLOCK_FACE_XP: return 0x1; + case BLOCK_FACE_XM: return 0x2; + case BLOCK_FACE_ZP: return 0x3; + case BLOCK_FACE_ZM: return 0x4; + case BLOCK_FACE_YM: return 0x0; + default: return 0x6; } } @@ -61,6 +61,39 @@ public: { return "step.wood"; } + + + inline static NIBBLETYPE BlockMetaDataToBlockFace(NIBBLETYPE a_Meta) + { + switch (a_Meta & 0x7) + { + case 0x1: return BLOCK_FACE_XP; + case 0x2: return BLOCK_FACE_XM; + case 0x3: return BLOCK_FACE_ZP; + case 0x4: return BLOCK_FACE_ZM; + case 0x5: + case 0x6: return BLOCK_FACE_YP; + case 0x7: + case 0x0: return BLOCK_FACE_YM; + default: + { + ASSERT(!"Unhandled block meta!"); + return BLOCK_FACE_NONE; + } + } + } + + + virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + { + NIBBLETYPE Meta; + a_Chunk.UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ, Meta); + + AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true); + BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn); + + return (a_RelY > 0) && (g_BlockIsSolid[BlockIsOn]); + } } ; diff --git a/source/Simulator/RedstoneSimulator.cpp b/source/Simulator/RedstoneSimulator.cpp index e9f9eea0c..15d954313 100644 --- a/source/Simulator/RedstoneSimulator.cpp +++ b/source/Simulator/RedstoneSimulator.cpp @@ -85,7 +85,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c continue; } - // Check to see if PoweredBlocks have invalid items (source is air or an unpowered source) + // Check to see if PoweredBlocks have invalid items (source is air or unpowered) for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end();) { sPoweredBlocks & Change = *itr; @@ -494,47 +494,46 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl void cRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState) { + // We do this so that the repeater can continually update block power status (without being affected by it's own block type, which would happen if the block powering code was in an IF statement) + bool IsOn = false; + if (a_MyState == E_BLOCK_REDSTONE_REPEATER_ON) { IsOn = true; } + NIBBLETYPE a_Meta = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); - if (a_MyState == E_BLOCK_REDSTONE_REPEATER_OFF) + + if (IsRepeaterPowered(a_BlockX, a_BlockY, a_BlockZ, a_Meta & 0x3)) { - if (IsRepeaterPowered(a_BlockX, a_BlockY, a_BlockZ, a_Meta & 0x3)) + if (!IsOn) { m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON, a_Meta); } // Only set if not on; SetBlock otherwise server doesn't set it in time for SimulateChunk's invalidation + switch (a_Meta & 0x3) // We only want the direction (bottom) bits { - m_World.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON, a_Meta); - switch (a_Meta & 0x3) // We only want the direction (bottom) bits + case 0x0: { - case 0x0: - { - SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON); - SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_REPEATER_ON); - break; - } - case 0x1: - { - SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON); - SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_REPEATER_ON); - break; - } - case 0x2: - { - SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON); - SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_REPEATER_ON); - break; - } - case 0x3: - { - SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON); - SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_REPEATER_ON); - break; - } + SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON); + SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_REPEATER_ON); + break; + } + case 0x1: + { + SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON); + SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_REPEATER_ON); + break; + } + case 0x2: + { + SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON); + SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_REPEATER_ON); + break; + } + case 0x3: + { + SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON); + SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_REPEATER_ON); + break; } } } else { - if (!IsRepeaterPowered(a_BlockX, a_BlockY, a_BlockZ, a_Meta & 0x3)) - { - m_World.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta); - } + if (IsOn) { m_World.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta); } } return; } @@ -685,24 +684,7 @@ void cRedstoneSimulator::HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BL { if ((m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x08) == 0x08) { - static const struct // Define which directions the rail can power (all sides) - { - int x, y, z; - } gCrossCoords[] = - { - { 1, 0, 0}, - {-1, 0, 0}, - { 0, 0, 1}, - { 0, 0, -1}, - { 0, 1, 0}, - { 0,-1, 0}, - } ; - - for (int i = 0; i < ARRAYCOUNT(gCrossCoords); i++) - { - // Power everything - SetBlockPowered(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, a_MyType); - } + SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, a_MyType); } break; } @@ -834,7 +816,6 @@ void cRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, i case BLOCK_FACE_XM: { BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ); - if (!g_BlockIsSolid[MiddleBlock]) { return; } // Nothing can link power something through a non-solid block if (a_SourceType == E_BLOCK_REDSTONE_WIRE) // Wires can't power another wire through a block { @@ -872,7 +853,6 @@ void cRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, i case BLOCK_FACE_XP: { BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ); - if (!g_BlockIsSolid[MiddleBlock]) { return; } if (a_SourceType == E_BLOCK_REDSTONE_WIRE) { @@ -910,7 +890,6 @@ void cRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, i case BLOCK_FACE_YM: { BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ); - if (!g_BlockIsSolid[MiddleBlock]) { return; } if (a_SourceType == E_BLOCK_REDSTONE_WIRE) { @@ -948,7 +927,6 @@ void cRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, i case BLOCK_FACE_YP: { BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ); - if (!g_BlockIsSolid[MiddleBlock]) { return; } if (a_SourceType == E_BLOCK_REDSTONE_WIRE) { @@ -986,7 +964,6 @@ void cRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, i case BLOCK_FACE_ZM: { BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1); - if (!g_BlockIsSolid[MiddleBlock]) { return; } if (a_SourceType == E_BLOCK_REDSTONE_WIRE) { @@ -1024,7 +1001,6 @@ void cRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, i case BLOCK_FACE_ZP: { BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1); - if (!g_BlockIsSolid[MiddleBlock]) { return; } if (a_SourceType == E_BLOCK_REDSTONE_WIRE) { @@ -1122,6 +1098,7 @@ void cRedstoneSimulator::SetBlockLinkedPowered(int a_BlockX, int a_BlockY, int a { if (m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_AIR) { return; } // Don't set air, fixes some bugs (wires powering themselves) if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) { return; } // Check for duplicates + if (!IsViableMiddleBlock(m_World.GetBlock(a_MiddleX, a_MiddleY, a_MiddleZ))) { return; } // See if middle block is viable sLinkedPoweredBlocks RC; RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ); diff --git a/source/Simulator/RedstoneSimulator.h b/source/Simulator/RedstoneSimulator.h index ab88f51e2..10d87505c 100644 --- a/source/Simulator/RedstoneSimulator.h +++ b/source/Simulator/RedstoneSimulator.h @@ -106,7 +106,7 @@ private: ///<summary>Marks all blocks immediately surrounding a coordinate as powered</summary> void SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock); - ///<summary>Returns if a coordiante is powered or linked powered</summary> + ///<summary>Returns if a coordinate is powered or linked powered</summary> bool AreCoordsPowered(int a_BlockX, int a_BlockY, int a_BlockZ); ///<summary>Returns if a repeater is powered</summary> bool IsRepeaterPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta); @@ -117,6 +117,29 @@ private: bool IsButtonOn(NIBBLETYPE a_BlockMeta); /* ============================== */ + /* ====== Misc Functions ====== */ + + ///<summary>Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation</summary> + 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_REDSTONE_REPEATER_ON: + case E_BLOCK_REDSTONE_REPEATER_OFF: + { + return false; + } + default: + { + return true; + } + } + } + + ///<summary>Returns if a block is a mechanism (something that accepts power and does something)</summary> inline static bool IsMechanism(BLOCKTYPE Block) { switch (Block) @@ -145,6 +168,7 @@ private: } } + ///<summary>Returns if a block has the potential to output power</summary> inline static bool IsPotentialSource(BLOCKTYPE Block) { switch (Block) @@ -167,6 +191,7 @@ private: } } + ///<summary>Returns if a block is any sort of redstone device</summary> inline static bool IsRedstone(BLOCKTYPE Block) { switch (Block) |