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:
parent
b205d233bd
commit
adb86a75da
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user