diff options
author | Alexander Harkness <bearbin@gmail.com> | 2013-11-24 15:19:41 +0100 |
---|---|---|
committer | Alexander Harkness <bearbin@gmail.com> | 2013-11-24 15:19:41 +0100 |
commit | 675b4aa878f16291ce33fced48a2bc7425f635ae (patch) | |
tree | 409914df27a98f65adf866da669429c4de141b6f /source/Simulator/RedstoneSimulator.cpp | |
parent | LineBlockTracer: Using the coord-based block faces. (diff) | |
download | cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.gz cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.bz2 cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.lz cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.xz cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.zst cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.zip |
Diffstat (limited to 'source/Simulator/RedstoneSimulator.cpp')
-rw-r--r-- | source/Simulator/RedstoneSimulator.cpp | 1178 |
1 files changed, 0 insertions, 1178 deletions
diff --git a/source/Simulator/RedstoneSimulator.cpp b/source/Simulator/RedstoneSimulator.cpp deleted file mode 100644 index 8526a888e..000000000 --- a/source/Simulator/RedstoneSimulator.cpp +++ /dev/null @@ -1,1178 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "RedstoneSimulator.h" -#include "../BlockEntities/DropSpenserEntity.h" -#include "../Blocks/BlockTorch.h" -#include "../Piston.h" -#include "../World.h" -#include "../BlockID.h" -#include "../Chunk.h" -#include "../Entities/TNTEntity.h" - - - - - -cRedstoneSimulator::cRedstoneSimulator(cWorld & a_World) - : super(a_World) -{ -} - - - - - -cRedstoneSimulator::~cRedstoneSimulator() -{ -} - - - - - -void cRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) -{ - if (a_Chunk == NULL) - { - return; - } - int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width; - int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width; - - // Check if any close neighbor is redstone-related: - int MinY = (a_BlockY > 0) ? -1 : 0; - int MaxY = (a_BlockY < cChunkDef::Height - 1) ? 1 : 0; - for (int y = MinY; y <= MaxY; y++) for (int x = -1; x < 2; x++) for (int z = -1; z < 2; z++) - { - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - if (!a_Chunk->UnboundedRelGetBlock(RelX + x, a_BlockY + y, RelZ + z, BlockType, BlockMeta)) - { - continue; - } - switch (BlockType) - { - case E_BLOCK_PISTON: - case E_BLOCK_STICKY_PISTON: - case E_BLOCK_DISPENSER: - case E_BLOCK_DROPPER: - case E_BLOCK_REDSTONE_LAMP_OFF: - case E_BLOCK_REDSTONE_LAMP_ON: - case E_BLOCK_REDSTONE_REPEATER_OFF: - case E_BLOCK_REDSTONE_REPEATER_ON: - case E_BLOCK_REDSTONE_TORCH_OFF: - case E_BLOCK_REDSTONE_TORCH_ON: - case E_BLOCK_REDSTONE_WIRE: - case E_BLOCK_LEVER: - case E_BLOCK_STONE_BUTTON: - case E_BLOCK_WOODEN_BUTTON: - case E_BLOCK_TRIPWIRE_HOOK: - { - m_Blocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ)); - return; - } - } // switch (BlockType) - } // for y, x, z - neighbors -} - - - - - -void cRedstoneSimulator::Simulate(float a_Dt) -{ - // Toggle torches on/off - while (!m_RefreshTorchesAround.empty()) - { - Vector3i pos = m_RefreshTorchesAround.front(); - m_RefreshTorchesAround.pop_front(); - - RefreshTorchesAround(pos); - } - - // Set repeaters to correct values, and decrement ticks - for (RepeaterList::iterator itr = m_SetRepeaters.begin(); itr != m_SetRepeaters.end();) - { - if (--itr->Ticks > 0) - { - // Not yet, move to next item in the list - ++itr; - continue; - } - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - m_World.GetBlockTypeMeta(itr->Position.x, itr->Position.y, itr->Position.z, BlockType, BlockMeta); - if (itr->bPowerOn && (BlockType == E_BLOCK_REDSTONE_REPEATER_OFF)) - { - m_World.FastSetBlock(itr->Position.x, itr->Position.y, itr->Position.z, E_BLOCK_REDSTONE_REPEATER_ON, BlockMeta); - m_Blocks.push_back(itr->Position); - } - else if (!itr->bPowerOn && (BlockType == E_BLOCK_REDSTONE_REPEATER_ON)) - { - m_World.FastSetBlock(itr->Position.x, itr->Position.y, itr->Position.z, E_BLOCK_REDSTONE_REPEATER_OFF, BlockMeta); - m_Blocks.push_back(itr->Position); - } - - if (itr->bPowerOffNextTime) - { - itr->bPowerOn = false; - itr->bPowerOffNextTime = false; - itr->Ticks = 10; // TODO: Look up actual ticks from block metadata - ++itr; - } - else - { - itr = m_SetRepeaters.erase(itr); - } - } - - // Handle changed blocks - { - cCSLock Lock(m_CS); - std::swap(m_Blocks, m_BlocksBuffer); - } - for (BlockList::iterator itr = m_BlocksBuffer.begin(); itr != m_BlocksBuffer.end(); ++itr) - { - HandleChange(*itr); - } - m_BlocksBuffer.clear(); -} - - - - - -void cRedstoneSimulator::RefreshTorchesAround(const Vector3i & a_BlockPos) -{ - static Vector3i Surroundings [] = { - Vector3i(-1, 0, 0), - Vector3i(1, 0, 0), - Vector3i(0, 0,-1), - Vector3i(0, 0, 1), - Vector3i(0, 1, 0), // Also toggle torch on top - }; - BLOCKTYPE TargetBlockType = E_BLOCK_REDSTONE_TORCH_ON; - BLOCKTYPE TargetRepeaterType = E_BLOCK_REDSTONE_REPEATER_OFF; - if (IsPowered(a_BlockPos, true)) - { - TargetBlockType = E_BLOCK_REDSTONE_TORCH_OFF; - TargetRepeaterType = E_BLOCK_REDSTONE_REPEATER_ON; - //Make TNT Explode when it gets powered. - if (m_World.GetBlock(a_BlockPos) == E_BLOCK_TNT) - { - m_World.BroadcastSoundEffect("random.fuse", a_BlockPos.x * 8, a_BlockPos.y * 8, a_BlockPos.z * 8, 0.5f, 0.6f); - m_World.SpawnPrimedTNT(a_BlockPos.x + 0.5, a_BlockPos.y + 0.5, a_BlockPos.z + 0.5, 4); // 4 seconds to boom - m_World.SetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_AIR, 0); - } - //Turn a redstone lamp on when it gets powered. - if (m_World.GetBlock(a_BlockPos) == E_BLOCK_REDSTONE_LAMP_OFF) - { - m_World.SetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_REDSTONE_LAMP_ON, 0); - } - //if (m_World.GetBlock(a_BlockPos) == E_BLOCK_DIRT) - //{ - // m_World.FastSetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_STONE, 0); - //} - } - else - { - //Turn a redstone lamp off when it gets powered. - if (m_World.GetBlock(a_BlockPos) == E_BLOCK_REDSTONE_LAMP_ON) - { - m_World.SetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_REDSTONE_LAMP_OFF, 0); - } - //if (m_World.GetBlock(a_BlockPos) == E_BLOCK_STONE) - //{ - // m_World.FastSetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_DIRT, 0); - //} - } - - for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i) - { - Vector3i TorchPos = a_BlockPos + Surroundings[i]; - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - m_World.GetBlockTypeMeta(TorchPos.x, TorchPos.y, TorchPos.z, BlockType, BlockMeta); - switch (BlockType) - { - case E_BLOCK_REDSTONE_TORCH_ON: - case E_BLOCK_REDSTONE_TORCH_OFF: - { - if (BlockType != TargetBlockType) - { - if (cBlockTorchHandler::IsAttachedTo(TorchPos, BlockMeta, a_BlockPos)) - { - m_World.FastSetBlock(TorchPos.x, TorchPos.y, TorchPos.z, TargetBlockType, BlockMeta); - m_Blocks.push_back(TorchPos); - } - } - break; - } - case E_BLOCK_REDSTONE_REPEATER_ON: - case E_BLOCK_REDSTONE_REPEATER_OFF: - { - if ((BlockType != TargetRepeaterType) && IsRepeaterPointingAway(TorchPos, BlockMeta, a_BlockPos)) - { - SetRepeater(TorchPos, 10, (TargetRepeaterType == E_BLOCK_REDSTONE_REPEATER_ON)); - } - break; - } - } // switch (BlockType) - } // for i - Surroundings[] -} - - - - - -void cRedstoneSimulator::HandleChange(const Vector3i & a_BlockPos) -{ - std::deque< Vector3i > SpreadStack; - - static const Vector3i Surroundings[] = { - Vector3i(1, 0, 0), - Vector3i(1, 1, 0), - Vector3i(1,-1, 0), - Vector3i(-1, 0, 0), - Vector3i(-1, 1, 0), - Vector3i(-1,-1, 0), - Vector3i(0, 0, 1), - Vector3i(0, 1, 1), - Vector3i(0,-1, 1), - Vector3i(0, 0,-1), - Vector3i(0, 1,-1), - Vector3i(0,-1,-1), - Vector3i(0,-1, 0), - }; - - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta); - - // First check whether torch should be on or off - switch (BlockType) - { - case E_BLOCK_REDSTONE_TORCH_ON: - case E_BLOCK_REDSTONE_TORCH_OFF: - { - static const Vector3i Surroundings [] = { - Vector3i(-1, 0, 0), - Vector3i(1, 0, 0), - Vector3i(0, 0,-1), - Vector3i(0, 0, 1), - Vector3i(0,-1, 0), - }; - for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i) - { - Vector3i pos = a_BlockPos + Surroundings[i]; - BLOCKTYPE OtherBlock = m_World.GetBlock(pos); - if ( - (OtherBlock != E_BLOCK_AIR) && - (OtherBlock != E_BLOCK_REDSTONE_TORCH_ON) && - (OtherBlock != E_BLOCK_REDSTONE_TORCH_OFF) - ) - { - RefreshTorchesAround(pos); - } - } - m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta); - break; - } // case "torches" - - case E_BLOCK_REDSTONE_REPEATER_ON: - case E_BLOCK_REDSTONE_REPEATER_OFF: - { - // Check if repeater is powered by a 'powered block' (not wires/torch) - Vector3i Direction = GetRepeaterDirection(BlockMeta); - Vector3i pos = a_BlockPos - Direction; // NOTE: It's minus Direction - BLOCKTYPE OtherBlock = m_World.GetBlock(pos); - if ( - (OtherBlock != E_BLOCK_AIR) && - (OtherBlock != E_BLOCK_REDSTONE_TORCH_ON) && - (OtherBlock != E_BLOCK_REDSTONE_TORCH_OFF) && - (OtherBlock != E_BLOCK_REDSTONE_WIRE) - ) - { - RefreshTorchesAround(pos); - } - else - { - SetRepeater(a_BlockPos, 10, IsPowered(a_BlockPos, false)); - } - m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta); - break; - } - } // switch (BlockType) - - BlockList Sources; - switch (BlockType) - { - case E_BLOCK_REDSTONE_TORCH_ON: - { - // If torch is still on, use it as a source - Sources.push_back(a_BlockPos); - break; - } - - case E_BLOCK_REDSTONE_REPEATER_ON: - { - // Repeater only spreads charge right in front, and up to one block up: - static const Vector3i Surroundings [] = { - Vector3i(0, 0, 0), - Vector3i(0, 1, 0), - }; - Vector3i Direction = GetRepeaterDirection(BlockMeta); - for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i) - { - Vector3i pos = a_BlockPos + Direction + Surroundings[i]; - if (PowerBlock(pos, a_BlockPos, 0xf)) - { - SpreadStack.push_back(pos); - } - } - break; - } // case E_BLOCK_REDSTONE_REPEATER_ON - - case E_BLOCK_LEVER: - { - // Adding lever to the source queue - if (cRedstoneSimulator::IsLeverOn(BlockMeta)) - { - Sources.push_back(a_BlockPos); - } - break; - } // case E_BLOCK_LEVER - } // switch (BlockType) - - // Power all blocks legally connected to the sources - if (BlockType != E_BLOCK_REDSTONE_REPEATER_ON) - { - BlockList NewSources = RemoveCurrent(a_BlockPos); - Sources.insert(Sources.end(), NewSources.begin(), NewSources.end()); - while (!Sources.empty()) - { - Vector3i SourcePos = Sources.back(); - Sources.pop_back(); - - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - m_World.GetBlockTypeMeta(SourcePos.x, SourcePos.y, SourcePos.z, BlockType, BlockMeta); - switch (BlockType) - { - case E_BLOCK_LEVER: // Treating lever as a torch - case E_BLOCK_REDSTONE_TORCH_OFF: - case E_BLOCK_REDSTONE_TORCH_ON: - { - static Vector3i Surroundings [] = { - Vector3i(-1, 0, 0), - Vector3i(1, 0, 0), - Vector3i(0, 0,-1), - Vector3i(0, 0, 1), - }; - for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i) - { - Vector3i OtherPos = SourcePos + Surroundings[i]; - if (PowerBlock(OtherPos, a_BlockPos, 0xf)) - { - SpreadStack.push_back(OtherPos); // Changed, so add to stack - } - } - break; - } - - case E_BLOCK_REDSTONE_REPEATER_OFF: - case E_BLOCK_REDSTONE_REPEATER_ON: - { - static Vector3i Surroundings [] = { - Vector3i(0, 0, 0), - Vector3i(0, 1, 0), - }; - Vector3i Direction = GetRepeaterDirection(BlockMeta); - for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i) - { - Vector3i pos = SourcePos + Direction + Surroundings[i]; - if (PowerBlock(pos, a_BlockPos, 0xf)) - { - SpreadStack.push_back(pos); - } - } - break; - } - } // switch (BlockType) - } // while (Sources[]) - } // if (!repeater_on) - - // Do a floodfill - while (!SpreadStack.empty()) - { - Vector3i pos = SpreadStack.back(); - SpreadStack.pop_back(); - NIBBLETYPE Meta = m_World.GetBlockMeta(pos); - - for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i) - { - Vector3i OtherPos = pos + Surroundings[i]; - if (PowerBlock(OtherPos, pos, Meta - 1)) - { - SpreadStack.push_back(OtherPos); // Changed, so add to stack - } - } - } - - // Only after a redstone area has been completely simulated the redstone entities can react - while (!m_RefreshPistons.empty()) - { - Vector3i pos = m_RefreshPistons.back(); - m_RefreshPistons.pop_back(); - - BLOCKTYPE BlockType = m_World.GetBlock(pos); - switch (BlockType) - { - case E_BLOCK_PISTON: - case E_BLOCK_STICKY_PISTON: - { - if (IsPowered(pos)) - { - cPiston Piston(&m_World); - Piston.ExtendPiston(pos.x, pos.y, pos.z); - } - else - { - cPiston Piston(&m_World); - Piston.RetractPiston(pos.x, pos.y, pos.z); - } - break; - } - } // switch (BlockType) - } // while (m_RefreshPistons[]) - - while (!m_RefreshDropSpensers.empty()) - { - Vector3i pos = m_RefreshDropSpensers.back(); - m_RefreshDropSpensers.pop_back(); - - BLOCKTYPE BlockType = m_World.GetBlock(pos); - if ((BlockType == E_BLOCK_DISPENSER) || (BlockType == E_BLOCK_DROPPER)) - { - class cSetPowerToDropSpenser : - public cDropSpenserCallback - { - bool m_IsPowered; - public: - cSetPowerToDropSpenser(bool a_IsPowered) : m_IsPowered(a_IsPowered) {} - - virtual bool Item(cDropSpenserEntity * a_DropSpenser) override - { - a_DropSpenser->SetRedstonePower(m_IsPowered); - return false; - } - } DrSpSP(IsPowered(pos)); - m_World.DoWithDropSpenserAt(pos.x, pos.y, pos.z, DrSpSP); - } - } -} - - - - - -bool cRedstoneSimulator::PowerBlock(const Vector3i & a_BlockPos, const Vector3i & a_FromBlock, char a_Power) -{ - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta); - switch (BlockType) - { - case E_BLOCK_REDSTONE_WIRE: - { - if (BlockMeta < a_Power) - { - m_World.SetBlockMeta(a_BlockPos, a_Power); - return true; - } - break; - } - - case E_BLOCK_PISTON: - case E_BLOCK_STICKY_PISTON: - { - m_RefreshPistons.push_back(a_BlockPos); - break; - } - - case E_BLOCK_DISPENSER: - case E_BLOCK_DROPPER: - { - m_RefreshDropSpensers.push_back(a_BlockPos); - break; - } - - case E_BLOCK_REDSTONE_REPEATER_OFF: - case E_BLOCK_REDSTONE_REPEATER_ON: - { - if (IsRepeaterPointingAway(a_BlockPos, BlockMeta, a_FromBlock)) - { - SetRepeater(a_BlockPos, 10, true); - } - break; - } - - case E_BLOCK_REDSTONE_LAMP_OFF: - { - m_World.FastSetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_REDSTONE_LAMP_ON, 0); - break; - } - - case E_BLOCK_TNT: - { - m_World.BroadcastSoundEffect("random.fuse", a_BlockPos.x * 8, a_BlockPos.y * 8, a_BlockPos.z * 8, 0.5f, 0.6f); - m_World.SpawnPrimedTNT(a_BlockPos.x + 0.5, a_BlockPos.y + 0.5, a_BlockPos.z + 0.5, 4); // 4 seconds to boom - m_World.SetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_AIR, 0); - break; - } - - default: - { - if ( - (BlockType != E_BLOCK_AIR) && - (BlockType != E_BLOCK_REDSTONE_TORCH_ON) && - (BlockType != E_BLOCK_REDSTONE_TORCH_OFF) && - (BlockType != E_BLOCK_LEVER) // Treating lever as a torch, for refreshing - ) - { - if (IsPowered(a_BlockPos, true)) - { - m_RefreshTorchesAround.push_back(a_BlockPos); - } - } - break; - } - } // switch (BlockType) - - return false; -} - - - - - -int cRedstoneSimulator::UnPowerBlock(const Vector3i & a_BlockPos, const Vector3i & a_FromBlock) -{ - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - if ((a_BlockPos.y < 0) || (a_BlockPos.y >= cChunkDef::Height)) - { - return 0; - } - m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta); - switch (BlockType) - { - case E_BLOCK_REDSTONE_WIRE: - { - if (BlockMeta > 0) - { - m_World.SetBlockMeta(a_BlockPos, 0); - return 1; - } - break; - } - - case E_BLOCK_PISTON: - case E_BLOCK_STICKY_PISTON: - { - m_RefreshPistons.push_back(a_BlockPos); - break; - } - - case E_BLOCK_DISPENSER: - case E_BLOCK_DROPPER: - { - m_RefreshDropSpensers.push_back(a_BlockPos); - break; - } - - case E_BLOCK_REDSTONE_TORCH_ON: - { - return 2; - break; - } - - case E_BLOCK_LEVER: - { - // Check if lever is ON. If it is, report it back as a source - if (cRedstoneSimulator::IsLeverOn(BlockMeta)) - { - return 2; - } - break; - } - - case E_BLOCK_REDSTONE_REPEATER_ON: - { - if ( - IsRepeaterPointingTo(a_BlockPos, BlockMeta, a_FromBlock) || // Repeater is next to wire - IsRepeaterPointingTo(a_BlockPos, BlockMeta, a_FromBlock - Vector3i(0, 1, 0)) // Repeater is below wire - ) - { - return 2; - } - else if (IsRepeaterPointingAway(a_BlockPos, BlockMeta, a_FromBlock)) - { - SetRepeater(a_BlockPos, 10, false); - } - // fall-through: - } - - case E_BLOCK_REDSTONE_REPEATER_OFF: - { - if (IsRepeaterPointingAway(a_BlockPos, BlockMeta, a_FromBlock)) - { - SetRepeater(a_BlockPos, 10, false); - } - break; - } - - case E_BLOCK_REDSTONE_LAMP_ON: - { - m_World.FastSetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_REDSTONE_LAMP_OFF, 0); - break; - } - - default: - { - if ( - (BlockType != E_BLOCK_AIR) && - (BlockType != E_BLOCK_REDSTONE_TORCH_ON) && - (BlockType != E_BLOCK_REDSTONE_TORCH_OFF) && - (BlockType != E_BLOCK_LEVER) - ) - { - if (!IsPowered(a_BlockPos, true)) - { - m_RefreshTorchesAround.push_back(a_BlockPos); - } - } - break; - } - } // switch (BlockType) - - return 0; -} - - - - - -// Removes current from all powered redstone wires until it reaches an energy source. -// Also returns all energy sources it encountered -cRedstoneSimulator::BlockList cRedstoneSimulator::RemoveCurrent(const Vector3i & a_BlockPos) -{ - - - std::deque< Vector3i > SpreadStack; - std::deque< Vector3i > FoundSources; - - Vector3i Surroundings[] = { - Vector3i(1, 0, 0), - Vector3i(1, 1, 0), - Vector3i(1,-1, 0), - Vector3i(-1, 0, 0), - Vector3i(-1, 1, 0), - Vector3i(-1,-1, 0), - Vector3i(0, 0, 1), - Vector3i(0, 1, 1), - Vector3i(0,-1, 1), - Vector3i(0, 0,-1), - Vector3i(0, 1,-1), - Vector3i(0,-1,-1), - Vector3i(0,-1, 0), - }; - - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta); - switch (BlockType) - { - case E_BLOCK_REDSTONE_REPEATER_ON: - case E_BLOCK_REDSTONE_REPEATER_OFF: - { - // Repeaters only spread to their front front and 0 or 1 block up - static Vector3i Surroundings [] = { - Vector3i(0, 0, 0), - Vector3i(0, 1, 0), - }; - Vector3i Direction = GetRepeaterDirection(BlockMeta); - for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i) - { - Vector3i pos = a_BlockPos + Direction + Surroundings[i]; - int RetVal = UnPowerBlock(pos, a_BlockPos); - if (RetVal == 1) - { - // Changed, so add to stack - SpreadStack.push_back(pos); - } - else if (RetVal == 2) - { - FoundSources.push_back(pos); - } - } - break; - } - - case E_BLOCK_REDSTONE_TORCH_OFF: - case E_BLOCK_REDSTONE_TORCH_ON: - case E_BLOCK_LEVER: - { - static Vector3i Surroundings [] = { // Torches only spread on the same level - Vector3i(-1, 0, 0), - Vector3i(1, 0, 0), - Vector3i(0, 0,-1), - Vector3i(0, 0, 1), - }; - - for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i) - { - Vector3i pos = Vector3i(a_BlockPos) + Surroundings[i]; - int RetVal = UnPowerBlock(pos, a_BlockPos); - if (RetVal == 1) - { - SpreadStack.push_back(pos); // Changed, so add to stack - } - else if (RetVal == 2) - { - FoundSources.push_back(pos); - } - } - break; - } - - default: - { - SpreadStack.push_back(a_BlockPos); - break; - } - } // switch (BlockType) - - - while (!SpreadStack.empty()) - { - Vector3i pos = SpreadStack.back(); - SpreadStack.pop_back(); - - for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i) - { - Vector3i OtherPos = pos + Surroundings[i]; - int RetVal = UnPowerBlock(OtherPos, pos); - if (RetVal == 1) - { - SpreadStack.push_back(OtherPos); // Changed, so add to stack - } - else if (RetVal == 2) - { - FoundSources.push_back(OtherPos); - } - } - } - - return FoundSources; -} - - - - - -bool cRedstoneSimulator::IsPowering(const Vector3i & a_PowerPos, const Vector3i & a_BlockPos, eRedstoneDirection a_WireDirection, bool a_bOnlyByWire) -{ - BLOCKTYPE PowerBlock; - NIBBLETYPE PowerMeta; - m_World.GetBlockTypeMeta(a_PowerPos.x, a_PowerPos.y, a_PowerPos.z, PowerBlock, PowerMeta); - - // Filter out powering blocks for a_bOnlyByWire - if ( - !a_bOnlyByWire && ( - (PowerBlock == E_BLOCK_REDSTONE_TORCH_ON) || - (PowerBlock == E_BLOCK_LEVER) - ) - ) - { - return true; - } - - switch (PowerBlock) - { - case E_BLOCK_REDSTONE_REPEATER_ON: - { - // A repeater pointing towards block is regarded as wire - if (IsRepeaterPointingTo(a_PowerPos, PowerMeta, a_BlockPos)) - { - return true; - } - break; - } - - case E_BLOCK_REDSTONE_WIRE: - { - if (PowerMeta > 0) - { - if (GetWireDirection(a_PowerPos) == a_WireDirection) - { - return true; - } - } - break; - } - } // switch (PowerBlock) - - return false; -} - - - - - -bool cRedstoneSimulator::IsPowered(const Vector3i & a_BlockPos, bool a_bOnlyByWire /* = false */) -{ - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta); - if ((BlockType == E_BLOCK_REDSTONE_REPEATER_OFF) || (BlockType == E_BLOCK_REDSTONE_REPEATER_ON)) - { - Vector3i Behind = a_BlockPos - GetRepeaterDirection(BlockMeta); - BLOCKTYPE BehindBlock; - NIBBLETYPE BehindMeta; - m_World.GetBlockTypeMeta(Behind.x, Behind.y, Behind.z, BehindBlock, BehindMeta); - switch (BehindBlock) - { - case E_BLOCK_REDSTONE_TORCH_ON: - case E_BLOCK_LEVER: - { - // _X: TODO: Shouldn't a lever be checked if it is switched on? - return true; - } - case E_BLOCK_REDSTONE_WIRE: - { - return (BehindMeta > 0); - } - case E_BLOCK_REDSTONE_REPEATER_ON: - { - return IsRepeaterPointingTo(Behind, BehindMeta, a_BlockPos); - } - } // switch (BehindBlock) - return false; - } - - if (IsPowering(Vector3i(a_BlockPos.x - 1, a_BlockPos.y, a_BlockPos.z), a_BlockPos, REDSTONE_X_POS, a_bOnlyByWire)) - { - return true; - } - if (IsPowering(Vector3i(a_BlockPos.x + 1, a_BlockPos.y, a_BlockPos.z), a_BlockPos, REDSTONE_X_NEG, a_bOnlyByWire)) - { - return true; - } - if (IsPowering(Vector3i(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z - 1), a_BlockPos, REDSTONE_Z_POS, a_bOnlyByWire)) - { - return true; - } - if (IsPowering(Vector3i(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z + 1), a_BlockPos, REDSTONE_Z_NEG, a_bOnlyByWire)) - { - return true; - } - - // Only wires can power the bottom block - BLOCKTYPE PosYType; - NIBBLETYPE PosYMeta; - m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y + 1, a_BlockPos.z, PosYType, PosYMeta); - if (PosYType == E_BLOCK_REDSTONE_WIRE) - { - return (PosYMeta > 0); - } - - return false; -} - - - - -// Believe me, it works!! TODO: Add repeaters and low/high wires -cRedstoneSimulator::eRedstoneDirection cRedstoneSimulator::GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ) -{ - int Dir = REDSTONE_NONE; - - BLOCKTYPE NegX = m_World.GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ); - if ( - (NegX == E_BLOCK_REDSTONE_WIRE) || - (NegX == E_BLOCK_REDSTONE_TORCH_ON) || - (NegX == E_BLOCK_LEVER) - ) - { - Dir |= (REDSTONE_X_POS); - } - - BLOCKTYPE PosX = m_World.GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ); - if ( - (PosX == E_BLOCK_REDSTONE_WIRE) || - (PosX == E_BLOCK_REDSTONE_TORCH_ON) || - (PosX == E_BLOCK_LEVER) - ) - { - Dir |= (REDSTONE_X_NEG); - } - - BLOCKTYPE NegZ = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1); - if ( - (NegZ == E_BLOCK_REDSTONE_WIRE) || - (NegZ == E_BLOCK_REDSTONE_TORCH_ON) || - (NegZ == E_BLOCK_LEVER) - ) - { - if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner - { - Dir ^= REDSTONE_X_POS; - Dir |= REDSTONE_X_NEG; - } - if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner - { - Dir ^= REDSTONE_X_NEG; - Dir |= REDSTONE_X_POS; - } - Dir |= REDSTONE_Z_POS; - } - - BLOCKTYPE PosZ = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1); - if ( - (PosZ == E_BLOCK_REDSTONE_WIRE) || - (PosZ == E_BLOCK_REDSTONE_TORCH_ON) || - (PosZ == E_BLOCK_LEVER) - ) - { - if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner - { - Dir ^= REDSTONE_X_POS; - Dir |= REDSTONE_X_NEG; - } - if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner - { - Dir ^= REDSTONE_X_NEG; - Dir |= REDSTONE_X_POS; - } - Dir |= REDSTONE_Z_NEG; - } - - return (eRedstoneDirection)Dir; -} - - - - - -bool cRedstoneSimulator::IsRepeaterPointingTo(const Vector3i & a_RepeaterPos, char a_MetaData, const Vector3i & a_BlockPos) -{ - switch (a_MetaData & 0x3) - { - case 0x0: - { - if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(0, 0, 1))) - { - return true; - } - break; - } - - case 0x1: - { - if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(-1, 0, 0))) - { - return true; - } - break; - } - - case 0x2: - { - if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(0, 0,-1))) - { - return true; - } - break; - } - - case 0x3: - { - if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(1, 0, 0))) - { - return true; - } - break; - } - } - return false; -} - - - - - -bool cRedstoneSimulator::IsRepeaterPointingAway(const Vector3i & a_RepeaterPos, char a_MetaData, const Vector3i & a_BlockPos) -{ - switch (a_MetaData & 0x3) - { - case 0x0: - { - if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(0, 0,-1))) - { - return true; - } - break; - } - - case 0x1: - { - if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(1, 0, 0))) - { - return true; - } - break; - } - - case 0x2: - { - if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(0, 0, 1))) - { - return true; - } - break; - } - - case 0x3: - { - if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(-1, 0, 0))) - { - return true; - } - break; - } - } - return false; -} - - - - - -NIBBLETYPE cRedstoneSimulator::RepeaterRotationToMetaData(double a_Rotation) -{ - a_Rotation += 90 + 45; // So its not aligned with axis - if (a_Rotation > 360) - { - a_Rotation -= 360; - } - - if ((a_Rotation >= 0) && (a_Rotation < 90)) - { - return 0x1; - } - else if ((a_Rotation >= 180) && (a_Rotation < 270)) - { - return 0x3; - } - else if ((a_Rotation >= 90) && (a_Rotation < 180)) - { - return 0x2; - } - else - { - return 0x0; - } -} - - - - - -Vector3i cRedstoneSimulator::GetRepeaterDirection(NIBBLETYPE a_MetaData) -{ - switch (a_MetaData & 0x3) - { - case 0x0: return Vector3i(0, 0,-1); - case 0x1: return Vector3i(1, 0, 0); - case 0x2: return Vector3i(0, 0, 1); - case 0x3: return Vector3i(-1, 0, 0); - } - return Vector3i(); -} - - - - - -NIBBLETYPE cRedstoneSimulator::LeverDirectionToMetaData(char a_Dir) -{ - // 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; - } -} - - - - - -bool cRedstoneSimulator::IsLeverOn(cWorld * a_World, const Vector3i & a_BlockPos) -{ - // Extract the metadata and ask the lower level: - return IsLeverOn(a_World->GetBlockMeta(a_BlockPos)); -} - - - - - -bool cRedstoneSimulator::IsLeverOn(NIBBLETYPE a_BlockMeta) -{ - // Extract the ON bit from metadata and return if true if it is set: - return ((a_BlockMeta & 0x8) == 0x8); -} - - - - - -void cRedstoneSimulator::SetRepeater(const Vector3i & a_Position, int a_Ticks, bool a_bPowerOn) -{ - for (RepeaterList::iterator itr = m_SetRepeaters.begin(); itr != m_SetRepeaters.end(); ++itr) - { - sRepeaterChange & Change = *itr; - if (Change.Position.Equals(a_Position)) - { - if (Change.bPowerOn && !a_bPowerOn) - { - Change.bPowerOffNextTime = true; - } - if (a_bPowerOn) - { - Change.bPowerOffNextTime = false; - } - Change.bPowerOn |= a_bPowerOn; - return; - } - } - - sRepeaterChange RC; - RC.Position = a_Position; - RC.Ticks = a_Ticks; - RC.bPowerOn = a_bPowerOn; - RC.bPowerOffNextTime = false; - m_SetRepeaters.push_back(RC); -} - - - - |