diff options
Diffstat (limited to '')
-rw-r--r-- | src/Simulator/FireSimulator.h | 2 | ||||
-rw-r--r-- | src/Simulator/NoopFluidSimulator.h | 10 | ||||
-rw-r--r-- | src/Simulator/RedstoneSimulator.cpp | 377 | ||||
-rw-r--r-- | src/Simulator/RedstoneSimulator.h | 109 | ||||
-rw-r--r-- | src/Simulator/SandSimulator.h | 2 | ||||
-rw-r--r-- | src/Simulator/Simulator.h | 9 |
6 files changed, 242 insertions, 267 deletions
diff --git a/src/Simulator/FireSimulator.h b/src/Simulator/FireSimulator.h index 66c31b440..9ccc3ef4f 100644 --- a/src/Simulator/FireSimulator.h +++ b/src/Simulator/FireSimulator.h @@ -22,7 +22,7 @@ public: cFireSimulator(cWorld & a_World, cIniFile & a_IniFile); ~cFireSimulator(); - virtual void Simulate(float a_Dt) override {} // not used + virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override; virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override; diff --git a/src/Simulator/NoopFluidSimulator.h b/src/Simulator/NoopFluidSimulator.h index 8f894433f..9113aec3c 100644 --- a/src/Simulator/NoopFluidSimulator.h +++ b/src/Simulator/NoopFluidSimulator.h @@ -27,8 +27,14 @@ public: } // cSimulator overrides: - virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override {} - virtual void Simulate(float a_Dt) override {} + virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override + { + UNUSED(a_BlockX); + UNUSED(a_BlockY); + UNUSED(a_BlockZ); + UNUSED(a_Chunk); + } + virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} } ; diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp index f65908729..e361cbf49 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -4,6 +4,7 @@ #include "RedstoneSimulator.h" #include "../BlockEntities/DropSpenserEntity.h" #include "../BlockEntities/NoteEntity.h" +#include "../BlockEntities/CommandBlockEntity.h" #include "../Entities/TNTEntity.h" #include "../Blocks/BlockTorch.h" #include "../Blocks/BlockDoor.h" @@ -44,83 +45,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))) - { - 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; + // 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 to see if PoweredBlocks have invalid items (source is air or unpowered) - for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end();) + for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) { - 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) == 0) || + (((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,151 +94,151 @@ 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) - { - 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) + if (!IsAllowedBlock(Block)) { - 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); + m_RepeatersDelayList.erase(itr); + break; } - else + } + + 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 { - ++itr; + 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; } } - for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end();) + if (!IsAllowedBlock(Block)) { - int RelX = itr->a_BlockPos.x - a_ChunkX * cChunkDef::Width; - int RelZ = itr->a_BlockPos.z - a_ChunkZ * cChunkDef::Width; + return; + } + + ChunkData.push_back(cCoordWithBlock(RelX, a_BlockY, RelZ, Block)); +} - BLOCKTYPE SourceBlockType; - if (!a_Chunk->UnboundedRelGetBlockType(RelX, itr->a_BlockPos.y, RelZ, SourceBlockType)) - { - continue; - } - 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;) + +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()) { - 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 + 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; - case E_BLOCK_TNT: HandleTNT(a_X, dataitr->y, a_Z); break; + case E_BLOCK_TNT: HandleTNT(a_X, dataitr->y, a_Z); break; case E_BLOCK_TRAPDOOR: HandleTrapdoor(a_X, dataitr->y, a_Z); break; case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(a_X, dataitr->y, a_Z); break; case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(a_X, dataitr->y, a_Z); break; case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(a_X, dataitr->y, a_Z); break; + case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(a_X, dataitr->y, a_Z); break; 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 +250,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 +269,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 +449,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 } @@ -545,7 +507,7 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl // transferring power to other wires around. // 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.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, 0); // SetMeta & WakeUpSims doesn't seem to work here, so SetBlock return; // No need to process block power sets because self not powered } else @@ -693,7 +655,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,50 +743,45 @@ 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); - } + cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ); + SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false); } - else // Opened door + } +} + + + + + +void cRedstoneSimulator::HandleCommandBlock(int a_BlockX, int a_BlockY, int a_BlockZ) +{ + class cSetPowerToCommandBlock : + public cCommandBlockCallback + { + bool m_IsPowered; + public: + cSetPowerToCommandBlock(bool a_IsPowered) : m_IsPowered(a_IsPowered) {} + + virtual bool Item(cCommandBlockEntity * a_CommandBlock) override { - if (!AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) // Unpowered? Close if so - { - cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ); - } + a_CommandBlock->SetRedstonePower(m_IsPowered); + return false; } - } + } CmdBlockSP (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)); + + m_World.DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, CmdBlockSP); } @@ -970,6 +927,7 @@ void cRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_BlockY, int a_B else { m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x0); + m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ); } break; } @@ -1032,6 +990,7 @@ void cRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_BlockY, int a_B else { m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x0); + m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ); } break; } @@ -1188,6 +1147,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 +1319,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 +1335,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 +1359,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 +1377,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 60c86a3c5..bb2efeb8a 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; @@ -19,7 +19,7 @@ public: cRedstoneSimulator(cWorld & a_World); ~cRedstoneSimulator(); - virtual void Simulate(float a_Dt) override {}; // Not used in this simulator + virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override; virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType ) override { return IsRedstone(a_BlockType); } @@ -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,107 +78,97 @@ private: // In addition to being non-performant, it would stop the player from actually breaking said device /* ====== SOURCES ====== */ - /// <summary>Handles the redstone torch</summary> + /** Handles the redstone torch */ void HandleRedstoneTorch(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState); - /// <summary>Handles the redstone block</summary> + /** Handles the redstone block */ void HandleRedstoneBlock(int a_BlockX, int a_BlockY, int a_BlockZ); - /// <summary>Handles levers</summary> + /** Handles levers */ void HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_BlockZ); - /// <summary>Handles buttons</summary> + /** Handles buttons */ void HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType); - /// <summary>Handles daylight sensors</summary> + /** Handles daylight sensors */ void HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ); - /// <summary>Handles pressure plates</summary> + /** Handles pressure plates */ void HandlePressurePlate(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType); /* ==================== */ /* ====== CARRIERS ====== */ - /// <summary>Handles redstone wire</summary> + /** Handles redstone wire */ void HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_BlockZ); - /// <summary>Handles repeaters</summary> + /** Handles repeaters */ void HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState); /* ====================== */ /* ====== DEVICES ====== */ - /// <summary>Handles pistons</summary> + /** Handles pistons */ void HandlePiston(int a_BlockX, int a_BlockY, int a_BlockZ); - /// <summary>Handles dispensers and droppers</summary> + /** Handles dispensers and droppers */ void HandleDropSpenser(int a_BlockX, int a_BlockY, int a_BlockZ); - /// <summary>Handles TNT (exploding)</summary> + /** Handles TNT (exploding) */ void HandleTNT(int a_BlockX, int a_BlockY, int a_BlockZ); - /// <summary>Handles redstone lamps</summary> + /** Handles redstone lamps */ void HandleRedstoneLamp(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState); - /// <summary>Handles doords</summary> + /** Handles doords */ void HandleDoor(int a_BlockX, int a_BlockY, int a_BlockZ); - /// <summary>Handles activator, detector, and powered rails</summary> + /** Handles command blocks */ + void HandleCommandBlock(int a_BlockX, int a_BlockY, int a_BlockZ); + /** Handles activator, detector, and powered rails */ void HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType); - /// <summary>Handles trapdoors</summary> + /** Handles trapdoors */ void HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ); - /// <summary>Handles noteblocks</summary> + /** Handles noteblocks */ void HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ); /* ===================== */ /* ====== Helper functions ====== */ - /// <summary>Marks a block as powered</summary> + /** 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); - /// <summary>Marks a block as being powered through another block</summary> + /** 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); - /// <summary>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</summary> + /** 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); - /// <summary>Marks the second block in a direction as linked powered</summary> + /** 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); - /// <summary>Marks all blocks immediately surrounding a coordinate as powered</summary> + /** Marks all blocks immediately surrounding a coordinate as powered */ void SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock); - /// <summary>Queues a repeater to be powered or unpowered</summary> + /** 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); - /// <summary>Returns if a coordinate is powered or linked powered</summary> + /** 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); } - /// <summary>Returns if a coordinate is in the directly powered blocks list</summary> + /** Returns if a coordinate is in the directly powered blocks list */ bool AreCoordsDirectlyPowered(int a_BlockX, int a_BlockY, int a_BlockZ); - /// <summary>Returns if a coordinate is in the indirectly powered blocks list</summary> + /** Returns if a coordinate is in the indirectly powered blocks list */ bool AreCoordsLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ); - /// <summary>Returns if a coordinate was marked as simulated (for blocks toggleable by players)</summary> + /** 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); - /// <summary>Returns if a repeater is powered</summary> + /** Returns if a repeater is powered */ bool IsRepeaterPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta); - /// <summary>Returns if a piston is powered</summary> + /** 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); - /// <summary>Returns if lever metadata marks it as emitting power</summary> + + /** Returns if lever metadata marks it as emitting power */ bool IsLeverOn(NIBBLETYPE a_BlockMeta); - /// <summary>Returns if button metadata marks it as emitting power</summary> + /** Returns if button metadata marks it as emitting power */ 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; } + /** 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; - } - } - - /// <summary>Returns if a block is a mechanism (something that accepts power and does something)</summary> + /** Returns if a block is a mechanism (something that accepts power and does something) */ inline static bool IsMechanism(BLOCKTYPE Block) { switch (Block) { case E_BLOCK_ACTIVATOR_RAIL: + case E_BLOCK_COMMAND_BLOCK: case E_BLOCK_PISTON: case E_BLOCK_STICKY_PISTON: case E_BLOCK_DISPENSER: @@ -205,16 +192,16 @@ private: } } - /// <summary>Returns if a block has the potential to output power</summary> + /** 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 +214,7 @@ private: } } - /// <summary>Returns if a block is any sort of redstone device</summary> + /** Returns if a block is any sort of redstone device */ inline static bool IsRedstone(BLOCKTYPE Block) { switch (Block) @@ -236,6 +223,7 @@ private: case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_ACTIVE_COMPARATOR: case E_BLOCK_BLOCK_OF_REDSTONE: + case E_BLOCK_COMMAND_BLOCK: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_DISPENSER: case E_BLOCK_DAYLIGHT_SENSOR: @@ -248,6 +236,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: @@ -271,4 +260,4 @@ private: default: return false; } } -};
\ No newline at end of file +}; diff --git a/src/Simulator/SandSimulator.h b/src/Simulator/SandSimulator.h index 6e9ea15ac..6e64aa425 100644 --- a/src/Simulator/SandSimulator.h +++ b/src/Simulator/SandSimulator.h @@ -15,7 +15,7 @@ public: cSandSimulator(cWorld & a_World, cIniFile & a_IniFile); // cSimulator overrides: - virtual void Simulate(float a_Dt) override {} // Unused in this simulator + virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override; virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override; diff --git a/src/Simulator/Simulator.h b/src/Simulator/Simulator.h index 5cd0e8657..a25b7f1b6 100644 --- a/src/Simulator/Simulator.h +++ b/src/Simulator/Simulator.h @@ -25,7 +25,14 @@ public: virtual void Simulate(float a_Dt) = 0; /// Called in each tick for each chunk, a_Dt is the time passed since the last tick, in msec; direct access to chunk data available - virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) {}; + virtual void SimulateChunk(float a_Dt, int a_ChunkX, + int a_ChunkZ, cChunk * a_Chunk) + { + UNUSED(a_Dt); + UNUSED(a_ChunkX); + UNUSED(a_ChunkZ); + UNUSED(a_Chunk); + }; /// Called when a block changes virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk); |