summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@hotmail.co.uk>2015-02-08 17:35:10 +0100
committerTiger Wang <ziwei.tiger@hotmail.co.uk>2015-06-06 13:21:09 +0200
commitde5b1401f813985300c33c6b3166b115f9a10dd3 (patch)
tree37c44a693a8b3402b8be7ddbcf9e52a8ea9882db
parentMerge pull request #2172 from mc-server/LightingCallbacks (diff)
downloadcuberite-de5b1401f813985300c33c6b3166b115f9a10dd3.tar
cuberite-de5b1401f813985300c33c6b3166b115f9a10dd3.tar.gz
cuberite-de5b1401f813985300c33c6b3166b115f9a10dd3.tar.bz2
cuberite-de5b1401f813985300c33c6b3166b115f9a10dd3.tar.lz
cuberite-de5b1401f813985300c33c6b3166b115f9a10dd3.tar.xz
cuberite-de5b1401f813985300c33c6b3166b115f9a10dd3.tar.zst
cuberite-de5b1401f813985300c33c6b3166b115f9a10dd3.zip
-rw-r--r--src/BlockEntities/BlockEntity.h2
-rw-r--r--src/BlockEntities/ChestEntity.h18
-rw-r--r--src/Blocks/BlockComparator.h79
-rw-r--r--src/ChunkDef.h6
-rw-r--r--src/Globals.h7
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.cpp200
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.h58
7 files changed, 287 insertions, 83 deletions
diff --git a/src/BlockEntities/BlockEntity.h b/src/BlockEntities/BlockEntity.h
index 85f75a523..7b5b6920f 100644
--- a/src/BlockEntities/BlockEntity.h
+++ b/src/BlockEntities/BlockEntity.h
@@ -91,7 +91,7 @@ public:
BLOCKTYPE GetBlockType(void) const { return m_BlockType; }
- cWorld * GetWorld(void) const {return m_World; }
+ cWorld * GetWorld(void) const { return m_World; }
int GetChunkX(void) const { return FAST_FLOOR_DIV(m_PosX, cChunkDef::Width); }
int GetChunkZ(void) const { return FAST_FLOOR_DIV(m_PosZ, cChunkDef::Width); }
diff --git a/src/BlockEntities/ChestEntity.h b/src/BlockEntities/ChestEntity.h
index 645dbf4bc..8ead8bda0 100644
--- a/src/BlockEntities/ChestEntity.h
+++ b/src/BlockEntities/ChestEntity.h
@@ -53,6 +53,24 @@ private:
/** Number of players who currently have this chest open */
int m_NumActivePlayers;
+
+ /** cItemGrid::cListener overrides: */
+ virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum)
+ {
+ UNUSED(a_SlotNum);
+ ASSERT(a_Grid == &m_Contents);
+ if (m_World != nullptr)
+ {
+ if (GetWindow() != nullptr)
+ {
+ GetWindow()->BroadcastWholeWindow();
+ }
+
+ m_World->MarkChunkDirty(GetChunkX(), GetChunkZ());
+ m_World->MarkRedstoneDirty(GetChunkX(), GetChunkZ());
+ }
+ }
+
} ; // tolua_export
diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h
index ed73a162e..3babeddad 100644
--- a/src/Blocks/BlockComparator.h
+++ b/src/Blocks/BlockComparator.h
@@ -64,6 +64,85 @@ public:
a_BlockMeta = cBlockRedstoneRepeaterHandler::RepeaterRotationToMetaData(a_Player->GetYaw());
return true;
}
+
+
+ inline static Vector3i GetSideCoordinate(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, bool a_bInverse)
+ {
+ if (!a_bInverse)
+ {
+ switch (a_Meta)
+ {
+ case 0x0: a_BlockX++; break;
+ case 0x1: a_BlockZ--; break;
+ case 0x2: a_BlockX--; break;
+ case 0x3: a_BlockZ++; break;
+ default:
+ {
+ LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta);
+ ASSERT(!"Unknown metadata while determining orientation of comparator!");
+ break;
+ }
+ }
+ }
+ else
+ {
+ switch (a_Meta)
+ {
+ case 0x0: a_BlockX--; break;
+ case 0x1: a_BlockZ++; break;
+ case 0x2: a_BlockX++; break;
+ case 0x3: a_BlockZ--; break;
+ default:
+ {
+ LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta);
+ ASSERT(!"Unknown metadata while determining orientation of comparator!");
+ break;
+ }
+ }
+ }
+
+ return Vector3i(a_BlockX, a_BlockY, a_BlockZ);
+ }
+
+
+ inline static Vector3i GetRearCoordinate(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta)
+ {
+ switch (a_Meta)
+ {
+ case 0x0: a_BlockZ++; break;
+ case 0x1: a_BlockX--; break;
+ case 0x2: a_BlockZ--; break;
+ case 0x3: a_BlockX++; break;
+ default:
+ {
+ LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta);
+ ASSERT(!"Unknown metadata while determining orientation of comparator!");
+ break;
+ }
+ }
+
+ return Vector3i(a_BlockX, a_BlockY, a_BlockZ);
+ }
+
+
+ inline static Vector3i GetFrontCoordinate(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta)
+ {
+ switch (a_Meta)
+ {
+ case 0x0: a_BlockZ--; break;
+ case 0x1: a_BlockX++; break;
+ case 0x2: a_BlockZ++; break;
+ case 0x3: a_BlockX--; break;
+ default:
+ {
+ LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta);
+ ASSERT(!"Unknown metadata while determining orientation of comparator!");
+ break;
+ }
+ }
+
+ return Vector3i(a_BlockX, a_BlockY, a_BlockZ);
+ }
} ;
diff --git a/src/ChunkDef.h b/src/ChunkDef.h
index b03a03bff..fb3451db1 100644
--- a/src/ChunkDef.h
+++ b/src/ChunkDef.h
@@ -96,6 +96,12 @@ public:
a_Z = a_Z - a_ChunkZ * Width;
}
+ /** Converts relative block coordinates into absolute coordinates with a known chunk location */
+ inline static Vector3i RelativeToAbsolute(const Vector3i & a_RelBlockPosition, int a_ChunkX, int a_ChunkZ)
+ {
+ return Vector3i(a_RelBlockPosition.x + a_ChunkX * Width, a_RelBlockPosition.y, a_RelBlockPosition.z + a_ChunkZ * Width);
+ }
+
/// Converts absolute block coords to chunk coords:
inline static void BlockToChunk(int a_X, int a_Z, int & a_ChunkX, int & a_ChunkZ)
diff --git a/src/Globals.h b/src/Globals.h
index 27d944fcc..8ff7b6894 100644
--- a/src/Globals.h
+++ b/src/Globals.h
@@ -192,14 +192,13 @@ template class SizeChecker<UInt8, 1>;
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT _WIN32_WINNT_WS03 // We want to target Windows XP with Service Pack 2 & Windows Server 2003 with Service Pack 1 and higher
+ // Windows SDK defines min and max macros, messing up with our std::min and std::max usage
+ #define NOMINMAX
+
#include <Windows.h>
#include <winsock2.h>
#include <Ws2tcpip.h> // IPv6 stuff
- // Windows SDK defines min and max macros, messing up with our std::min and std::max usage
- #undef min
- #undef max
-
// Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant
#ifdef GetFreeSpace
#undef GetFreeSpace
diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp
index 7f320af0d..c1a66243d 100644
--- a/src/Simulator/IncrementalRedstoneSimulator.cpp
+++ b/src/Simulator/IncrementalRedstoneSimulator.cpp
@@ -3,11 +3,10 @@
#include "BlockEntities/ChestEntity.h"
-typedef cItemCallback<cChestEntity> cChestCallback;
-
#include "Chunk.h"
#include "World.h"
#include "Blocks/GetHandlerCompileTimeTemplate.h"
+#include "Blocks/BlockComparator.h"
#include "Blocks/BlockTorch.h"
#include "Blocks/BlockLever.h"
#include "Blocks/BlockButton.h"
@@ -286,6 +285,12 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt
HandleRedstoneButton(dataitr->x, dataitr->y, dataitr->z);
break;
}
+ case E_BLOCK_ACTIVE_COMPARATOR:
+ case E_BLOCK_INACTIVE_COMPARATOR:
+ {
+ HandleRedstoneComparator(dataitr->x, dataitr->y, dataitr->z);
+ break;
+ }
default: break;
}
}
@@ -535,20 +540,16 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re
};
// Check to see if directly beside a power source
- unsigned char MyPower;
- if (!IsWirePowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower))
+ unsigned char MyPower = IsWirePowered(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ));
+ if (MyPower == 0)
{
+ SetSourceUnpowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk);
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0);
return;
}
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
- if (MyPower < 1)
- {
- return;
- }
-
MyPower--;
for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power
@@ -656,6 +657,67 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re
+void cIncrementalRedstoneSimulator::HandleRedstoneComparator(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
+{
+ auto Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
+ auto HighestSidePower = std::max(IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetSideCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3, false))), IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetSideCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3, true))));
+ auto FrontCoordinate = AdjustRelativeCoords(cBlockComparatorHandler::GetFrontCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3));
+ unsigned char Power = 0;
+
+ class cContainerCallback : public cBlockEntityCallback
+ {
+ public:
+ cContainerCallback() : m_SignalStrength(0)
+ {
+ }
+
+ virtual bool Item(cBlockEntity * a_BlockEntity) override
+ {
+ auto & Contents = static_cast<cBlockEntityWithItems *>(a_BlockEntity)->GetContents();
+ float Fullness = 0; // Is a floating-point type to allow later calculation to produce a non-truncated value
+ for (int Slot = 0; Slot != Contents.GetNumSlots(); ++Slot)
+ {
+ Fullness += Contents.GetSlot(Slot).m_ItemCount / Contents.GetSlot(Slot).GetMaxStackSize();
+ }
+
+ m_SignalStrength = static_cast<unsigned char>(1 + (Fullness / Contents.GetNumSlots()) * 14);
+ return false;
+ }
+
+ unsigned char m_SignalStrength;
+ } CCB;
+
+ auto AbsoluteComparatorCoords = cChunkDef::RelativeToAbsolute(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), m_Chunk->GetPosX(), m_Chunk->GetPosZ());
+ auto AbsoluteRearCoords = cBlockComparatorHandler::GetRearCoordinate(AbsoluteComparatorCoords.x, AbsoluteComparatorCoords.y, AbsoluteComparatorCoords.z, Meta & 0x3);
+
+ m_Chunk->DoWithBlockEntityAt(AbsoluteRearCoords.x, AbsoluteRearCoords.y, AbsoluteRearCoords.z, CCB);
+ auto RearPower = std::max(CCB.m_SignalStrength, IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetRearCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3))));
+
+ if ((Meta & 0x4) == 0x4)
+ { // Subtraction mode
+ Power = RearPower - HighestSidePower;
+ }
+ else
+ { // Comparison mode
+ Power = std::max(HighestSidePower, RearPower);
+ }
+
+ if (Power > 0)
+ {
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) | 0x8);
+ SetBlockPowered(FrontCoordinate, Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), Power);
+ }
+ else
+ {
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7);
+ SetSourceUnpowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk);
+ }
+}
+
+
+
+
+
void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState)
{
/* Repeater Orientation Mini Guide:
@@ -1017,19 +1079,19 @@ void cIncrementalRedstoneSimulator::HandleDaylightSensor(int a_RelBlockX, int a_
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
- if (!this->m_World.IsChunkLighted(ChunkX, ChunkZ))
+ if (!m_World.IsChunkLighted(ChunkX, ChunkZ))
{
- this->m_World.QueueLightChunk(ChunkX, ChunkZ);
+ m_World.QueueLightChunk(ChunkX, ChunkZ);
}
else
{
- if (m_Chunk->GetTimeAlteredLight(this->m_World.GetBlockSkyLight(BlockX, a_RelBlockY + 1, BlockZ)) > 8)
+ if (m_Chunk->GetTimeAlteredLight(m_Chunk->GetSkyLight(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ)) > 8)
{
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
}
else
{
- WakeUp(BlockX, a_RelBlockY, BlockZ, m_Chunk);
+ SetSourceUnpowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk);
}
}
}
@@ -1702,22 +1764,22 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBl
-bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel)
+unsigned char cIncrementalRedstoneSimulator::IsWirePowered(Vector3i a_RelBlockPosition)
{
- a_PowerLevel = 0;
+ unsigned char PowerLevel = 0;
for (const auto & itr : *m_PoweredBlocks) // Check powered list
{
- if (!itr.a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
+ if (itr.a_BlockPos != a_RelBlockPosition)
{
continue;
}
- a_PowerLevel = std::max(itr.a_PowerLevel, a_PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block)
+ PowerLevel = std::max(itr.a_PowerLevel, PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block)
}
for (const auto & itr : *m_LinkedPoweredBlocks) // Check linked powered list
{
- if (!itr.a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
+ if (itr.a_BlockPos != a_RelBlockPosition)
{
continue;
}
@@ -1727,10 +1789,10 @@ bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBloc
{
continue;
}
- a_PowerLevel = std::max(itr.a_PowerLevel, a_PowerLevel);
+ PowerLevel = std::max(itr.a_PowerLevel, PowerLevel);
}
- return (a_PowerLevel != 0); // Answer the inital question: is the wire powered?
+ return PowerLevel;
}
@@ -1871,20 +1933,20 @@ void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_RelBlockX, int a_R
{
static const struct
{
- int x, y, z;
+ Vector3i Offset;
} gCrossCoords[] =
{
- { 1, 0, 0 },
- { -1, 0, 0 },
- { 0, 0, 1 },
- { 0, 0, -1 },
- { 0, 1, 0 },
- { 0, -1, 0 }
+ Vector3i(1, 0, 0),
+ Vector3i(-1, 0, 0),
+ Vector3i(0, 0, 1),
+ Vector3i(0, 0, -1),
+ Vector3i(0, 1, 0),
+ Vector3i(0, -1, 0)
};
for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through struct to power all directions
{
- SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_PowerLevel);
+ SetBlockPowered(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ) + gCrossCoords[i].Offset, Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), a_PowerLevel);
}
}
@@ -1892,60 +1954,64 @@ void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_RelBlockX, int a_R
-void cIncrementalRedstoneSimulator::SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel)
+void cIncrementalRedstoneSimulator::SetBlockPowered(Vector3i a_RelBlockPosition, Vector3i a_RelSourcePosition, unsigned char a_PowerLevel)
{
- cChunk * Neighbour = m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelBlockX, a_RelBlockZ); // Adjust coordinates for the later call using these values
+ cChunk * Neighbour = m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelBlockPosition.x, a_RelBlockPosition.z); // Adjust coordinates for the later call using these values
if ((Neighbour == nullptr) || !Neighbour->IsValid())
{
return;
}
+ a_RelSourcePosition.x += (m_Chunk->GetPosX() - Neighbour->GetPosX()) * cChunkDef::Width;
+ a_RelSourcePosition.z += (m_Chunk->GetPosZ() - Neighbour->GetPosZ()) * cChunkDef::Width;
auto & Powered = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position
for (auto itr = Powered.begin(); itr != Powered.end(); ++itr)
{
- if (
- itr->a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) &&
- itr->a_SourcePos.Equals(Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ))
- )
+ if ((itr->a_BlockPos == a_RelBlockPosition) && (itr->a_SourcePos == a_RelSourcePosition))
{
- // Check for duplicates, update power level, don't add a new listing
- itr->a_PowerLevel = a_PowerLevel;
- return;
- }
- }
-
- // No need to get neighbouring chunk as we can guarantee that when something is powering us, the entry will be in our chunk
- for (auto itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr)
- {
- if (
- itr->a_BlockPos.Equals(Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ)) &&
- itr->a_SourcePos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) &&
- (m_Chunk->GetBlock(a_RelSourceX, a_RelSourceY, a_RelSourceZ) == E_BLOCK_REDSTONE_WIRE)
- )
- {
- BLOCKTYPE Block;
- NIBBLETYPE Meta;
- Neighbour->GetBlockTypeMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Block, Meta);
-
- if (Block == E_BLOCK_REDSTONE_WIRE)
+ if (itr->a_PowerLevel != a_PowerLevel)
{
- if (Meta < a_PowerLevel)
- {
- m_PoweredBlocks->erase(itr); // Powering source with higher power level, allow it
- break;
- }
- else
- {
- // Powered wires try to power their source - don't let them!
- return;
- }
+ // Update power level, don't add a new listing
+ Neighbour->SetIsRedstoneDirty(true);
+ m_Chunk->SetIsRedstoneDirty(true);
+ itr->a_PowerLevel = a_PowerLevel;
}
+ return;
}
}
+ //// No need to get neighbouring chunk as we can guarantee that when something is powering us, the entry will be in our chunk
+ //for (auto itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr)
+ //{
+ // if (
+ // (itr->a_BlockPos == a_RelBlockPosition) &&
+ // (itr->a_SourcePos == a_RelSourcePosition) &&
+ // (m_Chunk->GetBlock(a_RelSourcePosition) == E_BLOCK_REDSTONE_WIRE)
+ // )
+ // {
+ // BLOCKTYPE Block;
+ // NIBBLETYPE Meta;
+ // Neighbour->GetBlockTypeMeta(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, Block, Meta);
+
+ // if (Block == E_BLOCK_REDSTONE_WIRE)
+ // {
+ // if (Meta < a_PowerLevel)
+ // {
+ // m_PoweredBlocks->erase(itr); // Powering source with higher power level, allow it
+ // break;
+ // }
+ // else
+ // {
+ // // Powered wires try to power their source - don't let them!
+ // return;
+ // }
+ // }
+ // }
+ //}
+
sPoweredBlocks RC;
- RC.a_BlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
- RC.a_SourcePos = Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ);
+ RC.a_BlockPos = a_RelBlockPosition;
+ RC.a_SourcePos = a_RelSourcePosition;
RC.a_PowerLevel = a_PowerLevel;
Powered.emplace_back(RC);
Neighbour->SetIsRedstoneDirty(true);
@@ -2123,7 +2189,7 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R
for (const auto & itr : BlocksPotentiallyUnpowered)
{
auto Neighbour = a_Chunk->GetRelNeighborChunk(itr.x, itr.z);
- if (!AreCoordsPowered(itr.x, itr.y, itr.z) && (Neighbour->GetBlock(itr) != E_BLOCK_REDSTONE_REPEATER_ON))
+ if (Neighbour->GetBlock(itr) != E_BLOCK_REDSTONE_REPEATER_ON)
{
// Repeaters time themselves with regards to unpowering; ensure we don't do it for them
SetSourceUnpowered(itr.x, itr.y, itr.z, Neighbour);
diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h
index 43f0e89d0..65e3ff4af 100644
--- a/src/Simulator/IncrementalRedstoneSimulator.h
+++ b/src/Simulator/IncrementalRedstoneSimulator.h
@@ -114,73 +114,98 @@ private:
// We want a_MyState for devices needing a full FastSetBlock (as opposed to meta) because with our simulation model, we cannot keep setting the block if it is already set correctly
// In addition to being non-performant, it would stop the player from actually breaking said device
- /* ====== SOURCES ====== */
+
/** Handles the redstone torch */
void HandleRedstoneTorch(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
+
/** Handles the redstone block */
void HandleRedstoneBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles levers */
void HandleRedstoneLever(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles buttons */
void HandleRedstoneButton(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles daylight sensors */
void HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles pressure plates */
void HandlePressurePlate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType);
+
/** Handles tripwire hooks
Performs correct meta and power setting for self by going in the direction it faces and looking for a continous line of tripwire bounded by another oppositely facing hook
If this line is complete, it verifies that at least on wire reports an entity is on top (via its meta), and performs its task
*/
void HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles trapped chests */
void HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /* ==================== */
- /* ====== CARRIERS ====== */
+
/** Handles redstone wire */
void HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles repeaters */
void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
- /* ====================== */
- /* ====== DEVICES ====== */
+ /** Handles comparators */
+ void HandleRedstoneComparator(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
+
/** Handles pistons */
void HandlePiston(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles dispensers and droppers */
void HandleDropSpenser(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles TNT (exploding) */
void HandleTNT(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles redstone lamps */
void HandleRedstoneLamp(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
+
/** Handles doords */
void HandleDoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles command blocks */
void HandleCommandBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles activator, detector, and powered rails */
void HandleRail(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType);
+
/** Handles trapdoors */
void HandleTrapdoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles fence gates */
void HandleFenceGate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles noteblocks */
void HandleNoteBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Handles tripwires */
void HandleTripwire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
- /* ===================== */
- /* ====== Helper functions ====== */
+
/** Marks a block as powered */
- void SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
+ void SetBlockPowered(Vector3i a_RelBlockPosition, Vector3i a_RelSourcePosition, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
+ void SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL) { SetBlockPowered(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ), a_PowerLevel); }
+
/** Marks a block as being powered through another block */
void SetBlockLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelMiddleX, int a_RelMiddleY, int a_RelMiddleZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, BLOCKTYPE a_MiddeBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
+
/** 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_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool WasLastStatePowered);
+
/** Marks the second block in a direction as linked powered */
void SetDirectionLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, char a_Direction, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
+
/** Marks all blocks immediately surrounding a coordinate as powered */
void SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
+
/** Queues a repeater to be powered or unpowered and returns if the m_RepeatersDelayList iterators were invalidated */
bool QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
+
/** Removes a block from the Powered and LinkedPowered lists
Used for variable sources such as tripwire hooks, daylight sensors, and trapped chests
*/
@@ -189,31 +214,39 @@ private:
/** Returns if a coordinate is powered or linked powered */
bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }
+
/** Returns if a coordinate is in the directly powered blocks list */
bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, cChunk * a_Chunk);
+
/** Returns if a coordinate is in the indirectly powered blocks list */
bool AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+
/** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */
bool AreCoordsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool IsCurrentStatePowered);
+
/** Returns if a repeater is powered by testing for power sources behind the repeater */
bool IsRepeaterPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
+
/** Returns if a repeater is locked */
bool IsRepeaterLocked(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
+
/** Returns if a piston is powered */
bool IsPistonPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, 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_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel);
+ unsigned char IsWirePowered(Vector3i a_RelBlockPosition);
+
/** Handles delayed updates to repeaters **/
void HandleRedstoneRepeaterDelays(void);
/** Returns if lever metadata marks it as emitting power */
bool IsLeverOn(NIBBLETYPE a_BlockMeta);
+
/** Returns if button metadata marks it as emitting power */
bool IsButtonOn(NIBBLETYPE a_BlockMeta) { return IsLeverOn(a_BlockMeta); }
- /* ============================== */
- /* ====== Misc Functions ====== */
+
/** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */
inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { return cBlockInfo::FullyOccupiesVoxel(Block); }
@@ -227,6 +260,7 @@ private:
case E_BLOCK_ACACIA_DOOR:
case E_BLOCK_ACACIA_FENCE_GATE:
case E_BLOCK_ACTIVATOR_RAIL:
+ case E_BLOCK_ACTIVE_COMPARATOR:
case E_BLOCK_BIRCH_DOOR:
case E_BLOCK_BIRCH_FENCE_GATE:
case E_BLOCK_COMMAND_BLOCK:
@@ -236,6 +270,7 @@ private:
case E_BLOCK_DROPPER:
case E_BLOCK_FENCE_GATE:
case E_BLOCK_HOPPER:
+ case E_BLOCK_INACTIVE_COMPARATOR:
case E_BLOCK_IRON_DOOR:
case E_BLOCK_IRON_TRAPDOOR:
case E_BLOCK_JUNGLE_DOOR:
@@ -276,6 +311,7 @@ private:
case E_BLOCK_REDSTONE_REPEATER_ON:
case E_BLOCK_BLOCK_OF_REDSTONE:
case E_BLOCK_ACTIVE_COMPARATOR:
+ case E_BLOCK_INACTIVE_COMPARATOR:
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
case E_BLOCK_STONE_PRESSURE_PLATE: