From 33cd7f4e75819d50f22ae61027373ebb331305b5 Mon Sep 17 00:00:00 2001 From: QUSpilPrgm Date: Sat, 4 Jun 2016 14:16:35 +0200 Subject: - Add a activation flag to droppers and dispensers. Previously droppers and dispensers shot items with every block update. - Fixes a range check inside cIncrementalRedstoneSimulator::Simulate --- src/BlockEntities/DispenserEntity.cpp | 2 +- src/BlockEntities/DropSpenserEntity.cpp | 6 ++--- src/BlockID.h | 2 ++ .../DropSpenserHandler.h | 27 ++++++++++++++++++++-- .../IncrementalRedstoneSimulator.cpp | 6 ++--- 5 files changed, 34 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/BlockEntities/DispenserEntity.cpp b/src/BlockEntities/DispenserEntity.cpp index e03644a0f..d6fbafadf 100644 --- a/src/BlockEntities/DispenserEntity.cpp +++ b/src/BlockEntities/DispenserEntity.cpp @@ -283,7 +283,7 @@ UInt32 cDispenserEntity::SpawnProjectileFromDispenser(int a_BlockX, int a_BlockY Vector3d cDispenserEntity::GetShootVector(NIBBLETYPE a_Meta) { - switch (a_Meta & 0x7) + switch (a_Meta & E_META_DROPSPENSER_FACING_MASK) { case E_META_DROPSPENSER_FACING_YP: return Vector3d( 0, 1, 0); case E_META_DROPSPENSER_FACING_YM: return Vector3d( 0, -1, 0); diff --git a/src/BlockEntities/DropSpenserEntity.cpp b/src/BlockEntities/DropSpenserEntity.cpp index 8dddf85de..3a43e1073 100644 --- a/src/BlockEntities/DropSpenserEntity.cpp +++ b/src/BlockEntities/DropSpenserEntity.cpp @@ -41,7 +41,7 @@ cDropSpenserEntity::~cDropSpenserEntity() void cDropSpenserEntity::AddDropSpenserDir(int & a_BlockX, int & a_BlockY, int & a_BlockZ, NIBBLETYPE a_Direction) { - switch (a_Direction & 0x07) // Vanilla uses the 8th bit to determine power state - we don't + switch (a_Direction & E_META_DROPSPENSER_FACING_MASK) { case E_META_DROPSPENSER_FACING_YM: a_BlockY--; return; case E_META_DROPSPENSER_FACING_YP: a_BlockY++; return; @@ -87,7 +87,7 @@ void cDropSpenserEntity::DropSpense(cChunk & a_Chunk) // Broadcast a smoke and click effects: NIBBLETYPE Meta = a_Chunk.GetMeta(m_RelX, m_PosY, m_RelZ); int SmokeDir = 0; - switch (Meta) + switch (Meta & E_META_DROPSPENSER_FACING_MASK) { case E_META_DROPSPENSER_FACING_YP: SmokeDir = static_cast(SmokeDirection::CENTRE); break; // YP & YM don't have associated smoke dirs, just do 4 (centre of block) case E_META_DROPSPENSER_FACING_YM: SmokeDir = static_cast(SmokeDirection::CENTRE); break; @@ -176,7 +176,7 @@ void cDropSpenserEntity::DropFromSlot(cChunk & a_Chunk, int a_SlotNum) const int PickupSpeed = m_World->GetTickRandomNumber(4) + 2; // At least 2, at most 6 int PickupSpeedX = 0, PickupSpeedY = 0, PickupSpeedZ = 0; - switch (Meta) + switch (Meta & E_META_DROPSPENSER_FACING_MASK) { case E_META_DROPSPENSER_FACING_YP: PickupSpeedY = PickupSpeed; break; case E_META_DROPSPENSER_FACING_YM: PickupSpeedY = -PickupSpeed; break; diff --git a/src/BlockID.h b/src/BlockID.h index b32b673c6..5af0cc4f5 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -536,6 +536,8 @@ enum E_META_DROPSPENSER_FACING_ZP = 3, E_META_DROPSPENSER_FACING_XM = 4, E_META_DROPSPENSER_FACING_XP = 5, + E_META_DROPSPENSER_FACING_MASK = 7, + E_META_DROPSPENSER_ACTIVATED = 8, // E_BLOCK_DOUBLE_STONE_SLAB metas: E_META_DOUBLE_STONE_SLAB_STONE = 0, diff --git a/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h b/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h index b67b8d4fb..3c9952582 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h @@ -18,6 +18,22 @@ public: { } + inline static bool IsActivated(NIBBLETYPE a_Meta) + { + return (a_Meta & E_META_DROPSPENSER_ACTIVATED) != 0; + } + inline static NIBBLETYPE SetActivationState(NIBBLETYPE a_Meta, bool IsOn) + { + if (IsOn) + { + return a_Meta | E_META_DROPSPENSER_ACTIVATED; // set the bit + } + else + { + return a_Meta & ~E_META_DROPSPENSER_ACTIVATED; // clear the bit + } + } + virtual unsigned char GetPowerDeliveredToPosition(const Vector3i & a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const Vector3i & a_QueryPosition, BLOCKTYPE a_QueryBlockType) override { UNUSED(a_Position); @@ -39,8 +55,9 @@ public: virtual cVector3iArray Update(const Vector3i & a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) override { // LOGD("Evaluating spencer the dropspenser (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - - if (a_PoweringData.PowerLevel > 0) + bool IsPoweredNow = (a_PoweringData.PowerLevel > 0); + bool WasPoweredPreviously = IsActivated(a_Meta); + if (IsPoweredNow && !WasPoweredPreviously) { class cSetPowerToDropSpenser : public cDropSpenserCallback @@ -56,6 +73,12 @@ public: m_World.DoWithDropSpenserAt(a_Position.x, a_Position.y, a_Position.z, DrSpSP); } + // Update the internal dropspenser state if necessary + if (IsPoweredNow != WasPoweredPreviously) + { + m_World.SetBlockMeta(a_Position, SetActivationState(a_Meta, IsPoweredNow)); + } + return {}; } diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp index 9f8c0f39d..c7be24dc4 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp @@ -196,12 +196,12 @@ void cIncrementalRedstoneSimulator::Simulate(float a_dt) cRedstoneHandler::PoweringData Power; for (const auto & Location : CurrentHandler->GetValidSourcePositions(CurrentLocation, CurrentBlock, CurrentMeta)) { - BLOCKTYPE PotentialBlock; - NIBBLETYPE PotentialMeta; - if ((Location.y < 0) || (Location.y > cChunkDef::Height)) + if (!cChunk::IsValidHeight(Location.y)) { continue; } + BLOCKTYPE PotentialBlock; + NIBBLETYPE PotentialMeta; m_World.GetBlockTypeMeta(Location.x, Location.y, Location.z, PotentialBlock, PotentialMeta); auto PotentialSourceHandler = cIncrementalRedstoneSimulator::CreateComponent(m_World, PotentialBlock, &m_Data); -- cgit v1.2.3