Add WakeUp/AddBlock distinction
* WakeUp is for singular changes (block breaking for example). The simulator should check blocks around the position and discover other affected blocks as it sees fit * AddBlock is for when you know a whole area is to be updated; chunk loading, or area wakeups for example + Prepares for correct handling of destroyed blocks after removal of SolidBlockHandler in the redstone simulator
This commit is contained in:
parent
6d7b83a69d
commit
99856df686
@ -1330,7 +1330,7 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Wake up all simulators for the area, so that water and lava flows and sand falls into the blasted holes (FS #391):
|
// Wake up all simulators for the area, so that water and lava flows and sand falls into the blasted holes (FS #391):
|
||||||
m_World->GetSimulatorManager()->WakeUpArea(cCuboid(
|
m_World->GetSimulatorManager()->WakeUp(cCuboid(
|
||||||
{bx - ExplosionSizeInt - 1, MinY, bz - ExplosionSizeInt - 1},
|
{bx - ExplosionSizeInt - 1, MinY, bz - ExplosionSizeInt - 1},
|
||||||
{bx + ExplosionSizeInt + 1, MaxY, bz + ExplosionSizeInt + 1}
|
{bx + ExplosionSizeInt + 1, MaxY, bz + ExplosionSizeInt + 1}
|
||||||
));
|
));
|
||||||
|
@ -111,7 +111,6 @@ void cMultiVersionProtocol::HandleIncomingDataInRecognitionStage(cClientHandle &
|
|||||||
// The protocol recogniser succesfully identified, switch mode:
|
// The protocol recogniser succesfully identified, switch mode:
|
||||||
HandleIncomingData = [this](cClientHandle &, const std::string_view a_In)
|
HandleIncomingData = [this](cClientHandle &, const std::string_view a_In)
|
||||||
{
|
{
|
||||||
// TODO: make it take our a_ReceivedData
|
|
||||||
m_Protocol->DataReceived(m_Buffer, a_In.data(), a_In.size());
|
m_Protocol->DataReceived(m_Buffer, a_In.data(), a_In.size());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -78,19 +78,8 @@ cDelayedFluidSimulator::cDelayedFluidSimulator(cWorld & a_World, BLOCKTYPE a_Flu
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cDelayedFluidSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
void cDelayedFluidSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
|
||||||
{
|
{
|
||||||
if ((a_Block.y < 0) || (a_Block.y >= cChunkDef::Height))
|
|
||||||
{
|
|
||||||
// Not inside the world (may happen when rclk with a full bucket - the client sends Y = -1)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((a_Chunk == nullptr) || !a_Chunk->IsValid())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RelX = a_Block.x - a_Chunk->GetPosX() * cChunkDef::Width;
|
int RelX = a_Block.x - a_Chunk->GetPosX() * cChunkDef::Width;
|
||||||
int RelZ = a_Block.z - a_Chunk->GetPosZ() * cChunkDef::Width;
|
int RelZ = a_Block.z - a_Chunk->GetPosZ() * cChunkDef::Width;
|
||||||
BLOCKTYPE BlockType = a_Chunk->GetBlock(RelX, a_Block.y, RelZ);
|
BLOCKTYPE BlockType = a_Chunk->GetBlock(RelX, a_Block.y, RelZ);
|
||||||
@ -156,3 +145,14 @@ void cDelayedFluidSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
@ -55,7 +55,8 @@ 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);
|
||||||
|
|
||||||
// cSimulator overrides:
|
// cSimulator overrides:
|
||||||
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override;
|
virtual void WakeUp(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 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 cFluidSimulatorData * CreateChunkData(void) override { return new cDelayedFluidSimulatorChunkData(m_TickDelay); }
|
virtual cFluidSimulatorData * CreateChunkData(void) override { return new cDelayedFluidSimulatorChunkData(m_TickDelay); }
|
||||||
|
@ -239,7 +239,7 @@ bool cFireSimulator::DoesBurnForever(BLOCKTYPE a_BlockType)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cFireSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
void cFireSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
|
||||||
{
|
{
|
||||||
if ((a_Chunk == nullptr) || !a_Chunk->IsValid())
|
if ((a_Chunk == nullptr) || !a_Chunk->IsValid())
|
||||||
{
|
{
|
||||||
|
@ -43,8 +43,7 @@ protected:
|
|||||||
/** Chance [0..100000] of a fuel burning out being replaced by a new fire block instead of an air block */
|
/** Chance [0..100000] of a fuel burning out being replaced by a new fire block instead of an air block */
|
||||||
int m_ReplaceFuelChance;
|
int m_ReplaceFuelChance;
|
||||||
|
|
||||||
|
virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override;
|
||||||
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override;
|
|
||||||
|
|
||||||
/** Returns the time [msec] after which the specified fire block is stepped again; based on surrounding fuels */
|
/** Returns the time [msec] after which the specified fire block is stepped again; based on surrounding fuels */
|
||||||
int GetBurnStepTime(cChunk * a_Chunk, Vector3i a_RelPos);
|
int GetBurnStepTime(cChunk * a_Chunk, Vector3i a_RelPos);
|
||||||
|
@ -128,6 +128,53 @@ 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());
|
||||||
@ -224,7 +271,7 @@ void cIncrementalRedstoneSimulator::ProcessWorkItem(cChunk & Chunk, cChunk & Tic
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cIncrementalRedstoneSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
void cIncrementalRedstoneSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
|
||||||
{
|
{
|
||||||
// Can't inspect block, ignore:
|
// Can't inspect block, ignore:
|
||||||
if ((a_Chunk == nullptr) || !a_Chunk->IsValid())
|
if ((a_Chunk == nullptr) || !a_Chunk->IsValid())
|
||||||
@ -236,50 +283,16 @@ void cIncrementalRedstoneSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
|||||||
const auto Relative = cChunkDef::AbsoluteToRelative(a_Block, a_Chunk->GetPos());
|
const auto Relative = cChunkDef::AbsoluteToRelative(a_Block, a_Chunk->GetPos());
|
||||||
const auto CurrentBlock = a_Chunk->GetBlock(Relative);
|
const auto CurrentBlock = a_Chunk->GetBlock(Relative);
|
||||||
|
|
||||||
// Always update redstone devices
|
if (!IsRedstone(CurrentBlock))
|
||||||
if (IsRedstone(CurrentBlock))
|
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsAlwaysTicked(CurrentBlock))
|
if (IsAlwaysTicked(CurrentBlock))
|
||||||
{
|
{
|
||||||
ChunkData.AlwaysTickedPositions.emplace(Relative);
|
ChunkData.AlwaysTickedPositions.emplace(Relative);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always update redstone devices:
|
||||||
ChunkData.WakeUp(Relative);
|
ChunkData.WakeUp(Relative);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Never update blocks without a handler
|
|
||||||
if (GetComponentHandler(CurrentBlock) == nullptr)
|
|
||||||
{
|
|
||||||
ChunkData.ErasePowerData(Relative);
|
|
||||||
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(Relative.y + y))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int z = -1; z < 2; ++z)
|
|
||||||
{
|
|
||||||
auto CheckPos = Relative + 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(Relative);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,10 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
@ -36,7 +40,7 @@ public:
|
|||||||
return IsRedstone(a_BlockType);
|
return IsRedstone(a_BlockType);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override;
|
virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override;
|
||||||
|
|
||||||
/** Returns if a block is a mechanism (something that accepts power and does something)
|
/** Returns if a block is a mechanism (something that accepts power and does something)
|
||||||
Used by torches to determine if they will power a block */
|
Used by torches to determine if they will power a block */
|
||||||
|
@ -28,7 +28,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cSimulator overrides:
|
// cSimulator overrides:
|
||||||
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override
|
virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override
|
||||||
{
|
{
|
||||||
UNUSED(a_Block);
|
UNUSED(a_Block);
|
||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
|
@ -28,7 +28,7 @@ public:
|
|||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
}
|
}
|
||||||
virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType) override { return false; }
|
virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType) override { return false; }
|
||||||
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override
|
virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override
|
||||||
{
|
{
|
||||||
UNUSED(a_Block);
|
UNUSED(a_Block);
|
||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
|
@ -31,11 +31,6 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Simulate(float a_Dt) = 0;
|
|
||||||
virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) = 0;
|
|
||||||
virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) = 0;
|
|
||||||
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) = 0;
|
|
||||||
|
|
||||||
virtual cRedstoneSimulatorChunkData * CreateChunkData() = 0;
|
virtual cRedstoneSimulatorChunkData * CreateChunkData() = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -97,7 +97,7 @@ bool cSandSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cSandSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
void cSandSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
|
||||||
{
|
{
|
||||||
if ((a_Chunk == nullptr) || !a_Chunk->IsValid())
|
if ((a_Chunk == nullptr) || !a_Chunk->IsValid())
|
||||||
{
|
{
|
||||||
|
@ -27,6 +27,7 @@ class cSandSimulator :
|
|||||||
public cSimulator
|
public cSimulator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
cSandSimulator(cWorld & a_World, cIniFile & a_IniFile);
|
cSandSimulator(cWorld & a_World, cIniFile & a_IniFile);
|
||||||
|
|
||||||
// cSimulator overrides:
|
// cSimulator overrides:
|
||||||
@ -56,11 +57,12 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
bool m_IsInstantFall; // If set to true, blocks don't fall using cFallingBlock entity, but instantly instead
|
bool m_IsInstantFall; // If set to true, blocks don't fall using cFallingBlock entity, but instantly instead
|
||||||
|
|
||||||
int m_TotalBlocks; // Total number of blocks currently in the queue for simulating
|
int m_TotalBlocks; // Total number of blocks currently in the queue for simulating
|
||||||
|
|
||||||
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override;
|
virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override;
|
||||||
|
|
||||||
/** Performs the instant fall of the block - removes it from top, Finishes it at the bottom */
|
/** Performs the instant fall of the block - removes it from top, Finishes it at the bottom */
|
||||||
void DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
|
void DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
|
||||||
|
@ -1,33 +1,38 @@
|
|||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
|
|
||||||
#include "../World.h"
|
#include "Simulator.h"
|
||||||
#include "../Defines.h"
|
|
||||||
#include "../Chunk.h"
|
#include "../Chunk.h"
|
||||||
#include "../Cuboid.h"
|
#include "../Cuboid.h"
|
||||||
|
#include "../World.h"
|
||||||
#ifdef __clang__
|
|
||||||
#pragma clang diagnostic ignored "-Wweak-template-vtables"
|
|
||||||
#endif // __clang__
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "Simulator.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cSimulator::WakeUp(Vector3i a_Block, cChunk * a_Chunk)
|
void cSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
|
||||||
{
|
{
|
||||||
AddBlock(a_Block, a_Chunk);
|
ASSERT(a_Chunk.IsValid());
|
||||||
|
|
||||||
|
AddBlock(a_Chunk, a_Position, a_Block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cSimulator::WakeUpArea(const cCuboid & a_Area)
|
void cSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, Vector3i a_Offset, BLOCKTYPE a_Block)
|
||||||
|
{
|
||||||
|
ASSERT(a_Chunk.IsValid());
|
||||||
|
|
||||||
|
WakeUp(a_Chunk, a_Position, a_Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSimulator::WakeUp(const cCuboid & a_Area)
|
||||||
{
|
{
|
||||||
cCuboid area(a_Area);
|
cCuboid area(a_Area);
|
||||||
area.Sort();
|
area.Sort();
|
||||||
@ -60,7 +65,8 @@ void cSimulator::WakeUpArea(const cCuboid & a_Area)
|
|||||||
{
|
{
|
||||||
for (int x = startX; x <= endX; ++x)
|
for (int x = startX; x <= endX; ++x)
|
||||||
{
|
{
|
||||||
AddBlock({x, y, z}, &a_CBChunk);
|
const auto Position = cChunkDef::AbsoluteToRelative({ x, y, z });
|
||||||
|
AddBlock(a_CBChunk, Position, a_CBChunk.GetBlock(Position));
|
||||||
} // for x
|
} // for x
|
||||||
} // for z
|
} // for z
|
||||||
} // for y
|
} // for y
|
||||||
@ -70,7 +76,3 @@ void cSimulator::WakeUpArea(const cCuboid & a_Area)
|
|||||||
} // for cx
|
} // for cx
|
||||||
} // for cz
|
} // for cz
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ may update its internal state based on this call. */
|
|||||||
class cSimulator
|
class cSimulator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
cSimulator(cWorld & a_World)
|
cSimulator(cWorld & a_World)
|
||||||
: m_World(a_World)
|
: m_World(a_World)
|
||||||
{
|
{
|
||||||
@ -26,10 +27,13 @@ public:
|
|||||||
|
|
||||||
virtual ~cSimulator() {}
|
virtual ~cSimulator() {}
|
||||||
|
|
||||||
/** Called in each tick, a_Dt is the time passed since the last tick, in msec */
|
virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block);
|
||||||
virtual void Simulate(float a_Dt) = 0;
|
|
||||||
|
|
||||||
/** 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 */
|
protected:
|
||||||
|
|
||||||
|
friend class cChunk; // Calls AddBlock() in its WakeUpSimulators() function, to speed things up
|
||||||
|
|
||||||
|
virtual void Simulate(float a_Dt) = 0;
|
||||||
virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
|
virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
|
||||||
{
|
{
|
||||||
UNUSED(a_Dt);
|
UNUSED(a_Dt);
|
||||||
@ -38,28 +42,26 @@ public:
|
|||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called when a block changes */
|
|
||||||
void WakeUp(Vector3i a_Block, cChunk * a_Chunk);
|
|
||||||
|
|
||||||
/** Does the same processing as WakeUp, but for all blocks within the specified area.
|
|
||||||
Has better performance than calling WakeUp for each block individually, due to neighbor-checking.
|
|
||||||
All chunks intersected by the area should be valid (outputs a warning if not).
|
|
||||||
Note that, unlike WakeUp(), this call adds blocks not only face-neighboring, but also edge-neighboring and
|
|
||||||
corner-neighboring the specified area. So far none of the simulators care about that. */
|
|
||||||
void WakeUpArea(const cCuboid & a_Area);
|
|
||||||
|
|
||||||
/** Returns true if the specified block type is "interesting" for this simulator. */
|
/** Returns true if the specified block type is "interesting" for this simulator. */
|
||||||
virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) = 0;
|
virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) = 0;
|
||||||
|
|
||||||
protected:
|
/** Called to simulate a new block. Unlike WakeUp this function will perform minimal checking.
|
||||||
friend class cChunk; // Calls AddBlock() in its WakeUpSimulators() function, to speed things up
|
It queues the block to be simulated as fast as possible, only making sure that the block type IsAllowedBlock. */
|
||||||
|
virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) = 0;
|
||||||
|
|
||||||
/** Called to simulate a new block */
|
/** Called to simulate a single new block, typically as a result of a single block break or change.
|
||||||
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) = 0;
|
The simulator implementation may decide to perform additional checks or maintain consistency of internal state
|
||||||
|
before the block is added to the simulate queue. */
|
||||||
|
virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block);
|
||||||
|
|
||||||
|
/** Called to simulate a single block, synthesised by the simulator manager.
|
||||||
|
The position represents the adjacents of the block that was actually changed, with the offset used given.
|
||||||
|
Simulators may use this information to update additional blocks that were affected by the change, or queue
|
||||||
|
farther, extra-adjacents blocks to be updated. The simulator manager calls this overload after the 3-argument WakeUp. */
|
||||||
|
virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, Vector3i a_Offset, BLOCKTYPE a_Block);
|
||||||
|
|
||||||
|
/** Called to simulate an area by the manager, delegated to cSimulator to avoid virtual calls in tight loops. */
|
||||||
|
void WakeUp(const cCuboid & a_Area);
|
||||||
|
|
||||||
cWorld & m_World;
|
cWorld & m_World;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||||
|
|
||||||
#include "SimulatorManager.h"
|
#include "SimulatorManager.h"
|
||||||
|
#include "../Chunk.h"
|
||||||
#include "../World.h"
|
#include "../World.h"
|
||||||
|
|
||||||
|
|
||||||
@ -58,11 +59,13 @@ void cSimulatorManager::SimulateChunk(std::chrono::milliseconds a_Dt, int a_Chun
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cSimulatorManager::WakeUp(Vector3i a_Block, cChunk * a_Chunk)
|
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 (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr)
|
||||||
{
|
{
|
||||||
itr->first->WakeUp(a_Block, a_Chunk);
|
itr->first->WakeUp(a_Chunk, a_Position, a_Chunk.GetBlock(a_Position));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,11 +73,11 @@ void cSimulatorManager::WakeUp(Vector3i a_Block, cChunk * a_Chunk)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cSimulatorManager::WakeUpArea(const cCuboid & a_Area)
|
void cSimulatorManager::WakeUp(const cCuboid & a_Area)
|
||||||
{
|
{
|
||||||
for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr)
|
for (const auto Item : m_Simulators)
|
||||||
{
|
{
|
||||||
itr->first->WakeUpArea(a_Area);
|
Item.first->WakeUp(a_Area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +89,3 @@ void cSimulatorManager::RegisterSimulator(cSimulator * a_Simulator, int a_Rate)
|
|||||||
{
|
{
|
||||||
m_Simulators.push_back(std::make_pair(a_Simulator, a_Rate));
|
m_Simulators.push_back(std::make_pair(a_Simulator, a_Rate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,26 +28,30 @@ class cWorld;
|
|||||||
class cSimulatorManager
|
class cSimulatorManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
cSimulatorManager(cWorld & a_World);
|
cSimulatorManager(cWorld & a_World);
|
||||||
~cSimulatorManager();
|
~cSimulatorManager();
|
||||||
|
|
||||||
|
/** Called in each tick, a_Dt is the time passed since the last tick, in msec. */
|
||||||
void Simulate(float a_Dt);
|
void Simulate(float a_Dt);
|
||||||
|
|
||||||
|
/** 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 and its face-neighbors. */
|
/* Called when a single block changes, wakes all simulators up for the block.
|
||||||
void WakeUp(Vector3i a_Block, cChunk * a_Chunk);
|
The simulator implementation may also decide to wake the block's face-neighbors or 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.
|
/** Does the same processing as WakeUp, but for all blocks within the specified area.
|
||||||
Has better performance than calling WakeUp for each block individually, due to neighbor-checking.
|
Has better performance than calling WakeUp for each block individually, due to neighbor-checking.
|
||||||
All chunks intersected by the area should be valid (outputs a warning if not).
|
All chunks intersected by the area should be valid (outputs a warning if not).
|
||||||
Note that, unlike WakeUp(), this call adds blocks not only face-neighboring, but also edge-neighboring and
|
Note that, unlike WakeUp(), this call adds blocks not only face-neighboring, but also edge-neighboring and corner-neighboring the specified area. */
|
||||||
corner-neighboring the specified area. So far none of the simulators care about that. */
|
void WakeUp(const cCuboid & a_Area);
|
||||||
void WakeUpArea(const cCuboid & a_Area);
|
|
||||||
|
|
||||||
void RegisterSimulator(cSimulator * a_Simulator, int a_Rate); // Takes ownership of the simulator object!
|
void RegisterSimulator(cSimulator * a_Simulator, int a_Rate); // Takes ownership of the simulator object!
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
typedef std::vector <std::pair<cSimulator *, int> > cSimulators;
|
typedef std::vector <std::pair<cSimulator *, int> > cSimulators;
|
||||||
|
|
||||||
cWorld & m_World;
|
cWorld & m_World;
|
||||||
|
@ -22,7 +22,7 @@ cVaporizeFluidSimulator::cVaporizeFluidSimulator(cWorld & a_World, BLOCKTYPE a_F
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cVaporizeFluidSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
void cVaporizeFluidSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
|
||||||
{
|
{
|
||||||
if (a_Chunk == nullptr)
|
if (a_Chunk == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,7 @@ public:
|
|||||||
cVaporizeFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid);
|
cVaporizeFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid);
|
||||||
|
|
||||||
// cSimulator overrides:
|
// cSimulator overrides:
|
||||||
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override;
|
virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override;
|
||||||
virtual void Simulate(float a_Dt) override;
|
virtual void Simulate(float a_Dt) override;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
@ -1327,7 +1327,7 @@ void cWorld::WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_MinB
|
|||||||
|
|
||||||
void cWorld::WakeUpSimulatorsInArea(const cCuboid & a_Area)
|
void cWorld::WakeUpSimulatorsInArea(const cCuboid & a_Area)
|
||||||
{
|
{
|
||||||
m_SimulatorManager->WakeUpArea(a_Area);
|
m_SimulatorManager->WakeUp(a_Area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user