summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@outlook.com>2020-07-29 21:15:09 +0200
committerTiger Wang <ziwei.tiger@outlook.com>2020-08-04 19:15:18 +0200
commitadb86a75dac91a210149fc28b1dbf5225896f66c (patch)
treeb62bcb6cba06726081c598879d84018f7a39c824
parentUse std::queue for the block tick queue (diff)
downloadcuberite-adb86a75dac91a210149fc28b1dbf5225896f66c.tar
cuberite-adb86a75dac91a210149fc28b1dbf5225896f66c.tar.gz
cuberite-adb86a75dac91a210149fc28b1dbf5225896f66c.tar.bz2
cuberite-adb86a75dac91a210149fc28b1dbf5225896f66c.tar.lz
cuberite-adb86a75dac91a210149fc28b1dbf5225896f66c.tar.xz
cuberite-adb86a75dac91a210149fc28b1dbf5225896f66c.tar.zst
cuberite-adb86a75dac91a210149fc28b1dbf5225896f66c.zip
-rw-r--r--src/Simulator/DelayedFluidSimulator.cpp30
-rw-r--r--src/Simulator/DelayedFluidSimulator.h3
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp85
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h3
-rw-r--r--src/Simulator/Simulator.h19
-rw-r--r--src/Simulator/SimulatorManager.cpp24
-rw-r--r--src/Simulator/SimulatorManager.h4
7 files changed, 93 insertions, 75 deletions
diff --git a/src/Simulator/DelayedFluidSimulator.cpp b/src/Simulator/DelayedFluidSimulator.cpp
index b27e34e5f..ec1918617 100644
--- a/src/Simulator/DelayedFluidSimulator.cpp
+++ b/src/Simulator/DelayedFluidSimulator.cpp
@@ -78,21 +78,6 @@ cDelayedFluidSimulator::cDelayedFluidSimulator(cWorld & a_World, BLOCKTYPE a_Flu
-void cDelayedFluidSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
-{
- if (!cChunkDef::IsValidHeight(a_Position.y))
- {
- // Not inside the world (may happen when rclk with a full bucket - the client sends Y = -1)
- return;
- }
-
- Super::WakeUp(a_Chunk, a_Position, a_Block);
-}
-
-
-
-
-
void cDelayedFluidSimulator::Simulate(float a_Dt)
{
m_AddSlotNum = m_SimSlotNum;
@@ -153,3 +138,18 @@ void cDelayedFluidSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLO
++m_TotalBlocks;
}
+
+
+
+
+
+void cDelayedFluidSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
+{
+ if (!cChunkDef::IsValidHeight(a_Position.y))
+ {
+ // Not inside the world (may happen when rclk with a full bucket - the client sends Y = -1)
+ return;
+ }
+
+ AddBlock(a_Chunk, a_Position, a_Block);
+}
diff --git a/src/Simulator/DelayedFluidSimulator.h b/src/Simulator/DelayedFluidSimulator.h
index e307e4ad7..3022c9753 100644
--- a/src/Simulator/DelayedFluidSimulator.h
+++ b/src/Simulator/DelayedFluidSimulator.h
@@ -54,13 +54,12 @@ public:
cDelayedFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, int a_TickDelay);
- virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override;
-
protected:
virtual void Simulate(float a_Dt) override;
virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override;
virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override;
+ virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override;
virtual cFluidSimulatorData * CreateChunkData(void) override { return new cDelayedFluidSimulatorChunkData(m_TickDelay); }
int m_TickDelay; // Count of the m_Slots array in each ChunkData
diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp
index f2c8b7e65..e3177e420 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp
+++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp
@@ -128,53 +128,6 @@ std::unique_ptr<cRedstoneHandler> cIncrementalRedstoneSimulator::CreateComponent
-void cIncrementalRedstoneSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
-{
- Super::WakeUp(a_Chunk, a_Position, a_Block);
-
- auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData());
-
- // Never update blocks without a handler:
- if (GetComponentHandler(a_Block) == nullptr)
- {
- ChunkData.ErasePowerData(a_Position);
- return;
- }
-
- // Only update others if there is a redstone device nearby
- for (int x = -1; x < 2; ++x)
- {
- for (int y = -1; y < 2; ++y)
- {
- if (!cChunkDef::IsValidHeight(a_Position.y + y))
- {
- continue;
- }
-
- for (int z = -1; z < 2; ++z)
- {
- auto CheckPos = a_Position + Vector3i{ x, y, z };
- BLOCKTYPE Block;
- NIBBLETYPE Meta;
-
- // If we can't read the block, assume it is a mechanism
- if (
- !a_Chunk.UnboundedRelGetBlock(CheckPos, Block, Meta) ||
- IsRedstone(Block)
- )
- {
- ChunkData.WakeUp(a_Position);
- return;
- }
- }
- }
- }
-}
-
-
-
-
-
void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
{
auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk->GetRedstoneSimulatorData());
@@ -273,13 +226,16 @@ void cIncrementalRedstoneSimulator::ProcessWorkItem(cChunk & Chunk, cChunk & Tic
void cIncrementalRedstoneSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
{
- auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData());
-
if (!IsRedstone(a_Block))
{
return;
}
+ // Never update blocks without a handler:
+ ASSERT(GetComponentHandler(a_Block) != nullptr);
+
+ auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData());
+
if (IsAlwaysTicked(a_Block))
{
ChunkData.AlwaysTickedPositions.emplace(a_Position);
@@ -288,3 +244,34 @@ void cIncrementalRedstoneSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Positi
// Always update redstone devices:
ChunkData.WakeUp(a_Position);
}
+
+
+
+
+
+void cIncrementalRedstoneSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
+{
+ // Having WakeUp called on us directly means someone called SetBlock (or WakeUp)
+ // Since the simulator never does this, something external changed. Clear cached data:
+ static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData())->ErasePowerData(a_Position);
+
+ // Queue the block, in case the set block was redstone:
+ AddBlock(a_Chunk, a_Position, a_Block);
+}
+
+
+
+
+
+void cIncrementalRedstoneSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, Vector3i a_Offset, BLOCKTYPE a_Block)
+{
+ // This is an automatic cross-coords wakeup by cSimulatorManager
+ // There is no need to erase power data; if a component was destroyed the 3-arg WakeUp will handle it
+
+ AddBlock(a_Chunk, a_Position, a_Block);
+
+ // The only thing to do go one block farther than this cross-coord, in the direction of Offset
+ // in order to notify linked-powered positions that there was a change
+
+ // TODO: use a_Offset, exclude a_Position and a_Position - a_Offset
+}
diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h
index 44c63a5a8..e20880b7a 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h
@@ -147,7 +147,6 @@ public:
private:
- virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override;
virtual void Simulate(float Dt) override {};
virtual void SimulateChunk(std::chrono::milliseconds Dt, int ChunkX, int ChunkZ, cChunk * Chunk) override;
@@ -159,6 +158,8 @@ private:
}
virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override;
+ virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override;
+ virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, Vector3i a_Offset, BLOCKTYPE a_Block) override;
private:
diff --git a/src/Simulator/Simulator.h b/src/Simulator/Simulator.h
index aacd5f52f..f82b579cb 100644
--- a/src/Simulator/Simulator.h
+++ b/src/Simulator/Simulator.h
@@ -13,9 +13,9 @@ class cCuboid;
Each descendant provides an implementation of what needs to be done on each world tick.
The descendant may choose to do all processing in a single call for the entire world (Simulate())
or do per-chunk calculations (SimulateChunk()).
-Whenever a block is changed, the WakeUp() or WakeUpArea() functions are called to notify all simulators.
-The functions add all affected blocks and all their direct neighbors using the AddBlock() function. The simulator
-may update its internal state based on this call. */
+Whenever a block is changed, the WakeUp() functions are called to notify all simulators by the simulator manager.
+The functions are invoked to add all affected blocks and their direct neighbors using the AddBlock() function.
+The simulator may update its internal state based on this call. */
class cSimulator
{
public:
@@ -27,7 +27,18 @@ public:
virtual ~cSimulator() {}
- virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block);
+ // Contains our direct adjacents
+ inline static std::array<Vector3i, 6> AdjacentOffsets
+ {
+ {
+ { 1, 0, 0 },
+ { -1, 0, 0 },
+ { 0, 1, 0 },
+ { 0, -1, 0 },
+ { 0, 0, 1 },
+ { 0, 0, -1 },
+ }
+ };
protected:
diff --git a/src/Simulator/SimulatorManager.cpp b/src/Simulator/SimulatorManager.cpp
index f10c285e0..07b4a7214 100644
--- a/src/Simulator/SimulatorManager.cpp
+++ b/src/Simulator/SimulatorManager.cpp
@@ -63,9 +63,29 @@ void cSimulatorManager::WakeUp(cChunk & a_Chunk, Vector3i a_Position)
{
ASSERT(a_Chunk.IsValid());
- for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr)
+ for (const auto Item : m_Simulators)
+ {
+ Item.first->WakeUp(a_Chunk, a_Position, a_Chunk.GetBlock(a_Position));
+ }
+
+ for (const auto Offset : cSimulator::AdjacentOffsets)
{
- itr->first->WakeUp(a_Chunk, a_Position, a_Chunk.GetBlock(a_Position));
+ auto Relative = a_Position + Offset;
+ auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Relative);
+
+ if ((Chunk == nullptr) || !Chunk->IsValid())
+ {
+ continue;
+ }
+
+ // Stored block to give to simulators for performance
+ // Since they all need this we save them querying it themselves
+ const auto Block = Chunk->GetBlock(Relative);
+
+ for (const auto Item : m_Simulators)
+ {
+ Item.first->WakeUp(*Chunk, Relative, Offset, Block);
+ }
}
}
diff --git a/src/Simulator/SimulatorManager.h b/src/Simulator/SimulatorManager.h
index b5f54381c..4594bd7d6 100644
--- a/src/Simulator/SimulatorManager.h
+++ b/src/Simulator/SimulatorManager.h
@@ -38,8 +38,8 @@ public:
/** 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. */
void SimulateChunk(std::chrono::milliseconds a_DT, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk);
- /* Called when a single block changes, wakes all simulators up for the block.
- The simulator implementation may also decide to wake the block's face-neighbors or blocks farther away. */
+ /* Called when a single block changes, wakes all simulators up for the block and its face-neighbors.
+ The simulator implementation may also decide to wake blocks farther away. */
void WakeUp(cChunk & a_Chunk, Vector3i a_Position);
/** Does the same processing as WakeUp, but for all blocks within the specified area.