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)
|
void cDelayedFluidSimulator::Simulate(float a_Dt)
|
||||||
{
|
{
|
||||||
m_AddSlotNum = m_SimSlotNum;
|
m_AddSlotNum = m_SimSlotNum;
|
||||||
@ -153,3 +138,18 @@ void cDelayedFluidSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLO
|
|||||||
|
|
||||||
++m_TotalBlocks;
|
++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);
|
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:
|
protected:
|
||||||
|
|
||||||
virtual void Simulate(float a_Dt) override;
|
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 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 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); }
|
virtual cFluidSimulatorData * CreateChunkData(void) override { return new cDelayedFluidSimulatorChunkData(m_TickDelay); }
|
||||||
|
|
||||||
int m_TickDelay; // Count of the m_Slots array in each ChunkData
|
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)
|
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());
|
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)
|
void cIncrementalRedstoneSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
|
||||||
{
|
{
|
||||||
auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData());
|
|
||||||
|
|
||||||
if (!IsRedstone(a_Block))
|
if (!IsRedstone(a_Block))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Never update blocks without a handler:
|
||||||
|
ASSERT(GetComponentHandler(a_Block) != nullptr);
|
||||||
|
|
||||||
|
auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData());
|
||||||
|
|
||||||
if (IsAlwaysTicked(a_Block))
|
if (IsAlwaysTicked(a_Block))
|
||||||
{
|
{
|
||||||
ChunkData.AlwaysTickedPositions.emplace(a_Position);
|
ChunkData.AlwaysTickedPositions.emplace(a_Position);
|
||||||
@ -288,3 +244,34 @@ void cIncrementalRedstoneSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Positi
|
|||||||
// Always update redstone devices:
|
// Always update redstone devices:
|
||||||
ChunkData.WakeUp(a_Position);
|
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:
|
private:
|
||||||
|
|
||||||
virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override;
|
|
||||||
virtual void Simulate(float Dt) override {};
|
virtual void Simulate(float Dt) override {};
|
||||||
virtual void SimulateChunk(std::chrono::milliseconds Dt, int ChunkX, int ChunkZ, cChunk * Chunk) 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 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:
|
private:
|
||||||
|
|
||||||
|
@ -13,9 +13,9 @@ class cCuboid;
|
|||||||
Each descendant provides an implementation of what needs to be done on each world tick.
|
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())
|
The descendant may choose to do all processing in a single call for the entire world (Simulate())
|
||||||
or do per-chunk calculations (SimulateChunk()).
|
or do per-chunk calculations (SimulateChunk()).
|
||||||
Whenever a block is changed, the WakeUp() or WakeUpArea() functions are called to notify all simulators.
|
Whenever a block is changed, the WakeUp() functions are called to notify all simulators by the simulator manager.
|
||||||
The functions add all affected blocks and all their direct neighbors using the AddBlock() function. The simulator
|
The functions are invoked to add all affected blocks and their direct neighbors using the AddBlock() function.
|
||||||
may update its internal state based on this call. */
|
The simulator may update its internal state based on this call. */
|
||||||
class cSimulator
|
class cSimulator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -27,7 +27,18 @@ public:
|
|||||||
|
|
||||||
virtual ~cSimulator() {}
|
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:
|
protected:
|
||||||
|
|
||||||
|
@ -63,9 +63,29 @@ void cSimulatorManager::WakeUp(cChunk & a_Chunk, Vector3i a_Position)
|
|||||||
{
|
{
|
||||||
ASSERT(a_Chunk.IsValid());
|
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. */
|
/** 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);
|
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.
|
/* 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 the block's face-neighbors or blocks farther away. */
|
The simulator implementation may also decide to wake blocks farther away. */
|
||||||
void WakeUp(cChunk & a_Chunk, Vector3i a_Position);
|
void WakeUp(cChunk & a_Chunk, Vector3i a_Position);
|
||||||
|
|
||||||
/** Does the same processing as WakeUp, but for all blocks within the specified area.
|
/** Does the same processing as WakeUp, but for all blocks within the specified area.
|
||||||
|
Loading…
Reference in New Issue
Block a user