1
0
Fork 0

Do not GetBlock individually in simulators

* Have the simulator manager get the block and pass it on
+ Add new overload for WakeUp, called when the manager wakes face positions
This commit is contained in:
Tiger Wang 2020-07-29 20:15:09 +01:00
parent b205d233bd
commit adb86a75da
7 changed files with 93 additions and 75 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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
}

View File

@ -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:

View File

@ -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:

View File

@ -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)
{
itr->first->WakeUp(a_Chunk, a_Position, a_Chunk.GetBlock(a_Position));
Item.first->WakeUp(a_Chunk, a_Position, a_Chunk.GetBlock(a_Position));
}
for (const auto Offset : cSimulator::AdjacentOffsets)
{
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);
}
}
}

View File

@ -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.